scons - 如何编写具有难以预测的动态源的 SCons 脚本?

标签 scons

我正在尝试建立一个涉及代码生成器的构建系统。在生成器运行之前,生成的确切文件是未知的,但我希望能够通过模式匹配运行进一步的构建步骤(在具有某些扩展名的所有文件上运行一些程序)。这可能吗?

这里涉及代码生成的一些答案似乎假设输出是已知的或创建了生成文件的列表。这对我来说并非不可能,但我想避免它,因为它会让事情变得更加复杂。

https://bitbucket.org/scons/scons/wiki/DynamicSourceGenerator似乎表明可以在构建器操作期间添加其他目标,但是虽然我可以运行构建并列出生成的文件,但引入的任何构建步骤都不会运行。

https://bitbucket.org/scons/scons/wiki/NonDeterministicDependencies使用扫描仪添加构建步骤。我将 glob(...) 放入扫描仪中,它成功检测到生成的文件,但在实际运行依赖步骤之前,这些文件被莫名其妙地删除了。

这个用例可能吗?为什么 SCons 会删除我生成的文件?

一个玩具示例

源(SConscript 中引用的文件)

一个示例生成器,构造 3 个文件(构建系统不容易知道)并将它们放入参数文件夹中

echo "echo 1" > $1/gen1.txt
echo "echo 2" > $1/gen2.txt
echo "echo 3" > $1/gen3.txt

S构造

只需设置一个variant_dir

SConscript('SConscript', variant_dir='build')

SConscript

目标是:

  1. “编译”生成器(在这个玩具示例中,只需复制一个名为“source”的文件并添加执行权限
  2. 运行“已编译”生成器(“源”是生成文件的脚本)
  3. 按扩展名对每个生成的文件执行一些操作。此示例仅对它们运行“编译”复制操作(为了简单起见)。
<小时/>
env = Environment()

env.Append(BUILDERS = {'ExampleCompiler' :
                       Builder(action=[Copy('$TARGET', '$SOURCE'),
                                       Chmod('$TARGET', 0755)])})

generator = env.ExampleCompiler('generator', 'source')

env.Append(BUILDERS = {'GeneratorRun' :
                       Builder(action=[Mkdir('$TARGET'),
                                       '$SOURCE $TARGET'])})

generated_dir = env.GeneratorRun(Dir('generated'), generator)

到这里一切都很好,构建系统提前明确知道所有目标。

<小时/>

尝试使用此代码块来遍历生成的文件会导致 SCons 删除(!!)生成的文件:

for generated in generated_dir[0].glob('*.txt'):
  generated_run = env.ExampleCompiler(generated.abspath + '.sh', generated)
<小时/>

尝试使用操作来更新构建树会导致其他操作无法运行:

def generated_scanner(target, source, env):
  for generated in source[0].glob('*.txt'):
    print "scanned " + generated.abspath
    generated_target = env.ExampleCompiler(generated.abspath + '.sh', generated)
    Alias('TopLevelAlias', generated_target)

env.Append(BUILDERS = {'GeneratedOperation' :
                       Builder(action=[generated_scanner])})

dummy = env.GeneratedOperation(generated_dir[0].File('#dummy'), generated_dir)
Alias('TopLevelAlias', dummy)

上面的动态源生成器指南中建议了别名操作,但似乎没有做任何事情。打印确实执行并指示操作已运行。

最佳答案

使用 SCons 可以在特殊文件扩展名上运行某些构建模式。对于 C/CPP 文件,这是首选方案,例如:

env = Environment()
env.Program('main', Glob('*.cpp'))

SCons 作为构建系统的主要任务是做最少的工作,使所有目标都是最新的。这使得上面描述的用例变得复杂,因为不清楚如何达到不添加生成文件并且构建所有目标的“稳定”情况。 直接使用简单的 Python 脚本可能会更好...我真的不明白在这种情况下使用 SCons(或任何其他构建系统)是关键任务。

编辑:

在某些时候,您必须告诉 SCons 有关创建的文件(上面示例中的 *.txt)的信息,并且为了正确跟踪所有依赖项,*.txt 列表code> 文件必须完整。这是 SCons 中发射器的任务,它负责返回生成器调用的目标文件和源文件的列表。请注意,这些文件在 SCons 的“解析”阶段不必实际存在。另请看看我对 Scons: create late targets 的回答,其中有更多细节。

一旦你有了合适的发射器(另请参阅 https://bitbucket.org/scons/scons/wiki/ToolsForFools ,“使用发射器”),你应该能够使用 Glob('*.txt') 调用,它将检测并自动跟踪您创建的文件。

最后,在我们的“演讲和幻灯片”页面 (https://bitbucket.org/scons/scons/wiki/TalksAndSlides) 上,您可以找到我在 PyCon FR.2014 中的演讲“为什么 SCons 不慢”,其中简要解释了 SCons 内部的工作原理。这可能有助于更好地理解这个问题并提出完整的解决方案。

关于scons - 如何编写具有难以预测的动态源的 SCons 脚本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35168126/

相关文章:

c++ - 如何使用 scons 2.3 visual express 2012 构建 C++ 项目?

builder - SCons 自定义构建器 - 使用多个文件构建并输出一个文件

build - 配置 scons 以在 Windows 命令提示符中使用 posix 参数的问题

scons - 如何使生成的文件依赖于Scons中的java类

performance - Environment.Clone 窃取启动时间

python - Scons 无法导入 _args_from_interpreter_flags

c - 如何根据编译器类型在 SConstruct for C 编译器中设置选项?

c++ - 使用带有 g++ 和 gtest 的 scons 制作单元测试二进制文件

java - "jar"命令何时会拒绝将类添加到 .jar 文件?

build - 什么是好的 RPM 构建工具?