The scons utility builds software (or other files) by determining which component pieces must be rebuilt and executing the necessary commands to rebuild them.
By default, scons searches for a file named SConstruct, Sconstruct, or sconstruct (in that order) in the current directory and reads its configuration from the first file found. An alternate file name may be specified via the -f option.
The SConstruct file can specify subsidiary configuration files using the SConscript() function. By convention, these subsidiary files are named SConscript, although any name may be used. (Because of this naming convention, the term "SConscript files" is sometimes used to refer generically to all scons configuration files, regardless of actual file name.)
The configuration files specify the target files to be built, and (optionally) the rules to build those targets. Reasonable default rules exist for building common software components (executable programs, object files, libraries), so that for most software projects, only the target and input files need be specified.
Before reading the SConstruct file, scons adds looks for a dir named site_scons in the dir containing the SConstruct file; it adds that site_scons to sys.path, reads the file site_scons/site_init.py, and adds the directory site_scons/site_tools to the default toolpath, if those exist. See the --no-site-dir and --site-dir options for more details.
scons reads and executes the SConscript files as Python scripts, so you may use normal Python scripting capabilities (such as flow control, data manipulation, and imported Python libraries) to handle complicated build situations. scons, however, reads and executes all of the SConscript files before it begins building any targets. To make this obvious, scons prints the following messages about what it is doing:
$ scons foo.out scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... cp foo.in foo.out scons: done building targets. $
The status messages (everything except the line that reads "cp foo.in foo.out") may be suppressed using the -Q option.
scons does not automatically propagate the external environment used to execute scons to the commands used to build target files. This is so that builds will be guaranteed repeatable regardless of the environment variables set at the time scons is invoked. This also means that if the compiler or other commands that you want to use to build your target files are not in standard system locations, scons will not find them unless you explicitly set the PATH to include those locations. Whenever you create an scons construction environment, you can propagate the value of PATH from your external environment as follows:
import os
env = Environment(ENV = {'PATH' : os.environ['PATH']})
Similarly, if the commands use external environment variables like $PATH, $HOME, $JAVA_HOME, $LANG, $SHELL, $TERM, etc., these variables can also be explicitly propagated:
import os
env = Environment(ENV = {'PATH' : os.environ['PATH'],
'HOME' : os.environ['HOME']})
Or you may explicitly propagate the invoking user's complete external environment:
import os env = Environment(ENV = os.environ['PATH'])
This comes at the expense of making your build dependent on the user's environment being set correctly, but it may be more convenient for many configurations.
scons can scan known input files automatically for dependency information (for example, #include statements in C or C++ files) and will rebuild dependent files appropriately whenever any "included" input file changes. scons supports the ability to define new scanners for unknown input file types.
scons knows how to fetch files automatically from SCCS or RCS subdirectories using SCCS, RCS or BitKeeper.
scons is normally executed in a top-level directory containing a SConstruct file, optionally specifying as command-line arguments the target file or files to be built.
By default, the command
scons
will build all target files in or below the current directory. Explicit default targets (to be built when no targets are specified on the command line) may be defined the SConscript file(s) using the Default() function, described below.
Even when Default() targets are specified in the SConscript file(s), all target files in or below the current directory may be built by explicitly specifying the current directory (.) as a command-line target:
scons .
Building all target files, including any files outside of the current directory, may be specified by supplying a command-line target of the root directory (on POSIX systems):
scons /
or the path name(s) of the volume(s) in which all the targets should be built (on Windows systems):
scons C:\ D:\
To build only specific targets, supply them as command-line arguments:
scons foo bar
in which case only the specified targets will be built (along with any derived files on which they depend).
Specifying "cleanup" targets in SConscript files is not necessary. The -c flag removes all files necessary to build the specified target:
scons -c .
to remove all target files, or:
scons -c build export
to remove target files under build and export. Additional files or directories to remove can be specified using the Clean() function. Conversely, targets that would normally be removed by the -c invocation can be prevented from being removed by using the NoClean() function.
A subset of a hierarchical tree may be built by remaining at the top-level directory (where the SConstruct file lives) and specifying the subdirectory as the target to be built:
scons src/subdir
or by changing directory and invoking scons with the -u option, which traverses up the directory hierarchy until it finds the SConstruct file, and then builds targets relatively to the current subdirectory:
cd src/subdir scons -u .
scons supports building multiple targets in parallel via a -j option that takes, as its argument, the number of simultaneous tasks that may be spawned:
scons -j 4
builds four targets in parallel, for example.
scons can maintain a cache of target (derived) files that can be shared between multiple builds. When caching is enabled in a SConscript file, any target files built by scons will be copied to the cache. If an up-to-date target file is found in the cache, it will be retrieved from the cache instead of being rebuilt locally. Caching behavior may be disabled and controlled in other ways by the --cache-force, --cache-disable, and --cache-show command-line options. The --random option is useful to prevent multiple builds from trying to update the cache simultaneously.
Values of variables to be passed to the SConscript file(s) may be specified on the command line:
scons debug=1 .
These variables are available in SConscript files through the ARGUMENTS dictionary, and can be used in the SConscript file(s) to modify the build in any way:
if ARGUMENTS.get('debug', 0):
env = Environment(CCFLAGS = '-g')
else:
env = Environment()
The command-line variable arguments are also available in the ARGLIST list, indexed by their order on the command line. This allows you to process them in order rather than by name, if necessary. ARGLIST[0] returns a tuple containing (argname, argvalue). A Python exception is thrown if you try to access a list member that does not exist.
scons requires Python version 1.5.2 or later. There should be no other dependencies or requirements to run scons.
By default, scons knows how to search for available programming tools on various systems. On Windows systems, scons searches in order for the Microsoft Visual C++ tools, the MinGW tool chain, the Intel compiler tools, and the PharLap ETS compiler. On OS/2 systems, scons searches in order for the OS/2 compiler, the GCC tool chain, and the Microsoft Visual C++ tools, On SGI IRIX, IBM AIX, Hewlett Packard HP-UX, and Sun Solaris systems, scons searches for the native compiler tools (MIPSpro, Visual Age, aCC, and Forte tools respectively) and the GCC tool chain. On all other platforms, including POSIX (Linux and UNIX) platforms, scons searches in order for the GCC tool chain, the Microsoft Visual C++ tools, and the Intel compiler tools. You may, of course, override these default values by appropriate configuration of Environment construction variables.
$ scons --debug=includes foo.o
$ scons --debug=presub Building myprog.o with action(s): $SHCC $SHCFLAGS $SHCCFLAGS $CPPFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES
# Prints only derived files, with status information: scons --tree=derived,status # Prints all dependencies of target, with status information # and pruning dependencies of already-visited Nodes: scons --tree=all,prune,status target
env = Environment()
By default, a new construction environment is initialized with a set of builder methods and construction variables that are appropriate for the current platform. An optional platform keyword argument may be used to specify that an environment should be initialized for a different platform:
env = Environment(platform = 'cygwin') env = Environment(platform = 'os2') env = Environment(platform = 'posix') env = Environment(platform = 'win32')
Specifying a platform initializes the appropriate construction variables in the environment to use and generate file names with prefixes and suffixes appropriate for the platform.
Note that the win32 platform adds the SYSTEMDRIVE and SYSTEMROOT variables from the user's external environment to the construction environment's ENV dictionary. This is so that any executed commands that use sockets to connect with other systems (such as fetching source files from external CVS repository specifications like :pserver:anonymous@cvs.sourceforge.net:/cvsroot/scons) will work on Windows systems.
The platform argument may be function or callable object, in which case the Environment() method will call the specified argument to update the new construction environment:
def my_platform(env):
env['VAR'] = 'xyzzy'
env = Environment(platform = my_platform)
Additionally, a specific set of tools with which to initialize the environment may specified as an optional keyword argument:
env = Environment(tools = ['msvc', 'lex'])
Non-built-in tools may be specified using the toolpath argument:
env = Environment(tools = ['default', 'foo'], toolpath = ['tools'])
This looks for a tool specification in tools/foo.py (as well as using the ordinary default tools for the platform). foo.py should have two functions: generate(env, **kw) and exists(env). The generate() function modifies the passed-in environment to set up variables so that the tool can be executed; it may use any keyword arguments that the user supplies (see below) to vary its initialization. The exists() function should return a true value if the tool is available. Tools in the toolpath are used before any of the built-in ones. For example, adding gcc.py to the toolpath would override the built-in gcc tool. Also note that the toolpath is stored in the environment for use by later calls to Clone() and Tool() methods:
base = Environment(toolpath=['custom_path']) derived = base.Clone(tools=['custom_tool']) derived.CustomBuilder()
The elements of the tools list may also be functions or callable objects, in which case the Environment() method will call the specified elements to update the new construction environment:
def my_tool(env):
env['XYZZY'] = 'xyzzy'
env = Environment(tools = [my_tool])
The individual elements of the tools list may also themselves be two-element lists of the form (toolname, kw_dict). SCons searches for the toolname specification file as described above, and passes kw_dict, which must be a dictionary, as keyword arguments to the tool's generate function. The generate function can use the arguments to modify the tool's behavior by setting up the environment in different ways or otherwise changing its initialization.
# in tools/my_tool.py:
def generate(env, **kw):
# Sets MY_TOOL to the value of keyword argument 'arg1' or 1.
env['MY_TOOL'] = kw.get('arg1', '1')
def exists(env):
return 1
# in SConstruct:
env = Environment(tools = ['default', ('my_tool', {'arg1': 'abc'})],
toolpath=['tools'])
The tool definition (i.e. my_tool()) can use the PLATFORM variable from the environment it receives to customize the tool for different platforms.
If no tool list is specified, then SCons will auto-detect the installed tools using the PATH variable in the ENV construction variable and the platform name when the Environment is constructed. Changing the PATH variable after the Environment is constructed will not cause the tools to be redetected.
SCons supports the following tool specifications out of the box:
386asm aixc++ aixcc aixf77 aixlink ar as bcc32 c++ cc cvf dmd dvipdf dvips f77 f90 f95 fortran g++ g77 gas gcc gnulink gs hpc++ hpcc hplink icc icl ifl ifort ilink ilink32 intelc jar javac javah latex lex link linkloc m4 masm midl mingw mslib mslink msvc msvs mwcc mwld nasm pdflatex pdftex qt rmic rpcgen sgiar sgic++ sgicc sgilink sunar sunc++ suncc sunlink swig tar tex tlib yacc zip
Additionally, there is a "tool" named default which configures the environment with a default set of tools for the current platform.
On posix and cygwin platforms the GNU tools (e.g. gcc) are preferred by SCons, on Windows the Microsoft tools (e.g. msvc) followed by MinGW are preferred by SCons, and in OS/2 the IBM tools (e.g. icc) are preferred by SCons.
Build rules are specified by calling a construction environment's builder methods. The arguments to the builder methods are target (a list of target files) and source (a list of source files).
Because long lists of file names can lead to a lot of quoting, scons supplies a Split() global function and a same-named environment method that split a single string into a list, separated on strings of white-space characters. (These are similar to the string.split() method from the standard Python library, but work even if the input isn't a string.)
Like all Python arguments, the target and source arguments to a builder method can be specified either with or without the "target" and "source" keywords. When the keywords are omitted, the target is first, followed by the source. The following are equivalent examples of calling the Program builder method:
env.Program('bar', ['bar.c', 'foo.c'])
env.Program('bar', Split('bar.c foo.c'))
env.Program('bar', env.Split('bar.c foo.c'))
env.Program(source = ['bar.c', 'foo.c'], target = 'bar')
env.Program(target = 'bar', Split('bar.c foo.c'))
env.Program(target = 'bar', env.Split('bar.c foo.c'))
env.Program('bar', source = string.split('bar.c foo.c'))
When the target shares the same base name as the source and only the suffix varies, and if the builder method has a suffix defined for the target file type, then the target argument may be omitted completely, and scons will deduce the target file name from the source file name. The following examples all build the executable program bar (on POSIX systems) or bar.exe (on Windows systems) from the bar.c source file:
env.Program(target = 'bar', source = 'bar.c')
env.Program('bar', source = 'bar.c')
env.Program(source = 'bar.c')
env.Program('bar.c')
As a convenience, a srcdir keyword argument may be specified when calling a Builder. When specified, all source file strings that are not absolute paths will be interpreted relative to the specified srcdir. The following example will build the build/prog (or build/prog.exe on Windows) program from the files src/f1.c and src/f2.c:
env.Program('build/prog', ['f1.c', 'f2.c'], srcdir='src')
It is possible to override or add construction variables when calling a builder method by passing additional keyword arguments. These overridden or added variables will only be in effect when building the target, so they will not affect other parts of the build. For example, if you want to add additional libraries for just one program:
env.Program('hello', 'hello.c', LIBS=['gl', 'glut'])
or generate a shared library with a non-standard suffix:
env.SharedLibrary('word', 'word.cpp',
SHLIBSUFFIX='.ocx',
LIBSUFFIXES=['.ocx'])
(Note that both the $SHLIBSUFFIX and $LIBSUFFIXES variables must be set if you want SCons to search automatically for dependencies on the non-standard library names; see the descriptions of these variables, below, for more information.)
Although the builder methods defined by scons are, in fact, methods of a construction environment object, they may also be called without an explicit environment:
Program('hello', 'hello.c')
SharedLibrary('word', 'word.cpp')
In this case, the methods are called internally using a default construction environment that consists of the tools and values that scons has determined are appropriate for the local system.
Builder methods that can be called without an explicit environment may be called from custom Python modules that you import into an SConscript file by adding the following to the Python module:
from SCons.Script import *
All builder methods return a list of Nodes that represent the target or targets that will be built. A Node is an internal SCons object which represents build targets or sources.
The returned Node(s) can be passed to other builder methods as source(s) or passed to any SCons function or method where a filename would normally be accepted. For example, if it were necessary to add a specific -D flag when compiling one specific object file:
bar_obj_list = env.StaticObject('bar.c', CPPDEFINES='-DBAR')
env.Program(source = ['foo.c', bar_obj_list, 'main.c'])
Using a Node in this way makes for a more portable build by avoiding having to specify a platform-specific object suffix when calling the Program() builder method.
Note that Builder calls will automatically "flatten" the source and target file lists, so it's all right to have the bar_obj list return by the StaticObject() call in the middle of the source file list. If you need to manipulate a list of lists returned by Builders directly using Python, you can either build the list by hand:
foo = Object('foo.c')
bar = Object('bar.c')
objects = ['begin.o'] + foo + ['middle.o'] + bar + ['end.o']
for object in objects:
print str(object)
Or you can use the Flatten() supplied by scons to create a list containing just the Nodes, which may be more convenient:
foo = Object('foo.c')
bar = Object('bar.c')
objects = Flatten(['begin.o', foo, 'middle.o', bar, 'end.o'])
for object in objects:
print str(object)
The path name for a Node's file may be used by passing the Node to the Python-builtin str() function:
bar_obj_list = env.StaticObject('bar.c', CPPDEFINES='-DBAR')
print "The path to bar_obj is:", str(bar_obj_list[0])
Note again that because the Builder call returns a list, we have to access the first element in the list (bar_obj_list[0]) to get at the Node that actually represents the object file.
Builder calls support a chdir keyword argument that specifies that the Builder's action(s) should be executed after changing directory. If the chdir argument is a string or a directory Node, scons will change to the specified directory. If the chdir is not a string or Node and is non-zero, then scons will change to the target file's directory.
# scons will change to the "sub" subdirectory
# before executing the "cp" command.
env.Command('sub/dir/foo.out', 'sub/dir/foo.in',
"cp dir/foo.in dir/foo.out",
chdir='sub')
# Because chdir is not a string, scons will change to the
# target's directory ("sub/dir") before executing the
# "cp" command.
env.Command('sub/dir/foo.out', 'sub/dir/foo.in',
"cp foo.in foo.out",
chdir=1)
Note that scons will not automatically modify its expansion of construction variables like $TARGET and $SOURCE when using the chdir keyword argument--that is, the expanded file names will still be relative to the top-level SConstruct directory, and consequently incorrect relative to the chdir directory. If you use the chdir keyword argument, you will typically need to supply a different command line using expansions like ${TARGET.file} and ${SOURCE.file} to use just the filename portion of the targets and source.
scons provides the following builder methods:
# builds foo.c env.CFile(target = 'foo.c', source = 'foo.l') # builds bar.c env.CFile(target = 'bar', source = 'bar.y')
# builds foo.cc env.CXXFile(target = 'foo.cc', source = 'foo.ll') # builds bar.cc env.CXXFile(target = 'bar', source = 'bar.yy')
The suffix .dvi (hard-coded within TeX itself) is automatically added to the target if it is not already present. Examples:
# builds from aaa.tex env.DVI(target = 'aaa.dvi', source = 'aaa.tex') # builds bbb.dvi env.DVI(target = 'bbb', source = 'bbb.ltx') # builds from ccc.latex env.DVI(target = 'ccc.dvi', source = 'ccc.latex')
env.Jar(target = 'foo.jar', source = 'classes')
Example:
env.Java(target = 'classes', source = 'src') env.Java(target = 'classes', source = ['src1', 'src2'])
If the construction variable $JAVACLASSDIR is set, either in the environment or in the call to the JavaH() builder method itself, then the value of the variable will be stripped from the beginning of any .class file names.
Examples:
# builds java_native.h
classes = env.Java(target = 'classdir', source = 'src')
env.JavaH(target = 'java_native.h', source = classes)
# builds include/package_foo.h and include/package_bar.h
env.JavaH(target = 'include',
source = ['package/foo.class', 'package/bar.class'])
# builds export/foo.h and export/bar.h
env.JavaH(target = 'export',
source = ['classes/foo.class', 'classes/bar.class'],
JAVACLASSDIR = 'classes')
env.M4(target = 'foo.c', source = 'foo.c.m4')
env.Moc('foo.h') # generates moc_foo.cc
env.Moc('foo.cpp') # generates foo.moc
This builds a Visual Studio project file, based on the version of Visual Studio that is configured (either the latest installed version, or the version specified by $MSVS_VERSION in the Environment constructor). For Visual Studio 6, it will generate a .dsp file. For Visual Studio 7 (.NET), it will generate a .dsp file.
By default, this also generates a solution file for the specified project, a .dsw file for Visual Studio 6 or a .sln file for Visual Studio 7 (.NET). This behavior may be disabled by specifying auto_build_solution=0 when you call MSVSProject(), in which case you presumably want to build the solution file(s) by calling the MSVSSolution() Builder (see below).
It takes several lists of filenames to be placed into the project file. These are currently limited to srcs, incs, localincs, resources, and misc. These are pretty self-explanatory, but it should be noted that these lists are added to the $SOURCES construction variable as strings, NOT as SCons File Nodes. This is because they represent file names to be added to the project file, not the source files used to build the project file.
The above filename lists are all optional, although at least one must be specified for the resulting project file to be non-empty.
In addition to the above lists of values, the following values may be specified:
target: The name of the target .dsp or .vcproj file. The correct suffix for the version of Visual Studio must be used, but the $MSVSPROJECTSUFFIX construction variable will be defined to the correct value (see example below).
variant: The name of this particular variant. For Visual Studio 7 projects, this can also be a list of variant names. These are typically things like "Debug" or "Release", but really can be anything you want. For Visual Studio 7 projects, they may also specify a target platform separated from the variant name by a | (vertical pipe) character: Debug|Xbox. The default target platform is Win32. Multiple calls to MSVSProject() with different variants are allowed; all variants will be added to the project file with their appropriate build targets and sources.
buildtarget: An optional string, node, or list of strings or nodes (one per build variant), to tell the Visual Studio debugger what output target to use in what build variant. The number of buildtarget entries must match the number of variant entries.
runfile: The name of the file that Visual Studio 7 and later will run and debug. This appears as the value of the Output field in the resutling Visual Studio project file. If this is not specified, the default is the same as the specified buildtarget value.
Example usage:
barsrcs = ['bar.cpp'],
barincs = ['bar.h'],
barlocalincs = ['StdAfx.h']
barresources = ['bar.rc','resource.h']
barmisc = ['bar_readme.txt']
dll = env.SharedLibrary(target = 'bar.dll',
source = barsrcs)
env.MSVSProject(target = 'Bar' + env['MSVSPROJECTSUFFIX'],
srcs = barsrcs,
incs = barincs,
localincs = barlocalincs,
resources = barresources,
misc = barmisc,
buildtarget = dll,
variant = 'Release')
This builds a Visual Studio solution file, based on the version of Visual Studio that is configured (either the latest installed version, or the version specified by $MSVS_VERSION in the construction environment). For Visual Studio 6, it will generate a .dsw file. For Visual Studio 7 (.NET), it will generate a .sln file.
The following values must be specified:
target: The name of the target .dsw or .sln file. The correct suffix for the version of Visual Studio must be used, but the value $MSVSSOLUTIONSUFFIX will be defined to the correct value (see example below).
variant: The name of this particular variant, or a list of variant names (the latter is only supported for MSVS 7 solutions). These are typically things like "Debug" or "Release", but really can be anything you want. For MSVS 7 they may also specify target platform, like this "Debug|Xbox". Default platform is Win32.
projects: A list of project file names, or Project nodes returned by calls to the MSVSProject() Builder, to be placed into the solution file. (NOTE: Currently only one project is supported per solution.) It should be noted that these file names are NOT added to the $SOURCES environment variable in form of files, but rather as strings. This is because they represent file names to be added to the solution file, not the source files used to build the solution file.
Example Usage:
env.MSVSSolution(target = 'Bar' + env['MSVSSOLUTIONSUFFIX'],
projects = ['bar' + env['MSVSPROJECTSUFFIX']],
variant = 'Release')
env['PCH'] = env.PCH('StdAfx.cpp')[0]
# builds from aaa.tex env.PDF(target = 'aaa.pdf', source = 'aaa.tex') # builds bbb.pdf from bbb.dvi env.PDF(target = 'bbb', source = 'bbb.dvi')
# builds from aaa.tex env.PostScript(target = 'aaa.ps', source = 'aaa.tex') # builds bbb.ps from bbb.dvi env.PostScript(target = 'bbb', source = 'bbb.dvi')
env.Program(target = 'foo', source = ['foo.o', 'bar.c', 'baz.f'])
env.RES('resource.rc')
If the construction variable $JAVACLASSDIR is set, either in the environment or in the call to the RMIC() builder method itself, then the value of the variable will be stripped from the beginning of any .class file names.
classes = env.Java(target = 'classdir', source = 'src')
env.RMIC(target = 'outdir1', source = classes)
env.RMIC(target = 'outdir2',
source = ['package/foo.class', 'package/bar.class'])
env.RMIC(target = 'outdir3',
source = ['classes/foo.class', 'classes/bar.class'],
JAVACLASSDIR = 'classes')
# Builds src/rpcif_clnt.c
env.RPCGenClient('src/rpcif.x')
# Builds src/rpcif.h
env.RPCGenHeader('src/rpcif.x')
# Builds src/rpcif_svc.c
env.RPCGenClient('src/rpcif.x')
# Builds src/rpcif_xdr.c
env.RPCGenClient('src/rpcif.x')
env.SharedLibrary(target = 'bar', source = ['bar.c', 'foo.o'])
Any object files listed in the source must have been built for a shared library (that is, using the SharedObject() builder method). scons will raise an error if there is any mismatch.
On Windows systems, specifying register=1 will cause the .dll to be registered after it is built using REGSVR32. The command that is run ("regsvr32" by default) is determined by $REGSVR construction variable, and the flags passed are determined by $REGSVRFLAGS. By default, $REGSVRFLAGS includes the /s option, to prevent dialogs from popping up and requiring user attention when it is run. If you change $REGSVRFLAGS, be sure to include the /s option. For example,
env.SharedLibrary(target = 'bar',
source = ['bar.cxx', 'foo.obj'],
register=1)
env.SharedObject(target = 'ddd', source = 'ddd.c') env.SharedObject(target = 'eee.o', source = 'eee.cpp') env.SharedObject(target = 'fff.obj', source = 'fff.for')
env.StaticLibrary(target = 'bar', source = ['bar.c', 'foo.o'])
.asm assembly language file
.ASM assembly language file
.c C file
.C Windows: C file
POSIX: C++ file
.cc C++ file
.cpp C++ file
.cxx C++ file
.cxx C++ file
.c++ C++ file
.C++ C++ file
.d D file
.f Fortran file
.F Windows: Fortran file
POSIX: Fortran file + C pre-processor
.for Fortran file
.FOR Fortran file
.fpp Fortran file + C pre-processor
.FPP Fortran file + C pre-processor
.m Object C file
.mm Object C++ file
.s assembly language file
.S Windows: assembly language file
POSIX: assembly language file + C pre-processor
.spp assembly language file + C pre-processor
.SPP assembly language file + C pre-processor
env.StaticObject(target = 'aaa', source = 'aaa.c') env.StaticObject(target = 'bbb.o', source = 'bbb.c++') env.StaticObject(target = 'ccc.obj', source = 'ccc.f')
env.Tar('src.tar', 'src')
# Create the stuff.tar file.
env.Tar('stuff', ['subdir1', 'subdir2'])
# Also add "another" to the stuff.tar file.
env.Tar('stuff', 'another')
# Set TARFLAGS to create a gzip-filtered archive.
env = Environment(TARFLAGS = '-c -z')
env.Tar('foo.tar.gz', 'foo')
# Also set the suffix to .tgz.
env = Environment(TARFLAGS = '-c -z',
TARSUFFIX = '.tgz')
env.Tar('foo')
env.TypeLibrary(source="foo.idl")
env.Uic('foo.ui') # -> ['foo.h', 'uic_foo.cc', 'moc_foo.cc']
env.Uic(target = Split('include/foo.h gen/uicfoo.cc gen/mocfoo.cc'),
source = 'foo.ui') # -> ['include/foo.h', 'gen/uicfoo.cc', 'gen/mocfoo.cc']
env.Zip('src.zip', 'src')
# Create the stuff.zip file.
env.Zip('stuff', ['subdir1', 'subdir2'])
# Also add "another" to the stuff.tar file.
env.Zip('stuff', 'another')
All targets of builder methods automatically depend on their sources. An explicit dependency can be specified using the Depends method of a construction environment (see below).
In addition, scons automatically scans source files for various programming languages, so the dependencies do not need to be specified explicitly. By default, SCons can C source files, C++ source files, Fortran source files with .F (POSIX systems only), .fpp, or .FPP file extensions, and assembly language files with .S (POSIX systems only), .spp, or .SPP files extensions for C preprocessor dependencies. SCons also has default support for scanning D source files, You can also write your own Scanners to add support for additional source file types. These can be added to the default Scanner object used by the Object() StaticObject() and SharedObject() Builders by adding them to the SourceFileScanner object as follows:
See the section "Scanner Objects," below, for a more information about defining your own Scanner objects.
Usually, a construction environment method and global function with the same name both exist so that you don't have to remember whether to a specific bit of functionality must be called with or without a construction environment. In the following list, if you call something as a global function it looks like:
Function(arguments)
env.Function(arguments)
Global functions may be called from custom Python modules that you import into an SConscript file by adding the following to the Python module:
from SCons.Script import *
Except where otherwise noted, the same-named construction environment method and global function provide the exact same functionality. The only difference is that, where appropriate, calling the functionality through a construction environment will substitute construction variables into any supplied strings. For example:
env = Environment(FOO = 'foo')
Default('$FOO')
env.Default('$FOO')
Construction environment methods and global functions supported by scons include:
Note that the env.Action() form of the invocation will expand construction variables in any arguments strings, including the action argument, at the time it is called using the construction variables in the env construction environment through which env.Action() was called. The Action() form delays all variable expansion until the Action object is actually used.
Alias('install')
Alias('install', '/usr/bin')
Alias(['install', 'install-lib'], '/usr/local/lib')
env.Alias('install', ['/usr/local/bin', '/usr/local/lib'])
env.Alias('install', ['/usr/local/man'])
env.Alias('update', ['file1', 'file2'], "update_database $SOURCES")
If AllowSubstExceptions is called multiple times, each call completely overwrites the previous list of allowed exceptions. Example:
# Requires that all construction variable names exist.
# (You may wish to do this if you want to enforce strictly
# that all construction variables must be defined before use.)
AllowSubstExceptions()
# Also allow a string containing a zero-division expansion
# like '${1 / 0}' to evalute to ''.
AllowSubstExceptions(IndexError, NameError, ZeroDivisionError)
env.Append(CCFLAGS = ' -g', FOO = ['foo.yyy'])
print 'before:',env['ENV']['INCLUDE']
include_path = '/foo/bar:/foo'
env.AppendENVPath('INCLUDE', include_path)
print 'after:',env['ENV']['INCLUDE']
yields:
before: /foo:/biz
after: /biz:/foo/bar:/foo
env.AppendUnique(CCFLAGS = '-g', FOO = ['foo.yyy'])
env.SourceCode('.', env.BitKeeper())
The default behavior is for scons to duplicate all of the files in the tree underneath src_dir into build_dir, and then build the derived files within the copied tree. (The duplication is performed by linking or copying, depending on the platform; see also the --duplicate option.) This guarantees correct builds regardless of whether intermediate source files are generated during the build, where preprocessors or other scanners search for included files, or whether individual compilers or other invoked tools are hard-coded to put derived files in the same directory as source files.
This behavior of making a complete copy of the source tree may be disabled by setting duplicate to 0. This will cause scons to invoke Builders using the path names of source files in src_dir and the path names of derived files within build_dir. This is always more efficient than duplicate=1, and is usually safe for most builds. Specifying duplicate=0, however, may cause build problems if source files are generated during the build, if any invoked tools are hard-coded to put derived files in the same directory as the source files.
Note that specifying a BuildDir works most naturally with a subsidiary SConscript file in the source directory. However, you would then call the subsidiary SConscript file not in the source directory, but in the build_dir , as if scons had made a virtual copy of the source tree regardless of the value of duplicate. This is how you tell scons which variant of a source tree to build. For example:
BuildDir('build-variant1', 'src')
SConscript('build-variant1/SConscript')
BuildDir('build-variant2', 'src')
SConscript('build-variant2/SConscript')
Note that the env.Builder() form of the invocation will expand construction variables in any arguments strings, including the action argument, at the time it is called using the construction variables in the env construction environment through which env.Builder() was called. The Builder() form delays all variable expansion until after the Builder object is actually called.
When a CacheDir() is being used and scons finds a derived file that needs to be rebuilt, it will first look in the cache to see if a derived file has already been built from identical input files and an identical build action (as incorporated into the MD5 build signature). If so, scons will retrieve the file from the cache. If the derived file is not present in the cache, scons will rebuild it and then place a copy of the built file in the cache (identified by its MD5 build signature), so that it may be retrieved by other builds that need to build the same derived file from identical inputs.
Use of a specified CacheDir() may be disabled for any invocation by using the --cache-disable option.
If the --cache-force option is used, scons will place a copy of all derived files in the cache, even if they already existed and were not built by this invocation. This is useful to populate a cache the first time CacheDir() is added to a build, or after using the --cache-disable option.
When using CacheDir(), scons will report, "Retrieved `file' from cache," unless the --cache-show option is being used. When the --cache-show option is used, scons will print the action that would have been used to build the file, without any indication that the file was actually retrieved from the cache. This is useful to generate build logs that are equivalent regardless of whether a given derived file has been built in-place or retrieved from the cache.
The NoCache() method can be used to disable caching of specific files. This can be useful if inputs and/or outputs of some tool are impossible to predict or prohibitively large.
Multiple files or directories should be specified either as separate arguments to the Clean() method, or as a list. Clean() will also accept the return value of any of the construction environment Builder methods. Examples:
The related NoClean() function overrides calling Clean() for the same target, and any targets passed to both functions will not be removed by the -c option.
Examples:
Clean('foo', ['bar', 'baz'])
Clean('dist', env.Program('hello', 'hello.c'))
Clean(['foo', 'bar'], 'something_else_to_clean')
As a special case, the source_scanner keyword argument can be used to specify a Scanner object that will be used to scan the sources. (The global DirScanner object can be used if any of the sources will be directories that must be scanned on-disk for changes to files that aren't already specified in other Builder of function calls.)
Any other keyword arguments specified override any same-named existing construction variables.
An action can be an external command, specified as a string, or a callable Python object; see "Action Objects," below, for more complete information. Also note that a string specifying an external command may be preceded by an @ (at-sign) to suppress printing the command in question, or by a - (hyphen) to ignore the exit status of the external command. Examples:
env.Command('foo.out', 'foo.in',
"$FOO_BUILD < $SOURCES > $TARGET")
env.Command('bar.out', 'bar.in',
["rm -f $TARGET",
"$BAR_BUILD < $SOURCES > $TARGET"],
ENV = {'PATH' : '/usr/local/bin/'})
def rename(env, target, source):
import os
os.rename('.tmp', str(target[0]))
env.Command('baz.out', 'baz.in',
["$BAZ_BUILD < $SOURCES > .tmp",
rename ])
env.Command('ddd.list', Dir('ddd'), 'ls -l $SOURCE > $TARGET')
env['DISTDIR'] = 'destination/directory'
env.Command(env.Dir('$DISTDIR')), None, make_distdir)
env2 = env.Clone() env3 = env.Clone(CCFLAGS = '-g')
def MyTool(env): env['FOO'] = 'bar' env4 = env.Clone(tools = ['msvc', MyTool])
The optional specified module will be added to the beginning of all repository path names; this can be used, in essence, to strip initial directory names from the repository path names, so that you only have to replicate part of the repository directory hierarchy in your local build directory:
# Will fetch foo/bar/src.c
# from /usr/local/CVSROOT/foo/bar/src.c.
env.SourceCode('.', env.CVS('/usr/local/CVSROOT'))
# Will fetch bar/src.c
# from /usr/local/CVSROOT/foo/bar/src.c.
env.SourceCode('.', env.CVS('/usr/local/CVSROOT', 'foo'))
# Will fetch src.c
# from /usr/local/CVSROOT/foo/bar/src.c.
env.SourceCode('.', env.CVS('/usr/local/CVSROOT', 'foo/bar'))
Multiple targets should be specified as separate arguments to the Default() method, or as a list. Default() will also accept the Node returned by any of a construction environment's builder methods. Examples:
Default('foo', 'bar', 'baz')
env.Default(['a', 'b', 'c'])
hello = env.Program('hello', 'hello.c')
env.Default(hello)
The current list of targets added using the Default() function or method is available in the DEFAULT_TARGETS list; see below.
env.Depends('foo', 'other-input-file-for-foo')
dict = env.Dictionary()
cc_dict = env.Dictionary('CC', 'CCFLAGS', 'CCCOM')
Directory Nodes can be used anywhere you would supply a string as a directory name to a Builder method or function. Directory Nodes have attributes and methods that are useful in many situations; see "File and Directory Nodes," below.
This SConstruct:
env=Environment()
print env.Dump('CCCOM')
env=Environment() print env.Dump()
{ 'AR': 'ar',
'ARCOM': '$AR $ARFLAGS $TARGET $SOURCESRANLIB $RANLIBFLAGS $TARGET',
'ARFLAGS': ['r'],
'AS': 'as',
'ASCOM': '$AS $ASFLAGS -o $TARGET $SOURCES',
'ASFLAGS': [],
...
EnsurePythonVersion(2,2)
EnsureSConsVersion(0,14) EnsureSConsVersion(0,96,90)
env = Environment()
# Make env available for all SConscript files to Import().
Export("env")
package = 'my_name'
# Make env and package available for all SConscript files:.
Export("env", "package")
# Make env and package available for all SConscript files:
Export(["env", "package"])
# Make env available using the name debug:.
Export({"debug":env})
File Nodes can be used anywhere you would supply a string as a file name to a Builder method or function. File Nodes have attributes and methods that are useful in many situations; see "File and Directory Nodes," below.
foo = env.FindFile('foo', ['dir1', 'dir2'])
Note that use of FindPathDirs() is generally preferable to writing your own path_function for the following reasons: 1) The returned list will contain all appropriate directories found in source trees (when BuildDir() is used) or in code repositories (when Repository() or the -Y option are used). 2) scons will identify expansions of variable that evaluate to the same list of directories as, in fact, the same list, and avoid re-scanning the directories for files, when possible.
Example:
def my_scan(node, env, path, arg):
# Code to scan file contents goes here...
return include_files
scanner = Scanner(name = 'myscanner',
function = my_scan,
path_function = FindPathDirs('MYPATH'))
foo = Object('foo.c')
bar = Object('bar.c')
# Because `foo' and `bar' are lists returned by the Object() Builder,
# `objects' will be a list containing nested lists:
objects = ['f1.o', foo, 'f2.o', bar, 'f3.o']
# Passing such a list to another Builder is all right because
# the Builder will flatten the list automatically:
Program(source = objects)
# If you need to manipulate the list directly using Python, you need to
# call Flatten() yourself, or otherwise handle nested lists:
for object in Flatten(objects):
print str(object)
env.Ignore('foo', 'foo.c')
env.Ignore('bar', ['bar1.h', 'bar2.h'])
Import("env")
Import("env", "variable")
Import(["env", "variable"])
Import("*")
env.Install(dir = '/usr/local/bin', source = ['foo', 'bar'])
env.InstallAs(target = '/usr/local/bin/foo',
source = 'foo_debug')
env.InstallAs(target = ['../lib/libfoo.a', '../lib/libbar.a'],
source = ['libFOO.a', 'libBAR.a'])
By default, duplicate values are eliminated; you can, however, specify unique=0 to allow duplicate values to be added. When eliminating duplicate values, any construction variables that end with the string PATH keep the left-most unique value. All other construction variables keep the right-most unique value.
Examples:
# Add an optimization flag to $CCFLAGS.
env.MergeFlags('-O3')
# Combine the flags returned from running pkg-config with an optimization
# flag and merge the result into the construction variables.
env.MergeFlags(['!pkg-config gtk+-2.0 --cflags', '-O3'])
env.MergeFlags(['-O3',
'!pkg-config gtk+-2.0 --cflags --libs',
'!pkg-config libpng12 --cflags --libs'])
Multiple files should be specified either as separate arguments to the NoCache() method, or as a list. NoCache() will also accept the return value of any of the construction environment Builder methods.
Calling NoCache() on directories and other non-File Node types has no effect because only File Nodes are cached.
Examples:
NoCache('foo.elf')
NoCache(env.Program('hello', 'hello.c'))
Multiple files or directories should be specified either as separate arguments to the NoClean() method, or as a list. NoClean() will also accept the return value of any of the construction environment Builder methods.
Calling NoClean() for a target overrides calling Clean() for the same target, and any targets passed to both functions will not be removed by the -c option.
Examples:
NoClean('foo.elf')
NoClean(env.Program('hello', 'hello.c'))
Interpreted options and the construction variables they affect are as specified for the env.ParseFlags() method (which thie method calls). See that method's description, below, for a table of options and construction variables.
By default, it is not an error if the specified filename does not exist. The optional must_exit argument may be set to a non-zero value to have scons throw an exception and generate an error if the file does not exist, or is otherwise inaccessible.
The optional only_one argument may be set to a non-zero value to have scons thrown an exception and generate an error if the file contains dependency information for more than one target. This can provide a small sanity check for files intended to be generated by, for example, the gcc -M flag, which should typically only write dependency information for one output file into a corresponding .d file.
The filename and all of the files listed therein will be interpreted relative to the directory of the SConscript file which calls the ParseDepends function.
If the first character in any string is an exclamation mark (!), the rest of the string is executed as a command, and the output from the command is parsed as GCC tool chain command-line flags and added to the resulting dictionary.
Flag values are translated accordig to the prefix found, and added to the following construction variables:
-arch CCFLAGS, LINKFLAGS -D CPPDEFINES -framework FRAMEWORKS -frameworkdir= FRAMEWORKPATH -include CCFLAGS -isysroot CCFLAGS, LINKFLAGS -I CPPPATH -l LIBS -L LIBPATH -mno-cygwin CCFLAGS, LINKFLAGS -mwindows LINKFLAGS -pthread CCFLAGS, LINKFLAGS -std= CFLAGS -Wa, ASFLAGS, CCFLAGS -Wl,-rpath= RPATH -Wl,-R, RPATH -Wl,-R RPATH -Wl, LINKFLAGS -Wp, CPPFLAGS - CCFLAGS + CCFLAGS, LINKFLAGS
Examples (all of which produce the same result):
dict = env.ParseFlags('-O2 -Dfoo -Dbar=1')
dict = env.ParseFlags('-O2', '-Dfoo', '-Dbar=1')
dict = env.ParseFlags(['-O2', '-Dfoo -Dbar=1'])
dict = env.ParseFlags('-O2', '!echo -Dfoo -Dbar=1')
env.SourceCode('.', env.Perforce())
env = Environment(platform = Platform('win32'))
env.Platform('posix')
env.Prepend(CCFLAGS = '-g ', FOO = ['foo.yyy'])
print 'before:',env['ENV']['INCLUDE']
include_path = '/foo/bar:/foo'
env.PrependENVPath('INCLUDE', include_path)
print 'after:',env['ENV']['INCLUDE']
yields:
before: /biz:/foo
after: /foo/bar:/foo:/biz
env.PrependUnique(CCFLAGS = '-g', FOO = ['foo.yyy'])
env.SourceCode('.', env.RCS())
env.Replace(CCFLAGS = '-g', FOO = 'foo.xxx')
To scons, a repository is a copy of the source tree, from the top-level directory on down, which may contain both source files and derived files that can be used to build targets in the local source tree. The canonical example would be an official source tree maintained by an integrator. If the repository contains derived files, then the derived files should have been built using scons, so that the repository contains the necessary signature information to allow scons to figure out when it is appropriate to use the repository copy of a derived file, instead of building one locally.
Note that if an up-to-date derived file already exists in a repository, scons will not make a copy in the local directory tree. In order to guarantee that a local copy will be made, use the Local() method.
Return("foo")
Return(["foo", "bar"])
env.SourceCode('.', env.SCCS())
The first way you can call SConscript() is to explicitly specify one or more scripts as the first argument. A single script may be specified as a string; multiple scripts must be specified as a list (either explicitly or as created by a function like Split()).
The second way you can call SConscript() is to specify a list of (sub)directory names as a dirs=subdirs keyword argument. In this case, scons will, by default, execute a subsidiary configuration file named SConscript in each of the specified directories. You may specify a name other than SConscript by supplying an optional name=script keyword argument.
The optional exports argument provides a list of variable names or a dictionary of named values to export to the script(s). These variables are locally exported only to the specified script(s), and do not affect the global pool of variables used by the Export() function. The subsidiary script(s) must use the Import() function to import the variables.
The optional build_dir argument specifies that all of the target files (for example, object files and executables) that would normally be built in the subdirectory in which script resides should actually be built in build_dir. build_dir is interpreted relative to the directory of the calling SConscript file.
The optional src_dir argument specifies that the source files from which the target files should be built can be found in src_dir. src_dir is interpreted relative to the directory of the calling SConscript file.
By default, scons will link or copy (depending on the platform) all the source files into the build directory. This behavior may be disabled by setting the optional duplicate argument to 0 (it is set to 1 by default), in which case scons will refer directly to the source files in their source directory when building target files. (Setting duplicate=0 is usually safe, and always more efficient than the default of duplicate=1, but it may cause build problems in certain end-cases, such as compiling from source files that are generated by the build.)
Any variables returned by script using Return() will be returned by the call to SConscript().
Examples:
SConscript('subdir/SConscript')
foo = SConscript('sub/SConscript', exports='env')
SConscript('dir/SConscript', exports=['env', 'variable'])
SConscript('src/SConscript', build_dir='build', duplicate=0)
SConscript('bld/SConscript', src_dir='src', exports='env variable')
SConscript(dirs=['sub1', 'sub2'])
SConscript(dirs=['sub3', 'sub4'], name='MySConscript')
SConscriptChdir(0) env.SConscriptChdir(0)
You may enable and disable this ability by calling SConscriptChdir() multiple times:
env = Environment()
SConscriptChdir(0)
SConscript('foo/SConscript') # will not chdir to foo
env.SConscriptChdir(1)
SConscript('bar/SConscript') # will chdir to bar
If file is None, then scons will store file signatures in a separate .sconsign file in each directory, not in one global database file. (This was the default behavior prior to SCons 0.96.91 and 0.97.)
The optional dbm_module argument can be used to specify which Python database module The default is to use a custom SCons.dblite module that uses pickled Python data structures, and which works on all Python versions from 1.5.2 on.
Examples:
# Explicitly stores signatures in ".sconsign.dblite"
# in the top-level SConstruct directory (the
# default behavior).
SConsignFile()
# Stores signatures in the file "etc/scons-signatures"
# relative to the top-level SConstruct directory.
SConsignFile("etc/scons-signatures")
# Stores signatures in the specified absolute file name.
SConsignFile("/home/me/SCons/signatures")
# Stores signatures in a separate .sconsign file
# in each directory.
SConsignFile(None)
env.SetDefault(FOO = 'foo')
if not env.has_key('FOO'): env['FOO'] = 'foo'
SetOption('max_drift', 1)
For any non-existent source files, scons will search up the directory tree and use the first SourceCode builder it finds. The specified builder may be None, in which case scons will not use a builder to fetch source files for the specified entries, even if a SourceCode builder has been specified for a directory higher up the tree.
scons will, by default, fetch files from SCCS or RCS subdirectories without explicit configuration. This takes some extra processing time to search for the necessary source code management files on disk. You can avoid these extra searches and speed up your build a little by disabling these searches as follows:
env.SourceCode('.', None)
scons provides a set of canned factory functions that return appropriate Builders for various popular source code management systems. Canonical examples of invocation include:
env.SourceCode('.', env.BitKeeper('/usr/local/BKsources'))
env.SourceCode('src', env.CVS('/usr/local/CVSROOT'))
env.SourceCode('/', env.RCS())
env.SourceCode(['f1.c', 'f2.c'], env.SCCS())
env.SourceCode('no_source.c', None)
By default, leading or trailing white space will be removed from the result. and all sequences of white space will be compressed to a single space character. Additionally, any $( and $) character sequences will be stripped from the returned string, The optional raw argument may be set to 1 if you want to preserve white space and $(-$) sequences. The raw argument may be set to 2 if you want to strip all characters between any $( and $) pairs (as is done for signature calculation).
The optional target and source keyword arguments must be set to lists of target and source nodes, respectively, if you want the $TARGET, $TARGETS, $SOURCE and $SOURCES to be available for expansion. This is usually necessary if you are calling env.subst() from within a Python function used as an SCons action.
By default, all returned values are converted to their string representation. The optional conv argument may specify a conversion function that will be used in place of the default. For example, if you want Python objects (including SCons Nodes) to be returned as Python objects, you can use the Python lambda idiom to pass in an unnamed function that simply returns its unconverted argument.
print env.subst("The C compiler is: $CC")
def compile(target, source, env):
sourceDir = env.subst("${SOURCE.srcdir}",
target=target,
source=source)
source_nodes = env.subst('$EXPAND_TO_NODELIST',
conv=lambda x: x)