4.2. Construction Environments

A construction environment is the basic means by which a software system interacts with the SCons Python API to control a build process.

A construction environment is an object with associated methods for generating target files of various types (Builder objects), other associated object methods for automatically determining dependencies from the contents of various types of source files (Scanner objects), and a dictionary of values used by these methods.

Passing no arguments to the Environment instantiation creates a construction environment with default values for the current platform:

	env = Environment()
	

4.2.1. Construction variables

A construction environment has an associated dictionary of construction variables that control how the build is performed. By default, the Environment method creates a construction environment with values that make most software build "out of the box" on the host system. These default values will be generated at the time SCons is installed using functionality similar to that provided by GNU Autoconf. [1] At a minimum, there will be pre-configured sets of default values that will provide reasonable defaults for UNIX and Windows NT.

The default construction environment values may be overridden when a new construction environment is created by specifying keyword arguments:

	env = Environment(CC =          'gcc',
	                  CCFLAGS =    '-g',
	                  CPPPATH =    ['.', 'src', '/usr/include'],
	                  LIBPATH =    ['/usr/lib', '.'])
	

4.2.2. Fetching construction variables

A copy of the dictionary of construction variables can be returned using the Dictionary method:

	env = Environment()
	dict = env.Dictionary()
	

If any arguments are supplied, then just the corresponding value(s) are returned:

	ccflags = env.Dictionary('CCFLAGS')
	cc, ld = env.Dictionary('CC', 'LD')
	

4.2.3. Copying a construction environment

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

	env = Environment()
	debug = env.Copy(CCFLAGS = '-g')
	

4.2.4. Multiple construction environments

Different external objects often require different build characteristics. Multiple construction environments may be defined, each with different values:

	env = Environment(CCFLAGS = '')
	debug = Environment(CCFLAGS = '-g')
	env.Make(target = 'hello', source = 'hello.c')
	debug.Make(target = 'hello-debug', source = 'hello.c')
	

Dictionaries of values from multiple construction environments may be passed to the Environment instantiation or the Copy method, in which case the last-specified dictionary value wins:

	env1 = Environment(CCFLAGS = '-O', LDFLAGS = '-d')
	env2 = Environment(CCFLAGS = '-g')
	new = Environment(env1.Dictionary(), env2.Dictionary())
	

The new environment in the above example retains LDFLAGS = '-d' from the env1 environment, and CCFLAGS = '-g' from the env2 environment.

4.2.5. Variable substitution

Within a construction command, any variable from the construction environment may be interpolated by prefixing the name of the construction with $:

	MyBuilder = Builder(command = "$XX $XXFLAGS -c $_INPUTS -o $target")

	env.Command(targets = 'bar.out', sources = 'bar.in',
	            command = "sed '1d' < $source > $target")
	

Variable substitution is recursive: the command line is expanded until no more substitutions can be made.

Variable names following the $ may be enclosed in braces. This can be used to concatenate an interpolated value with an alphanumeric character:

	VerboseBuilder = Builder(command = "$XX -${XXFLAGS}v > $target")
	

The variable within braces may contain a pair of parentheses after a Python function name to be evaluated (for example, ${map()}). SCons will interpolate the return value from the function (presumably a string):

	env = Environment(FUNC = myfunc)
	env.Command(target = 'foo.out', source = 'foo.in',
	            command = "${FUNC($<)}")
	

If a referenced variable is not defined in the construction environment, the null string is interpolated.

The following special variables can also be used:

$targets

All target file names. If multiple targets are specified in an array, $targets expands to the entire list of targets, separated by a single space.

Individual targets from a list may be extracted by enclosing the targets keyword in braces and using the appropriate Python array index or slice:

	${targets[0]}     # expands to the first target

	${targets[1:]}    # expands to all but the first target

	${targets[1:-1]}  # expands to all but the first and last targets
	
$target

A synonym for ${targets[0]}, the first target specified.

$sources

All input file names. Any input file names that are used anywhere else on the current command line (via ${sources[0]}, ${sources{[1]}, etc.) are removed from the expanded list.

Any of the above special variables may be enclosed in braces and followed immediately by one of the following attributes to select just a portion of the expanded path name:

.base

Basename: the directory plus the file name, minus any file suffix.

.dir

The directory in which the file lives. This is a relative path, where appropriate.

.file

The file name, minus any directory portion.

.suffix

The file name suffix (that is, the right-most dot in the file name, and all characters to the right of that).

.filebase

The file name (no directory portion), minus any file suffix.

.abspath

The absolute path to the file.



[1] It would be nice if we could avoid re-inventing the wheel here by using some other Python-based tool Autoconf replacement--like what was supposed to come out of the Software Carpentry configuration tool contest. It will probably be most efficient to roll our own logic initially and convert if something better does come along.