The &AddMethod; function is used to add a method
to an environment. It's typically used to add a "pseudo-builder,"
a function that looks like a &Builder; but
wraps up calls to multiple other &Builder;s
or otherwise processes its arguments
before calling one or more &Builder;s.
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"
As mentioned, a psuedo-builder also provides more flexibility
in parsing arguments than you can get with a &Builder;.
The next example shows a pseudo-builder with a
named argument that modifies the filename, and a separate argument
for the 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 used in all subsequently created environments.
def BuildTestProg(env, testfile, resourcefile, testdir="tests"):
"""Build the test program;
prepends "test_" to src and target,
and puts target into testdir."""
srcfile = "test_%s.c" % testfile
target = "%s/test_%s" % (testdir, testfile)
if env['PLATFORM'] == 'win32':
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 /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 &consenv; because it gets called as a proper method,
and because &AddMethod; provides for copying the method
to any clones of the &consenv; instance.