带有部分生成的源文件和变体构建的 SCons:如何正确设置依赖关系

问题描述 投票:0回答:1

我正面临一个奇怪的 SCons 问题,尽管看起来我并没有试图实现任何奇怪的事情。情况是这样的(不幸的是,我们使用了许多专有的 SCons 包装器,所以我不能分享代码,至少因为它无论如何都不清楚):

  1. 有一个调用生成器包装函数的 SConscript。它获取参数文件的名称并返回生成的 SCons.Node.FS.File 对象的列表。
  2. 然后,这个 SConscript 调用一个带有 variant_dir (duplicate=0) 的附属 SConscript。生成的文件对象列表作为导出参数传递。
  3. 目的是构建一个共享库的变体,每个变体都在其特定的子文件夹(变体目录)中成功构建。
  4. 虽然对生成的文件有特殊的态度
    • 它们生成一次并保存到父文件夹(所有变体子目录都位于此文件夹中)。我们更愿意生成它们一次,以确保所有变体都使用相同的生成源。
    • 我们不希望它们被编译一次,因为变体构建可能使用不同的定义,因此即使源相同,目标文件也应该明显不同。
    • 这意味着我们生成了一些文件,我们需要它们成为库构建的一部分,并且我们需要它们的目标文件在每个构建变体的变体目录中。

令人惊讶的是,这是我很长一段时间都无法实现的事情,因为我无法保持 SCons 逻辑的一致性。

最简单的一致方法是将生成的文件列表作为库的源。从依赖关系的角度来看,这看起来工作正常; SCons 识别生成的文件何时更新,从而重新编译它们并重新链接库。问题是SCons把生成文件的结果对象放到了生成文件所在的父目录下。因此,它们不是使生成的二进制文件损坏的每个变体目标文件。

然而,我找不到任何方法来构建生成文件的目标文件的单独副本。如果我将生成的文件复制到父 SConscript 中的变体目录 (Command(,,(Copy))),SCons 可以在文件再次生成之前复制这些文件。如果我尝试在附属的 SConscript 中填充生成的文件,库构建器无法识别这些源文件的更新,也不会重新编译它们。

我尝试了很多不同的选项和显式依赖关系,但是文件之间的依赖关系构建链在不同的构建场景中看起来并不确定。我真的很感激任何新的想法。这不是 SCons 具有什么功能的问题,而是如何将功能绑定在一起以达到目标的问题。到现在为止,我还没有找到办法,但我简直不敢相信我的情况太特殊了。

python c++ scons
1个回答
0
投票

我假设你的变体 dir SConscript 看起来像这样

Import(['env','list_of_generated_files'])
env.SharedLibary('magically_delicious',list_of_generated_files)

假设是这样,这就是 SCons 在幕后所做的事情。

  1. SharedLibary 唯一有效的源文件是目标文件、共享库和静态库(我相当确定)。并且绝对 C/C++ 源文件不是有效的源文件。但是 SCons 知道如何将 C/C++ 文件构建到目标文件中。

  2. 在引擎盖下 SCons 做这样的事情:

    list_of_objects=[env.SharedObject(s) for s in list_of_generated_files]

由于生成的文件在父目录中,默认情况下(换句话说,当没有指定明确的目标时),SCons 将始终在指定的源文件旁边构建目标文件。

因此在变体目录中生成你的库,在父目录中生成对象。

那么我们如何解决这个问题呢? 我们基本上重现了 SCons 在幕后所做的事情,但这次我们指定了目标。

Import(['env','list_of_generated_files'])
list_of_objects = [env.SharedObject('./${SOURCE.filebase}$SHOBJSUFFIX',s) for s in list_of_generated_files]
env.SharedLibary('magically_delicious',list_of_objects)

请注意,您可以在目标文件规范中使用 subst() 的字符串。

这里有一堆这样的例子

$TARGET              => sub/dir/file.x
${TARGET.base}       => sub/dir/file
${TARGET.dir}        => sub/dir
${TARGET.file}       => file.x
${TARGET.filebase}   => file
${TARGET.suffix}     => .x
${TARGET.abspath}    => /top/dir/sub/dir/file.x
${TARGET.relpath}    => sub/dir/file.x

$TARGET              => ../dir2/file.x
${TARGET.abspath}    => /top/dir2/file.x
${TARGET.relpath}    => ../dir2/file.x

您可以在联机帮助页中阅读更多相关信息 试试上面的方法,让我们知道这是否适合您

© www.soinside.com 2019 - 2024. All rights reserved.