4

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

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

S构造:

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

征兵:

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

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

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

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

4

2 回答 2

6

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

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

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

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

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

于 2013-10-08T20:11:32.053 回答
4

我想这在 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)

在不使用 debug-targets 标志的情况下运行我们的 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。可能有很多方法可以针对您的特定环境进行改进和微调

于 2013-10-05T12:32:31.067 回答