Chapter 19. Pseudo-Builders: the AddMethod function

The env.AddMethod(function, [name]) function is used to add a method to an environment. It's typically used to add a "pseudo-builder" or wrap up a call to multiple builders. In the first example, we want to install the program into the standard bin dir, but also copy it into a local install/bin dir that might be used to build a package from.


     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 "install/bin/hello"
    Install file: "hello" as "/usr/bin/hello"
  

It also gives 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). Also this example 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.


     import sys
     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
         if sys.platform=='win32':
             target="%s/test_%s$EXESUFFIX"%(testdir,[testfile, resourcefile])
         else:
             target="%s/test_%s$EXESUFFIX"%(testdir,testfile)
         p = env.Program(target, srcfile)
         return p
     AddMethod(Environment, BuildTestProg)

     # Now use it
     env=Environment()
     env.BuildTestProg('stuff', resourcefile='res.rc')
  

This produces the following (on Linux, anyway; Windows would include the resource file):


    % scons -Q
    cc -o test_stuff.o -c test_stuff.c
    cc -o tests/test_stuff test_stuff.o
  

Using AddMethod is better than just adding an instance method to an Environment because it gets called as a proper method, and AddMethod provides for copying the method to any copies of the Environment instance.