【问题标题】:In scons, how can I inject a target to be built?在 scons 中,如何注入要构建的目标?
【发布时间】:2010-10-16 23:46:51
【问题描述】:

我想注入一个“清理”目标,该目标取决于在它关闭之前完成的许多其他目标以及 gzip 的一些日志文件。重要的是我不要过早使用 gzip,因为这会导致某些工具失败。

如何注入清理目标以供 Scons 执行?

例如我有目标 foo 和 bar。我想注入一个名为“cleanup”的新自定义目标,它依赖于 foo 和 bar,并在它们都完成后运行,而无需用户指定

% scons foo cleanup

我希望他们输入:

% scons foo

但是让 scons 像用户输入一样执行

% scons foo cleanup

我已尝试创建清理目标并将其附加到 sys.argv,但似乎 scons 在到达我的代码时已经处理了 sys.argv,因此它不会处理我的“清理”目标手动追加到 sys.argv。

【问题讨论】:

    标签: scons


    【解决方案1】:

    您不应该使用_Add_Targets 或未记录的功能,您只需将清理目标添加到BUILD_TARGETS

    from SCons.Script import BUILD_TARGETS
    BUILD_TARGETS.append('cleanup')
    

    如果您使用此记录的目标列表而不是未记录的函数,则 scons 在记账时不会感到困惑。这个评论区可以在SCons/Script/__init__.py找到:

    # BUILD_TARGETS can be modified in the SConscript files.  If so, we
    # want to treat the modified BUILD_TARGETS list as if they specified
    # targets on the command line.  To do that, though, we need to know if
    # BUILD_TARGETS was modified through "official" APIs or by hand.  We do
    # this by updating two lists in parallel, the documented BUILD_TARGETS
    # list, above, and this internal _build_plus_default targets list which
    # should only have "official" API changes.  Then Script/Main.py can
    # compare these two afterwards to figure out if the user added their
    # own targets to BUILD_TARGETS.
    

    所以我猜它是为了改变 BUILD_TARGETS 而不是调用内部辅助函数

    【讨论】:

    • 这很好用!但后续问题是 - 当我要添加的目标来自扫描仪时,我该怎么做? IE。它在运行时生成。我尝试添加到 BUILD_TARGETS,但这没有任何效果。很可能 SCons 在开始构建后不会检查该列表。
    【解决方案2】:

    一种方法是让 gzip 工具依赖于日志文件的输出。例如,如果我们有这个 C 文件,'hello.c':

    #include <stdio.h>
    int main()
    {
        printf("hello world\n");
        return 0;
    }
    

    还有这个 SConstruct 文件:

    #!/usr/bin/python
    env = Environment()
    hello = env.Program('hello', 'hello.c')
    env.Default(hello)
    env.Append(BUILDERS={'CreateLog':
        Builder(action='$SOURCE.abspath > $TARGET', suffix='.log')})
    log = env.CreateLog('hello', hello)
    zipped_log = env.Zip('logs.zip', log)
    env.Alias('cleanup', zipped_log)
    

    然后运行“scons cleanup”将以正确的顺序运行所需的步骤:

    gcc -o hello.o -c hello.c
    gcc -o hello hello.o
    ./hello > hello.log
    zip(["logs.zip"], ["hello.log"])
    

    这与您指定的不完全一致,但此示例与您的要求之间的唯一区别是“清理”是实际创建 zip 文件的步骤,因此这是您必须运行的步骤。它的依赖关系(运行生成日志的程序,创建该程序)是自动计算的。您现在可以按如下方式添加别名“foo”以获得所需的输出:

    env.Alias('foo', zipped_log)
    

    【讨论】:

    • 感谢您的想法。问题是,我正在做一个构建流程,其中包含我无法完全控制的部分,因此我无法预先注册要压缩的日志文件,因为我不知道正在创建的所有日志文件。跨度>
    【解决方案3】:

    在 SCons 1.1.0.d20081104 版本中,您可以使用私有内部 SCons 方法:

    SCons.Script._Add_Targets( [ 'MY_INJECTED_TARGET' ] )
    

    如果用户键入:

    % scons foo bar 
    

    上面的代码 sn-p 将导致 SCons 的行为就像用户输入了一样:

    % scons foo bar MY_INJECTED_TARGET
    

    【讨论】:

    • 未记录的功能 FTW! :-) 当我遇到这些“无法解决”的问题时,我发现我经常只是在寻找 SCons 的来源......
    • 使用 --random 标志时会中断吗?据我所知,用户提供的目标的构建顺序是未定义的。
    • 我注入了目标,但依赖于其他目标,因此它非常适合图表。即使您执行-random,它也只会随机化并发步骤——而不是相互依赖的步骤。在依赖的目标构建命令开始执行之前,依赖关系总是得到满足。
    • 不要使用未记录的“功能”;尤其是当有一个记录的功能要使用时:BUILD_TARGETS.append('cleanup')
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多