# Extending &SCons;: Pseudo-Builders and the AddMethod function

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='__ROOT__/usr/bin', LOCALBIN='#install/bin') env.AddMethod(install_in_bin_dirs, "InstallInBinDirs") env.InstallInBinDirs(Program('hello.c')) # installs hello in both bin dirs
int main() { printf("Hello, world!\n"); }

This produces the following:

scons -Q /

As mentioned, a pseudo-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')
int main() { printf("Hello, world!\n"); }
res.rc

This produces the following on Linux:

scons -Q

And the following on Windows:

scons -Q

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.