4.3. Builder Objects

By default, SCons supplies (and uses) a number of pre-defined Builder objects:

Objectcompile or assemble an object file
Libraryarchive files into a library
SharedLibraryarchive files into a shared library
Programlink objects and/or libraries into an executable
Makebuild according to file suffixes; see below

A construction environment can be explicitly initialized with associated Builder objects that will be bound to the construction environment object:

	env = Environment(BUILDERS = ['Object', 'Program'])

Builder objects bound to a construction environment can be called directly as methods. When invoked, a Builder object returns a (list of) objects that it will build:

	obj = env.Object(target ='hello.o', source = 'hello.c')
	lib = env.Library(target ='libfoo.a',
	                  source = ['aaa.c', 'bbb.c'])
	slib = env.SharedLibrary(target ='libbar.so',
	                         source = ['xxx.c', 'yyy.c'])
	prog = env.Program(target ='hello',
	                   source = ['hello.o', 'libfoo.a', 'libbar.so'])

4.3.1. Specifying multiple inputs

Multiple input files that go into creating a target file may be passed in as a single string, with the individual file names separated by white space:

	env.Library(target = 'foo.a', source = 'aaa.c bbb.c ccc.c')
	env.Object(target = 'yyy.o', source = 'yyy.c')
	env.Program(target = 'bar', source = 'xxx.c yyy.o foo.a')

Alternatively, multiple input files that go into creating a target file may be passed in as an array. This allows input files to be specified using their object representation:

	env.Library(target = 'foo.a', source = ['aaa.c', 'bbb.c', 'ccc.c'])
	yyy_obj = env.Object(target = 'yyy.o', source = 'yyy.c')
	env.Program(target = 'bar', source = ['xxx.c', yyy_obj, 'foo.a'])

Individual string elements within an array of input files are not further split into white-space separated file names. This allows file names that contain white space to be specified by putting the value into an array:

	env.Program(target = 'foo', source = ['an input file.c'])

4.3.2. Specifying multiple targets

Conversely, the generated target may be a string listing multiple files separated by white space:

	env.Object(target = 'grammar.o y.tab.h', source = 'grammar.y')

An array of multiple target files can be used to mix string and object representations, or to accomodate file names that contain white space:

	env.Program(target = ['my program'], source = 'input.c')

4.3.3. File prefixes and suffixes

For portability, if the target file name does not already have an appropriate file prefix or suffix, the Builder objects will append one appropriate for the file type on the current system:

	# builds 'hello.o' on UNIX, 'hello.obj' on Windows NT:
	obj = env.Object(target ='hello', source = 'hello.c')

	# builds 'libfoo.a' on UNIX, 'foo.lib' on Windows NT:
	lib = env.Library(target ='foo', source = ['aaa.c', 'bbb.c'])

	# builds 'libbar.so' on UNIX, 'bar.dll' on Windows NT:
	slib = env.SharedLibrary(target ='bar', source = ['xxx.c', 'yyy.c'])

	# builds 'hello' on UNIX, 'hello.exe' on Windows NT:
	prog = env.Program(target ='hello',
	                   source = ['hello.o', 'libfoo.a', 'libbar.so'])

4.3.4. Builder object exceptions

Builder objects raise the following exceptions on error:

4.3.5. User-defined Builder objects

Users can define additional Builder objects for specific external object types unknown to SCons. A Builder object may build its target by executing an external command:

	WebPage = Builder(command = 'htmlgen $HTMLGENFLAGS $sources > $target',
	                  suffix = '.html',
	                  src_suffix = '.in')

Alternatively, a Builder object may also build its target by executing a Python function:

	def update(dest):
	        # [code to update the object]
	        return 1

	OtherBuilder1 = Builder(function = update,
	                        src_suffix = ['.in', '.input'])

An optional argument to pass to the function may be specified:

	def update_arg(dest, arg):
	        # [code to update the object]
	        return 1

	OtherBuilder2 = Builder(function = update_arg,
	                        function_arg = 'xyzzy',
	                        src_suffix = ['.in', '.input'])

Both an external command and an internal function may be specified, in which case the function will be called to build the object first, followed by the command line.

User-defined Builder objects can be used like the default Builder objects to initialize construction environments.

	WebPage = Builder(command = 'htmlgen $HTMLGENFLAGS $sources > $target',
	                  suffix = '.html',
	                  src_suffix = '.in')
	env = Environment(BUILDERS = ['WebPage'])
	env.WebPage(target = 'foo.html', source = 'foo.in')
	# Builds 'bar.html' on UNIX, 'bar.htm' on Windows NT:
	env.WebPage(target = 'bar', source = 'bar.in')

The command-line specification can interpolate variables from the construction environment; see "Variable substitution," above.

A Builder object may optionally be initialized with a list of:

  • the prefix of the target file (e.g., 'lib' for libraries)

  • the suffix of the target file (e.g., '.a' for libraries)

  • the expected suffixes of the input files (e.g., '.o' for object files)

These arguments are used in automatic dependency analysis and to generate output file names that don't have suffixes supplied explicitly.

4.3.6. Copying Builder Objects

A Copy method exists to return a copy of an existing Builder object, with any overridden values specified as keyword arguments to the method:

	build = Builder(function = my_build)
	build_out = build.Copy(suffix = '.out')

Typically, Builder objects will be supplied by a tool-master or administrator through a shared construction environment.

4.3.7. Special-purpose build rules

A pre-defined Command builder exists to associate a target file with a specific command or list of commands for building the file:

	env.Command(target = 'foo.out', source = 
	            command = 'foo.in', "foo.process $sources > $target")

	commands = [    "bar.process -o .tmpfile $sources",
	                "mv .tmpfile $target" ]
	env.Command(target = 'bar.out', source = 'bar.in', command = commands)

This is useful when it's too cumbersome to create a Builder object just to build a single file in a special way.

4.3.8. The Make Builder

A pre-defined Builder object named Make exists to make simple builds as easy as possible for users, at the expense of sacrificing some build portability.

The following minimal example builds the 'hello' program from the 'hello.c' source file:

	Environment().Make('hello', 'hello.c')

Users of the Make Builder object are not required to understand intermediate steps involved in generating a file--for example, the distinction between compiling source code into an object file, and then linking object files into an executable. The details of intermediate steps are handled by the invoked method. Users that need to, however, can specify intermediate steps explicitly:

	env = Environment()
	env.Make(target = 'hello.o', source = 'hello.c')
	env.Make(target = 'hello', source = 'hello.o')

The Make method understands the file suffixes specified and "does the right thing" to generate the target object and program files, respectively. It does this by examining the specified output suffixes for the Builder objects bound to the environment.

Because file name suffixes in the target and source file names must be specified, the Make method can't be used portably across operating systems. In other words, for the example above, the Make builder will not generate hello.exe on Windows NT.

4.3.9. Builder maps

The env.Make method "does the right thing" to build different file types because it uses a dictionary from the construction environment that maps file suffixes to the appropriate Builder object. This BUILDERMAP can be initialized at instantiation:

	env = Environment(BUILDERMAP = {
	                        '.o' : Object,
	                        '.a' : Library,
	                        '.html' : WebPage,
	                        '' : Program,

With the BUILDERMAP properly initialized, the env.Make method can be used to build additional file types:

	env.Make(target = 'index.html', source = 'index.input')

Builder objects referenced in the BUILDERMAP do not need to be listed separately in the BUILDERS variable. The construction environment will bind the union of the Builder objects listed in both variables.