Skip to content
William Deegan edited this page Sep 25, 2021 · 4 revisions

How to write a scons wrapper function ?

WARNING: as of SCons 0.98, the API provides the AddMethod function (more portable and API-safe).

If you have a sequence of SCons operations that's not well-captured by a Builder, or you just want to wrap up some SCons functions into a neat callable package, you probably want to make it look like a regular SCons environment method. Here's how to do that:

Let's say you have this (just for example):

#!python
sources = ["foo.c", "bar.c", "main.c"]
env = Environment()
VariantDir("build", ".", duplicate = 0)
build_sources = ["build/" + filename for filename in sources]
prog = env.Program("build/program", build_sources)
Default(prog)

and you want to wrap it up so you can do that kind of thing in several places. Write a normal python function making sure an Environment is its first arg:

#!python
def BuildProgramInDir(env, program, sources):
   VariantDir("build", ".", duplicate=0)
   build_sources = ["build/" + filename for filename in sources]
   prog = env.Program("build/"+program, build_sources)
   Default(prog)

then to make it callable as an Environment method, do this (pre-0.98; otherwise use AddMethod):

#!python
from SCons.Script.SConscript import SConsEnvironment # just do this once
SConsEnvironment.BuildProgramInDir = BuildProgramInDir

then you can call it as usual:

#!python
env=Environment()
sources = ["foo.c", "bar.c", "main.c"]
env.BuildProgramInDir('program', sources)

There are many more useful things you can do with this, from simple renaming of standard methods to complex pathname manipulations to automatically building and installing in one command. Have fun!

Here's another wrapper example that handles targets, sources, and overrides in the same way that ordinary SCons builders do. In this example, I want to define a wrapper that will automatically add a certain library when building my test programs.

#!python
from SCons.Script.SConscript import SConsEnvironment
# Define _null (used to detect missing target arg in wrapper functions)
class _Null:
    pass
_null = _Null
def MyTestProgram( env, target=None, source=_null, **kw ):
    '''Build a test program, adding utest library to link automatically.'''
    # Reassign args if no target specified
    if source is _null:
        source = target
        target = None
   # Add utest to the list of libraries
    if 'LIBS' in kw:
        libs = kw.pop( 'LIBS' )
    else:
        libs = []
    kw['LIBS'] = [ 'utest' ] + libs
    # Use ordinary Program builder to build the program
    program = env.Program( target, source, **kw )
    # Must build the utest library first
    env.Depends( program, env['LIBPREFIX'] + 'utest' + env['LIBSUFFIX'] )
    return program
# Add wrapper to environment
SConsEnvironment.MyTestProgram = MyTestProgram
env = Environment()
env.Library( 'utest', 'usub1.c' )
# Specify just the source
env.MyTestProgram( 'test1.c' )
# Specify both target and source
env.MyTestProgram( 'renamed_test2', 'test2.c' )
# Specify just source with an override for CCFLAGS
env.MyTestProgram( 'test3.c', CCFLAGS='/nologo /O1' )
Clone this wiki locally