2017-02-27 99 views
0

我从scons 2.3.0看到一些奇怪的行为。也许我只是做错了™,但这似乎像它应该是明智的......scons忽略文件目标路径?

destinations = [base_dir+'lib/', base_dir+'tree/usr/local/lib/'] 
boost_ver = '1.63.0' 
boost_libs = (x for x in env['LIBS'] if 'boost_' in x) 
# eg. 'boost_thread', 'boost_system' 

for dest in destinations: 
    for lib_name in boost_libs: 
     lib_so = 'lib'+lib_name+'.so' 
     lib_so_ver = lib_so+'.'+boost_ver 

     env.Command(dest+lib_so_ver, libsrc+lib_so_ver, Copy("$TARGET","$SOURCE")) 
     env.Command(dest+lib_so, dest+lib_so_ver, SymLink) 

问题的关键是采取命名的图书馆,并复制它们libsrc到每个destinations的,重新创建非版本化的符号链接。 (base_dirlibsrc是绝对路径,虽然base_dir点scons的输出树中。)

这对单个目标工作正常,但复制或链接永远不会发生任何其他目的地。我试过用env.Depends添加明确的依赖关系;我试着将结果赋值给变量并稍后使用;似乎没有任何工作。

如果我看一下--tree的输出,总是只列出第一个目标中的文件;任何后续的永远不会。 (如果我更改它们列出的顺序,那么现在先列出的是唯一的列表。)

如果我为每个目标添加一个别名目标,并将其作为Depends作为命令的结果,则两个别名目标出现在树中,但只有第一个具有子项;无论哪个出现第二个总是没有孩子。

即使我在命令行中明确指定第二个别名目标,它也不会执行任何操作,并且不会在--tree中打印任何子项。只有通过重新排序目的地,我才能让它做任何事 - 然后当然另一个停止工作。

基本上,它看起来像只有一个动作可以用于任何给定的输入文件,并且完全忽略多次使用源文件的任何尝试,甚至没有多少警告。这看起来很疯狂。

+0

你可以告诉我更多关于'SymLink'方法(?)在做什么以及为什么它似乎不需要任何参数?我无法在UserGuide/sources中找到具有此名称的方法/工厂...既不适用于SCons 2.3.0,也不适用于最新的2.5.1。 – dirkbaechle

+0

这只是一个本地定义的python函数('def SymLink(target,source,env)'),它听起来像。它使用标准scons [自定义动作扩展机制](http://scons.org/doc/2.3.0/HTML/scons-user.html#chap-builders-commands),并且与此问题无关。 – Miral

+0

澄清:复制和符号链接均适用于单个目标。复制和符号链接都不能用于任何其他目的地,因为scons似乎忽略了额外的“命令”。关于为什么发生这种情况,我唯一的理论是,源与所有目的地之间的每对中的第一个命令相同。但这似乎是一个愚蠢的失败原因,如果这确实是原因。 – Miral

回答

0

原来这不是Scons的问题,而是Python。真正的问题™是这样的定义:

boost_libs = (x for x in env['LIBS'] if 'boost_' in x) 

无论出于何种原因(显然我蟒福不够高),这会导致在内部for循环上面的第一个目的地只执行一次。

的解决方案是使用方括号来代替:

boost_libs = [x for x in env['LIBS'] if 'boost_' in x] 

这正确地执行用于每个目的地的内部循环。

+0

仅供参考,我现在知道原因 - 带圆括号的语法是一个生成器,它只能迭代一次。与方括号相反,它是一个可以迭代多次的列表。只是为了更加混乱,元组(也使用圆括号)也可以迭代很多次。 – Miral

+0

(关于元组的令人困惑的事情是,代码之前已经读过'('boost_thread','boost_system')',并且这个按预期工作 - 但是在保留括号的情况下给它一个表达式,所以这是我的错因为不知道生成器,显然,但是之前的开发人员通过使用元组而不是列表导致混淆。) – Miral