scons 忽略文件目标路径?

scons is ignoring file destination path?

我发现 scons 2.3.0 有一些奇怪的行为。也许我只是做错了™,但这似乎应该是明智的...

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,并重新创建 non-versioned 符号链接。 (base_dirlibsrc 是绝对路径,尽管 base_dir 指向 scons 输出树内。)

这对于单个目标来说工作正常,但复制或链接永远不会发生在任何其他目标上。我尝试使用 env.Depends 添加显式依赖项;我试过将结果分配给变量并在以后使用它;似乎没有任何效果。

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

如果我为每个目的地添加一个别名目标,并在命令的结果中使其成为 Depends,那么两个别名目标都会出现在树中,但只有第一个目标具有 sub-items;第二个出现的总是没有children.

即使我在命令行上明确指定第二个别名目标,它也什么都不做,并且在 --tree 中不打印 children。只有 re-ordering 目的地我才能让它做任何事情——然后另一个当然停止工作。

基本上,对于任何给定的输入文件,它似乎只能执行一个操作,并且完全忽略任何多次使用源文件的尝试,甚至没有警告。这看起来很疯狂。

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

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

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

解决方法是改用方括号:

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

这会为每个目的地正确执行内部循环。