SCons: как вызвать самостоятельно определенную функцию python в скрипте scons и создать правильную зависимость - PullRequest
5 голосов
/ 22 ноября 2011

Я пишу функцию Python, такую ​​как замена строк и вызывается в скрипте scons.

def Replace(env, filename, old, new):
    with open(filename,"r+") as f:
    d = f.read()
    d = d.replace(old, new)
    f.truncate(0)
    f.seek(0)
    f.write(d)
    f.close()
env.AddMethod(Replace,'Replace')

В SConscript

lib = env.SharedLibrary('lib', object, extra_libs)
tmp = env.Command([],[],[env.Replace(somefile, 'A', 'b')] )
env.Depends(tmp,lib )

Что я ожидаю, так это запустить метод Replace () после сборки библиотеки. но scons всегда запускают Replace () в первой фразе парсинга скрипта. кажется, мне не хватает какой-то зависимости.

1 Ответ

4 голосов
/ 23 ноября 2011

Я полагаю, что вы, вероятно, ищете компоновщиков, которые выполняют функции Python .

Хитрость в том, что SCons на самом деле не хочет работать так, как вы его заставляетек.Действия сборки должны быть повторяемыми и неразрушающими, в вашем коде вы фактически уничтожаете исходное содержимое somefile.Вместо этого вы можете использовать парадигму target / source и некоторый файл шаблона для достижения того же результата.

import os
import re

def replace_action(target, source, env):
    # NB. this is a pretty sloppy way to write a builder, but
    #     for things that are used internally or infrequently
    #     it should be more than sufficient
    assert( len(target) == 1 )
    assert( len(source) == 1 )
    srcf = str(source[0])
    dstf = str(target[0])
    with open(srcf, "r") as f:
        contents = f.read()
        # In cases where this builder fails, check to make sure you
        # have correctly added REPLST to your environment
        for old, new in env['REPLST']:
            contents = re.sub( old, new, contents )
        with open( dstf, "w") as outf:
            outf.write(contents)

replace_builder = Builder(action = replace_action)

env = Environment( ENV = os.environ )
env.Append( BUILDERS = {'Replace' : replace_builder } )
b = env.Replace( 'somefile', ['somefile.tmpl'], REPLST=[('A','b')] )
lib = env.SharedLibrary('lib', object + [b], extra_libs )

Обратите внимание, что в моем тестировании функция замены не очень хорошо работала с многострочными данными, поэтому я только что перешел на использование полных регулярных выражений (re.sub).Это, вероятно, медленнее, но предлагает значительно большую гибкость.

...