The AddMethod
function is used to add a method
to an environment. It is typically used to add a "pseudo-builder,"
a function that looks like a Builder but
wraps up calls to multiple other Builders
or otherwise processes its arguments
before calling one or more Builders.
In the following example,
we want to install the program into the standard
/usr/bin
directory hierarchy,
but also copy it into a local install/bin
directory from which a package might be built:
def install_in_bin_dirs(env, source): """Install source in both bin dirs""" i1 = env.Install("$BIN", source) i2 = env.Install("$LOCALBIN", source) return [i1[0], i2[0]] # Return a list, like a normal builder env = Environment(BIN='/usr/bin', LOCALBIN='#install/bin') env.AddMethod(install_in_bin_dirs, "InstallInBinDirs") env.InstallInBinDirs(Program('hello.c')) # installs hello in both bin dirs
This produces the following:
% scons -Q /
cc -o hello.o -c hello.c
cc -o hello hello.o
Install file: "hello" as "/usr/bin/hello"
Install file: "hello" as "install/bin/hello"
A pseudo-builder is useful because it gives you more flexibility
parsing arguments than you can get with a standard Builder.
The next example shows a pseudo-builder with a
named argument that modifies the filename, and a separate optional
argument for a resource file (rather than having the builder figure it out
by file extension). This example also demonstrates using the global
AddMethod
function to add a method to the global Environment class,
so it will be available in all subsequently created environments.
def BuildTestProg(env, testfile, resourcefile="", testdir="tests"): """Build the test program. Prepends "test_" to src and target and puts the target into testdir. If the build is running on Windows, also make use of a resource file, if supplied. """ srcfile = f"test_{testfile}.c" target = f"{testdir}/test_{testfile}" if env['PLATFORM'] == 'win32' and resourcefile: resfile = env.RES(resourcefile) p = env.Program(target, [srcfile, resfile]) else: p = env.Program(target, srcfile) return p AddMethod(Environment, BuildTestProg) env = Environment() env.BuildTestProg('stuff', resourcefile='res.rc')
This produces the following on Linux:
% scons -Q
cc -o test_stuff.o -c test_stuff.c
cc -o tests/test_stuff test_stuff.o
And the following on Windows:
C:\>scons -Q
rc /nologo /fores.res res.rc
cl /Fotest_stuff.obj /c test_stuff.c /nologo
link /nologo /OUT:tests\test_stuff.exe test_stuff.obj res.res
embedManifestExeCheck(target, source, env)
Using AddMethod
is better than just adding an instance method
to a construction environment because it gets called as a proper method,
and because AddMethod
provides for copying the method
to any clones of the construction environment instance.