Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scons: changing compilation flags for a single source file

Tags:

scons

I have a fairly complex scons system with several subdirectories, with many libraries and executables. Currently, every SConscript gets its own cloned environment, so I can easily change CFLAGS (or any other wariable) on a per-SConscript basis, but I'd like to change it per-target, and even per-object-file within a target.

I created a simple example SConscript and SConstruct to explain the problem, as follows.

SConstruct:

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

SConscript:

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

If I run scons, both foo.c and bar.c compile with -O2 flags. I could easily change flags SConscript-wide by just adding env['CFLAGS'] = '...' within the SConscript, but let's say that I want to compile foo.c with -O2, but bar.c with full debugging, -O0 -g. How do I do that (in the simplest possible way)?

The example uses gcc, but I'd like something that can be used with any compiler.

This happens frequently with performance-sensitive projects where compiling everything without optimization would result in unacceptable performance, but there is a need to debug one single file (or a subset of them).

like image 669
Daniele Avatar asked Dec 26 '22 19:12

Daniele


2 Answers

The simplest one-liner answer is probably just to replace your Program line with this:

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

because Program can take Object nodes as well as source files, and you can override any construction variable(s) in any builder (here, we override CFLAGS in the Object builder call). If you want to break out the Object into its own line for clarity:

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

and of course taking that to the limit you get a system like Avatar33 showed above.

like image 196
GaryO Avatar answered Mar 05 '23 23:03

GaryO


I suppose this is a bit harder in scons than it would be in make where you could just clean the required target and rebuilt with debug flags. Which would then just rebuild a specific object.

The solution to your particular project depends on it's size and how much effort the developer is prepared to put in. So here's a rough solution where you specify source files on the command line that you want to be compiled with debug and no optimization, the rest will be compiled with -O2.

In your SConsctruct one additional line to get source files that we want to compile with debug from a command line option:

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

And now in the SConscript file:

    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)

Running our scons with out our debug-targets flag:

    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

But now we want to compile bar.c with debug info:

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

So that adds a bit of complexity to your build system, but if you don't need to specify debug targets from the command line like that, then the developer can obviously just cut and past sources from the normal_src list to debug_src. There's probably many ways to improve and fine tune this for your specific environment

like image 24
Avatar33 Avatar answered Mar 05 '23 22:03

Avatar33