【问题标题】:SCons code generation and VariantDirSCons 代码生成和 VariantDir
【发布时间】:2013-05-08 20:50:49
【问题描述】:

我希望 SCons 在我的 src/ 目录中为我生成一些源文件,然后在我的构建目录 build/variantX 中将它们构建为任何其他源文件。

这是我的 SCons 文件:

import SCons

def my_builder(env, target, source):
    # do stuff
    pass

env = Environment()
env.VariantDir('build/variant1/', 'src', duplicate=0)
env.Command('src/foobar.cc', 'src/foobar.input', action=my_builder)
env.Program('bin/test', [
    'build/variant1/foobar.cc',
    'build/variant1/test.cc',
    ])

此错误并显示以下消息:

找不到源src/foobar.cc,目标build/variant1/foobar.o需要

考虑到我确实提供了构建src/foobar.cc 的命令,我认为这是不正确的。

现在,我尝试了一些解决方法:

  • 如果我将 Program 中的 build/variant1/foobar.cc 替换为 src/foobar.cc,它确实有效,但显然 foobar.o 是在 src/ 而不是 build/variant1 中创建的

  • 如果我将命令中的src/foobar.cc 替换为build/variant1/foobar.cc,它确实有效,但我希望在src/ 中生成代码; (也因为除非duplicate=1,否则包含目录中的相对路径之类的东西将不起作用)

  • 如果duplicate=1,我会收到类似的错误消息,但这次提到了变体目录:

    找不到源build/variant1/foobar.cc,目标build/variant1/foobar.o需要

有没有办法解决这个问题?这是 SCons 中的限制/错误,还是我这边存在根本性的误解?

【问题讨论】:

  • 你有没有找到这个问题的答案?我面临着非常相似的事情。

标签: code-generation scons


【解决方案1】:

我建议在 Command() 和 Program() 调用之间创建显式依赖关系,如下所示:

target1 = env.Command('src/foobar.cc', 'src/foobar.input', action=my_builder)
target2 = env.Program('bin/test', [
                      'build/variant1/foobar.cc',
                      'build/variant1/test.cc',
                      ])
Depends(target2, target1)
# This should work too
# Depends(target2, "src/foobar.cc")

或者您可以将 Command() 中的目标指定为 Program() 源的一部分,如下所示:

target1 = env.Command('src/foobar.cc', 'src/foobar.input', action=my_builder)
env.Program('bin/test', [
            target1,
            'build/variant1/test.cc',
            ])

我还没有测试过这个,所以我不确定它如何与对 VariantDir() 的调用一起工作

Here 是一些关于使用 SCons 生成源代码的额外信息。

【讨论】:

  • 嗨,布雷迪,感谢您的帮助。您的第一个想法确实不错,但似乎没有任何效果。第二个似乎与我的第一个解决方法实际上相同:它可以工作,但它在源目录而不是变体目录中构建它。该链接看起来很有趣,我现在正在浏览它。
  • @UncleZeiv 我真的很惊讶 Depends() 函数不起作用。尝试使用实际文件名,我会更新答案。
  • --tree=all 告诉我这会导致 bin/test 取决于“正确的”src/foobar.cc(又取决于 src/foobar.input),但 build/variant1/foobar.o 仍然取决于“悬空”src/foobar.cc,它不依赖于任何东西,并且(打开摆弄 scons 源代码)似乎甚至没有附加任何构建器。我真的开始认为这是一个 Scons 错误。
  • 我认为 VariantDir 从根本上破坏了依赖关系树中的某些内容。我设法想出了一个非常简单的损坏测试用例,它根本不涉及代码生成。感兴趣的可以看看这里:scons.tigris.org/issues/show_bug.cgi?id=2908
  • @UncleZeiv 直接调用 VariantDir() 函数的另一种替代方法是创建分层构建,您可以使用 SConscript() 函数并使用 variant_dir 参数。这更直接,并且没有 VariantDir() 调用的奇怪副作用。我想这取决于你的项目结构。
【解决方案2】:

我知道这已经有一段时间了,但我碰到了同一堵墙。对“测试用例”和解决方案(见下文)稍作修改,代码如下:

import SCons

env = Environment()
env.VariantDir('build/variant1/', 'src', duplicate=0)
env.Command('src/foobar.cc', 'src/foobar.input', action="cp src/foobar.input src/foobar.cc", shell=True )
env.Depends("build/variant1/foobar.cc", "src/foobar.cc")
env.Program('bin/test', [
'build/variant1/foobar.cc',
])

在 'variantdir-source' 到 'generated-source' 上添加的 'env.Depends' 是关键。不知道为什么需要这样做。我会称之为错误,但我猜它的特点(基于你得到的错误反馈..)

干杯,

【讨论】:

  • 这为我解决了。好像是个bug,scons应该能找出文件的变种版本是与生成的源相关的目标。
【解决方案3】:

仅供参考,我找到了在使用 SConscript(variant_dir=...) 时有效的另一个解决方案。在我的项目中,我没有单独的“src”目录,我确实有分层的 SConscript 文件,理想情况下,我宁愿不要在任何地方命名构建目录,因为它取决于正在构建的目标。

关键是 (a) 直接依赖于 File 而不是字符串文件名,这似乎会混淆依赖关系树 [这解决了依赖关系问题,如上所述],以及 (b) 显式创建 Object其名称会导致它在 build 目录中生成,而不是在源目录中[解决 .o-in-src/ 问题]。

这就是我所拥有的证明这个工作原理的东西,

S构造:

env = Environment()
Export('env')
SConscript('src/SConscript', variant_dir='build/variant1', duplicate=False)

src/SConscript:

Import('env')
s = env.Command('#/src/foobar.cc', 'foobar.input', action="cp $SOURCES $TARGETS", shell=True )
o = Object(target="foobar.o", source=s)
env.Program('#/bin/test', [o])

建筑给了我,

$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cp src/foobar.input src/foobar.cc
g++ -o build/variant1/foobar.o -c src/foobar.cc
g++ -o bin/test build/variant1/foobar.o
scons: done building targets.

主要的缺点是您必须从树的根目录“root”目标源文件而不是提供相对名称,才能在源目录而不是 build/variant 目录中生成它。

任何关于如何更优雅地做到这一点的建议都会很棒!我目前将它包裹在 Builder 中,它会自动处理上述内容,但我仍然必须提供绝对文件名,这很不方便。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    • 2014-03-06
    • 2011-01-22
    • 2022-01-07
    相关资源
    最近更新 更多