当使用python函数构建器时,Scons忽略了依赖性跟踪的环境

时间:2017-12-10 17:55:54

标签: python scons

我在scons 2.5.1中遇到的问题与通过环境将参数传递给基于python的构建器有关。 当调用普通构建器时,如果传入的任何源文件或环境变量发生更改,则结果似乎标记为脏。 当使用python函数构建器(这里描述http://scons.org/doc/1.2.0/HTML/scons-user/x3524.html)时,似乎scons只关心源文件。

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

$this->app->register(\Tymon\JWTAuth\Providers\LumenServiceProvider::class);

以下是使用不同参数运行scons脚本的结果:

#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'))

在使用普通构建器的情况下,它会在MSG更改时检测到结果是脏的(并且在MSG保持不变时清理)但在python命令版本中,即使MSG已更改,它也会认为它是最新的。

解决方法是将我的构建器脚本放在一个单独的python脚本中,并使用环境依赖项作为命令行参数调用该python脚本,但它似乎很复杂。

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

是否有比我上面描述的更简单的解决方法,我可以将我的构建函数保存在SConstruct文件中?

1 个答案:

答案 0 :(得分:1)

这是预期的行为,因为SCons无法知道函数(如所写的)取决于MESSAGE。

但是,如果您阅读联机帮助页 http://scons.org/doc/production/HTML/scons-man.html

你会看到这个(Under" Action Objects"):

  

变量也可以由varl​​ist = keyword参数指定;   如果两者都存在,则将它们合并。无论何时,这都是必要的   希望在特定的构造变量时重建目标   变化。对于字符串操作,通常不需要这样做,因为扩展了   变量通常是命令行的一部分,但可能需要   如果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'))

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