15.7. Variant Build Examples

The variant_dir keyword argument of the SConscript function provides everything we need to show how easy it is to create variant builds using SCons. Suppose, for example, that we want to build a program for both Windows and Linux platforms, but that we want to build it in directory on a network share with separate side-by-side build directories for the Windows and Linux versions of the program. We have to do a little bit of work to construct paths, to make sure unwanted location dependencies don't creep in. The top-relative path reference can be useful here. To avoid writing conditional code based on platform, we can build the variant_dir path dynamically:

platform = ARGUMENTS.get('OS', Platform())

include = "#export/$PLATFORM/include"
lib = "#export/$PLATFORM/lib"
bin = "#export/$PLATFORM/bin"

env = Environment(
    PLATFORM=platform,
    BINDIR=bin,
    INCDIR=include,
    LIBDIR=lib,
    CPPPATH=[include],
    LIBPATH=[lib],
    LIBS='world',
)

Export('env')

env.SConscript('src/SConscript', variant_dir='build/$PLATFORM')
    

This SConstruct file, when run on a Linux system, yields:

% scons -Q OS=linux
Install file: "build/linux/world/world.h" as "export/linux/include/world.h"
cc -o build/linux/hello/hello.o -c -Iexport/linux/include build/linux/hello/hello.c
cc -o build/linux/world/world.o -c -Iexport/linux/include build/linux/world/world.c
ar rc build/linux/world/libworld.a build/linux/world/world.o
ranlib build/linux/world/libworld.a
Install file: "build/linux/world/libworld.a" as "export/linux/lib/libworld.a"
cc -o build/linux/hello/hello build/linux/hello/hello.o -Lexport/linux/lib -lworld
Install file: "build/linux/hello/hello" as "export/linux/bin/hello"

The same SConstruct file on Windows would build:

C:\>scons -Q OS=windows
Install file: "build/windows/world/world.h" as "export/windows/include/world.h"
cl /Fobuild\windows\hello\hello.obj /c build\windows\hello\hello.c /nologo /Iexport\windows\include
cl /Fobuild\windows\world\world.obj /c build\windows\world\world.c /nologo /Iexport\windows\include
lib /nologo /OUT:build\windows\world\world.lib build\windows\world\world.obj
Install file: "build/windows/world/world.lib" as "export/windows/lib/world.lib"
link /nologo /OUT:build\windows\hello\hello.exe /LIBPATH:export\windows\lib world.lib build\windows\hello\hello.obj
embedManifestExeCheck(target, source, env)
Install file: "build/windows/hello/hello.exe" as "export/windows/bin/hello.exe"

In order to build several variants at once when using the variant_dir argument to SConscript, you can call the function repeatedely - this example does so in a loop. Note that the SConscript trick of passing a list of script files, or a list of source directories, does not work with variant_dir, SCons allows only a single SConscript to be given if variant_dir is used.

env = Environment(OS=ARGUMENTS.get('OS'))
for os in ['newell', 'post']:
    SConscript('src/SConscript', variant_dir='build/' + os)