使用Python功能构建器时,SCON会忽略依赖关系跟踪的环境



我在SCONS 2.5.1中有一个问题,与通过环境传递到基于Python的构建器的参数有关。当称为普通的构建器时,如果任何源文件或环境变量已更改,则结果似乎被标记为肮脏。使用Python函数构建器时(此处http://scons.org/doc/1.2.0/html/scons-user/x3524.html)似乎SCONS似乎只关心源文件。

这是它失败的最小人工示例。这是通过环境传递参数并使用Shell将其写入目标文件的两个实现。一个实现只是一个命令字符串,另一个实现是使用Python子过程在Python函数中调用它。我用一个参数来选择要使用的建筑商。

#SConstruct
import subprocess
def echo_fun(env, source, target):
    subprocess.check_call('echo %s > %s' % (env['MESSAGE'], str(target[0])), shell= True)
    return None
env = Environment(BUILDERS = {'echo' : Builder(action='echo $MESSAGE > $TARGET'),
                              'echo_py': Builder(action=echo_fun),
                              })
build_fn = env.echo_py if ARGUMENTS.get('USE_PYTHON', False) else env.echo
build_fn(['test.file'], [], MESSAGE = ARGUMENTS.get('MSG', 'None'))

这是运行具有不同参数的SCONS脚本的结果:

PS C:workcodesconsissue> scons -Q MSG=Hello
echo Hello > test.file
PS C:workcodesconsissue> scons -Q MSG=Hello
scons: `.' is up to date.
PS C:workcodesconsissue> scons -Q MSG=HelloAgain
echo HelloAgain > test.file
PS C:workcodesconsissue> del .test.file
PS C:workcodesconsissue> scons -Q MSG=Hello -Q USE_PYTHON=True
echo_fun(["test.file"], [])
PS C:workcodesconsissue> scons -Q MSG=Hello -Q USE_PYTHON=True
scons: `.' is up to date.
PS C:workcodesconsissue> scons -Q MSG=HelloAgain -Q USE_PYTHON=True
scons: `.' is up to date.

在使用普通构建器的情况下,它检测到当味精更改时结果是脏的(并且在MSG保持不变时清洁),但是在Python命令版本中,即使更改了MSG,也会考虑到最新。p>解决方法是将我的构建器脚本放在单独的python脚本中,并将该python脚本与环境依赖关系作为命令行参数进行调用,但似乎令人费解。

这是预期的行为还是错误?

是否比上面描述的一个更容易在Sconstruct File中保留构建功能?

这是预期的行为,因为Scons无法知道该功能(如书面)取决于消息。

但是,如果您阅读了该手册http://scons.org/doc/production/html/scons-man.html

您会看到此(在"动作对象"下):

变量也可以通过varlist =关键字参数指定; 如果两者都存在,则将它们合并。每当你有必要 希望在特定的施工变量时重建目标 变化。随着扩展,弦乐操作通常不需要 变量通常是命令行的一部分,但可能需要 如果python函数动作使用施工变量的值 生成命令行时。

...
# Alternatively, use a keyword argument.
a = Action(build_it, varlist=['XXX'])

因此,如果您重写为:

#SConstruct
import subprocess
def echo_fun(env, source, target):
    subprocess.check_call('echo %s > %s' % (env['MESSAGE'], str(target[0])), shell= True)
    return None
env = Environment(BUILDERS = {'echo' : Builder(action='echo $MESSAGE > $TARGET'),
                              'echo_py': Builder(action=Action(echo_fun, varlist=['MESSAGE'])),
                              })
build_fn = env.echo_py if ARGUMENTS.get('USE_PYTHON', False) else env.echo
build_fn(['test.file'], [], MESSAGE = ARGUMENTS.get('MSG', 'None'))

它应该按照您的意愿行事。

最新更新