测试目标存在

时间:2012-02-02 03:11:57

标签: scons

我有一个SCons文件,它调用其他人来构建程序的不同变体。 遗憾的是,其中一些变体(AKA较低的SConscripts)需要通过调用外部程序来构建库。

# /SConstruct
<...>
subdirs = ['variant1', 'variant2', 'variant3']
for subdir in subdirs:
    SConscript(dirs=subdir, src_dir=subdir)

# /variant1/SConscript
localEnv = env.Clone() # Duplicates the global Environment so we may modify it without problems
localEnv.Command('../libs/generated.so', '', 'someexternalscript')
<...>

# /variant2/SConscript
localEnv = env.Clone() # Duplicates the global Environment so we may modify it without problems
localEnv.Command('../libs/generated.so', '', 'someexternalscript')
<...>

这会发出警告:

scons: warning: Two different environments were specified for target ../libs/generated.so
                but they appear to have the same action: someexternalscript

这当然是正确的,但我不知道如何在变种 SConscripts 中检查目标是否存在。 而且由于其他人可能会在稍后调用SConscripts,因此我不能依赖全局变量。

4 个答案:

答案 0 :(得分:0)

因此,SConscript1将构建:../ libs / generate.so,SConscript2将构建相同的../libs/generated.so - 相同的目标文件。

您不能使用2个相同的目标(SConscript1和SConscript2中的../libs/generated.so)。您必须为SConscripts中的一个Command指定不同的目标。例如,对于SConscript2 Command(../ libs / generated2.so。

  

但我不知道如何检查目标的存在   变体SConscripts

为什么需要检查它?如果scons检测到目标需要构建它将构建。如果要更改任何源文件,您还可以为run命令设置其他依赖性以生成.so。

genLibCmd = localEnv.Command('../libs/generated.so', '', 'someexternalscript')
Depends(genLibCmd, [ listOfSrcThatSomeExternalScriptUse ])

对于测试现有目标,您可以使用scons类File:

File('#libs/generated.so').exists()

但是,我确定 - 如果你两次构建相同的目标,你的错误Sconscripts。

答案 1 :(得分:0)

很难知道你是否真的认为 ../ libs / generated.so 是构建的一部分。

如果这是一个您期望在构建之外存在的库,但您想确保它。我建议您使用Configure来确保库存在,如果不存在,您可能会失败或运行someexternalscript来纠正这种情况。

config = Configure(env)
if not config.CheckLib("generated.so") make_generated_so()

你如何实际make_generated_so()取决于你想要怎么做,你可能会把它作为你的构建的一部分,或者只是在配置阶段运行shell脚本。

另一方面,如果您将../libs/generated.so视为构建的一部分,则必须创建此目标一次,并使依赖目标依赖于此.so文件,您可以通过包含generated.so节点作为env.Program("someprogram",target)中目标的一部分或只是env.Depends(sometarget,"generated.so")

答案 2 :(得分:0)

In this situation, I do not clone the environment for this particular process. And I don't think you need to in your example, as that Command does not change anything in env. You can clone afterwards. If this target ends up being called from different SConscripts, with their env already cloned, have a single environment accessible for this purpose.

答案 3 :(得分:0)

如果这是字面上的代码,我会看到两种方法来删除警告:

# /SConstruct
<...>
subdirs = ['variant1', 'variant2', 'variant3']
for subdir in subdirs:
    SConscript(dirs=subdir, src_dir=subdir)

# /variant1/SConscript
localEnv = env.Clone() # Duplicates the global Environment so we may modify it without problems
localEnv.Command('../libs/generated.so', '', 'someexternalscript')
<...>

# /variant2/SConscript
localEnv = env.Clone() # Duplicates the global Environment so we may modify it without problems
localEnv.Command('../libs/generated.so', '', 'someexternalscript')
<...>

另请注意,实际上没有两个SConscripts(一个在variant1中,一个在variant2中,它是相同的SConscript。

首先:在克隆之前调用一些externalscript:

# /variant*/SConscript
env.Command('../libs/generated.so', '', 'someexternalscript')
localEnv = env.Clone() # Duplicates the global Environment so we may modify it without problems
<...>

其次:添加一些条件逻辑并通过SConscript调用传递一个标志:

# /SConstruct
<...>
subdirs = ['variant1', 'variant2', 'variant3']
for subdir in subdirs:
    build_generated = (subdir == 'variant1')
    SConscript(dirs=subdir, src_dir=subdir, exports=['env','build_generated'])

# /variant*/SConscript
Import('build_generated','env')
localEnv = env.Clone() # Duplicates the global Environment so we may modify it without problems
if build_generated:
    localEnv.Command('../libs/generated.so', '', 'someexternalscript')
<...>

最后:如果您总是希望调用此脚本,则可以将调用放在SConstruct中。

此外,为什么要将目标的来源列为''?

该目标永远不会改变,至少源应该是someexternalscript