It's often useful to keep any built files completely separate from the source files. Consider if you have a project to build software for a variety of different controller hardware. The boards are able to share a lot of code, so it makes sense to keep them in the same source tree, but certain build options in the source code and header files differ. If you build "Controller A" first, then "Controller B", on the "Controller B" build everything would have to be rebuilt, because SCons recognizes that the build instructions are different from those used in the "Controller A" build for each target - the build instructions are part of SCons's out-of-date calculation. Now when you go back and build for "Controller A", things have to be rebuilt from scratch again for the same reason. However, if you can separate the locations of the output files, this problem can be avoided. You can even set up to do both builds in one invocation of SCons.
You can enable this separation by establishing one or more variant directory trees that are used to perform the build in, and thus provide a unique home for object files, libraries, and executable programs, etc. for a specific flavor, or variant, of build. SCons tracks targets by their path, so when the variant directory is included, objects belonging to "Controller A" can have different build instructions than those belonging to "Controller B" without triggering ping-ponging rebuilds.
SCons provides two ways to do this,
one through the SConscript
function that we've already seen,
and the second through a more flexible VariantDir
function.
Historical note: the VariantDir
function
used to be called BuildDir
, a name which was
removed because the SCons functionality
differs from a familiar model of a "build directory"
implemented by other build systems like GNU Autotools.
You might still find references to the old name on
the Internet in postings about SCons, but it no longer works.
The most straightforward way to establish a variant directory tree
relies the fact that the usual way to
set up a build hierarchy is to have an
SConscript file in the source subdirectory.
If you pass a variant_dir
argument to the
SConscript
function call:
SConscript('src/SConscript', variant_dir='build')
SCons will then build all of the files in
the build
subdirectory:
%ls src
SConscript hello.c %scons -Q
cc -o build/hello.o -c build/hello.c cc -o build/hello build/hello.o %ls src
SConscript hello.c %ls build
SConscript hello hello.c hello.o
No files were built in src
, they went to build
.
The build output might show a bit of a surprise:
the object file
build/hello.o
and the executable file
build/hello
were built in the build
subdirectory,
as expected.
But even though our hello.c
file lives in the src
subdirectory,
SCons has actually compiled a
build/hello.c
file
to create the object file,
and that file is now seen in build
.
What's happened is that SCons has duplicated
the hello.c
file from the src
subdirectory
to the build
subdirectory,
and built the program from there (it also duplicated SConscript
).
The next section explains why SCons does this.