【问题标题】:scons: changing compilation flags for a single source filescons:更改单个源文件的编译标志
【发布时间】:2013-10-04 18:39:39
【问题描述】:

我有一个相当复杂的 scons 系统,其中包含多个子目录、许多库和可执行文件。 目前,每个 SConscript 都有自己的克隆环境,因此我可以在每个 SConscript 的基础上轻松更改 CFLAGS (或任何其他 wariable),但我想在每个目标甚至每个对象文件中更改它目标。

我创建了一个简单的示例 SConscript 和 SConstruct 来解释问题,如下。

S构造:

env = Environment()
env['CFLAGS'] = '-O2'
env.SConscript('SConscript', 'env')

SConscript:

Import('env')
env=env.Clone()
env.Program('foo', ['foo.c', 'bar.c'])

如果我运行 scons,则 foo.c 和 bar.c 都使用 -O2 标志进行编译。我可以通过在 SConscript 中添加 env['CFLAGS'] = '...' 轻松更改 SConscript 范围内的标志,但是假设我想用 -O2 编译 foo.c,但要使用完整调试 -O0 -g 编译 bar.c。我该怎么做(以最简单的方式)?

该示例使用 gcc,但我想要可以与任何编译器一起使用的东西。

这种情况经常发生在对性能敏感的项目中,在没有优化的情况下编译所有内容会导致无法接受的性能,但需要调试单个文件(或其中的一个子集)。

【问题讨论】:

    标签: scons


    【解决方案1】:

    最简单的单行答案可能只是将您的 Program 行替换为:

    env.Program('foo', ['foo.c', env.Object('bar.c', CFLAGS='-g')])
    

    因为程序可以获取对象节点以及源文件,并且您可以覆盖任何构建器中的任何构造变量(这里,我们在对象构建器调用中覆盖 CFLAGS)。如果您想为清楚起见将 Object 拆分为自己的行:

    debug_objs = env.Object('bar.c', CFLAGS='-g')
    env.Program('foo', ['foo.c', debug_objs])
    

    当然,将其发挥到极致,您就会得到像上面显示的 Avatar33 这样的系统。

    【讨论】:

    • 感谢@GaryO,这是最简单的解决方案,正是我想要的!对 SConscript 进行了一行更改以添加一些标志,暂时仅用于调试。不知怎的,我在 scons 手册中找不到这个,谢谢,我会尽快尝试!
    • 经过测试,有效,很简单,正是我想要的,谢谢!
    • 一个更有趣的问题是如何制作一个随每个目标而变化的选项,例如如果您想使用 /Fd{fname} 选项根据目标名称命名 .pdb 文件。
    【解决方案2】:

    我想这在 scons 中比在 make 中要难一些,你可以只清理所需的目标并使用调试标志重新构建。然后它会重建一个特定的对象。

    具体项目的解决方案取决于项目的规模以及开发人员准备投入多少精力。 所以这里有一个粗略的解决方案,你在命令行中指定你想用调试而不优化编译的源文件,其余的将用 -O2 编译。

    在您的 SConstruct 中增加一行来获取我们想要通过命令行选项调试编译的源文件:

        env = Environment()
        env['CFLAGS'] = '-O2'
        AddOption('--debug-targets', dest='debug-targets', type='string')
        env.SConscript('SConscript', 'env')
    

    现在在 SConscript 文件中:

        Import('env')
        env=env.Clone()
        debug_env = env.Clone()
        debug_env['CFLAGS'] = '-g -O0'
    
        normal_src = ['foo.c', 'bar.c']
        debug_src = []
    
        #Add src specified via the command line to the debug build 
        if GetOption('debug-targets'):
            for x in GetOption('debug-targets').split(','):
                 if x in normal_src:
                    normal_src.remove(x)
                    debug_src.append(x)
    
        normal_obj = env.Object(normal_src)
        debug_obj = debug_env.Object(debug_src)
        all_obj = normal_obj + debug_obj
        env.Program('foo', all_obj)
    

    在没有调试目标标志的情况下运行我们的 scons:

        scons -Q      
        gcc -o bar.o -c -O2 bar.c
        gcc -o foo.o -c -O2 foo.c
        gcc -o foo foo.o bar.o
    

    但是现在我们要编译带有调试信息的 bar.c:

        scons -Q --debug-targets=bar.c 
        gcc -o bar.o -c -g -O0 bar.c
        gcc -o foo foo.o bar.o
    

    因此,这会为您的构建系统增加一些复杂性,但是如果您不需要像那样从命令行指定调试目标,那么开发人员显然可以从 normal_src 列表中剪切和过去的源到 debug_src。 可能有很多方法可以针对您的特定环境进行改进和微调

    【讨论】:

    • 虽然对于那些了解 SCons 的人来说可能很明显,但展示如何从命令行使用此解决方案会很有帮助。
    • 谢谢@Avatar33,你的解决方案提供了很多想法,但我真的在寻找一些简单的东西,我可以很容易地向我的同事解释,他们对scons一无所知,几乎不知道python(一些),如果他们需要调试特定文件。此外,我们的项目涉及许多库和可执行文件,并且一些库是为不同的目标平台构建的(例如,本机和 arm 交叉编译),因此仅从 scons 命令行指定源是不够的。
    猜你喜欢
    • 2012-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多