Attaching a Builder to a Construction Environment

A Builder object isn't useful until it's attached to a construction environment so that we can call it to arrange for files to be built. This is done through the BUILDERS construction variable in an environment. The BUILDERS variable is a Python dictionary that maps the names by which you want to call various Builder objects to the objects themselves. For example, if we want to call the Builder we just defined by the name Foo, our SConstruct file might look like:

       bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
       env = Environment(BUILDERS = {'Foo' : bld})
    

With the Builder so attached to our construction environment we can now actually call it like so:

       env.Foo('file.foo', 'file.input')
    

Then when we run SCons it looks like:

      % scons
      foobuild < file.input > file.foo
    

Note, however, that the default BUILDERS variable in a construction environment comes with a default set of Builder objects already defined: Program, Library, etc. And when we explicitly set the BUILDERS variable when we create the construction environment, the default Builders are no longer part of the environment:

       bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
       env = Environment(BUILDERS = {'Foo' : bld})
       env.Foo('file.foo', 'file.input')
       env.Program('hello.c')
    

      % scons
      scons: Reading SConscript files ...
      other errors
      Traceback (most recent call last):
        File "/usr/lib/scons/SCons/Script/__init__.py", line 901, in main
          _main()
        File "/usr/lib/scons/SCons/Script/__init__.py", line 762, in _main
          SCons.Script.SConscript.SConscript(script)
        File "/usr/lib/scons/SCons/Script/SConscript.py", line 207, in SConscript
          exec _file_ in stack[-1].globals
        File "SConstruct", line 4, in ?
          env.Program('hello.c')
      scons: Environment instance has no attribute 'Program'
    

To be able use both our own defined Builder objects and the default Builder objects in the same construction environment, you can either add to the BUILDERS variable using the Append function:

       env = Environment()
       bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
       env.Append(BUILDERS = {'Foo' : bld})
       env.Foo('file.foo', 'file.input')
       env.Program('hello.c')
    

Or you can explicitly set the appropriately-named key in the BUILDERS dictionary:

       env = Environment()
       bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
       env['BUILDERS']['Foo'] = bld
       env.Foo('file.foo', 'file.input')
       env.Program('hello.c')
    

Either way, the same construction environment can then use both the newly-defined Foo Builder and the default Program Builder:

      % scons
      foobuild < file.input > file.foo
      cc -c hello.c -o hello.o
      cc -o hello hello.o