8

我希望 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

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

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

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

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

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

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

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

4

3 回答 3

3

我建议在 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() 的调用一起工作

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

于 2013-05-14T14:46:16.153 回答
1

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

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' 是关键。不知道为什么需要这样做。我会称之为错误,但我猜它的特色(基于你得到的错误反馈..)

干杯,

于 2017-03-15T16:27:09.457 回答
0

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

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

这是我所拥有的证明这种工作的东西,

S构造:

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

源/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自动处理上述内容的文件中,但我仍然必须提供一个绝对文件名,这很不方便。

于 2021-11-17T03:17:15.067 回答