Chapter 10. Controlling a Build From the Command Line

Software builds are rarely completely static, so SCons gives you a number of ways to help control build execution via instructions on the command line. The arguments that can be specified on the command line are broken down into three types:

Options

Command-line arguments that begin with a - (hyphen) characters are called options. SCons provides ways for you to examine and act on options and their values, as well as the ability to define custom options for your project. See Section 10.1, “Command-Line Options”, below.

Variables

Command-line arguments containing an = (equal sign) character are called build variables (or just variables). SCons provides direct access to all of the build variable settings from the command line, as well as a higher-level interface that lets you define known build variables, including defining types, default values, help text, and automatic validation, as well as applying those to a construction environment. See Section 10.2, “Command-Line variable=value Build Variables”, below.

Targets

Command-line arguments that are neither options nor build variables (that is, do not begin with a hyphen and do not contain an equal sign) are considered targets that you are telling SCons to build. SCons provides access to the list of specified targets, as well as ways to set the default list of targets from within the SConscript files. See Section 10.3, “Command-Line Targets”, below.

10.1. Command-Line Options

SCons has many command-line options that control its behavior. A command-line option always begins with one or two hyphen (-) characters. The SCons manual page contains the description of the current options (see https://scons.org/doc/production/HTML/scons-man.html).

10.1.1. How To Avoid Typing Command-Line Options Each Time: the SCONSFLAGS Environment Variable

You may find yourself using certain command-line options every time you run SCons. For example, you might find it saves time to specify -j 2 to have SCons run up to two build commands in parallel. To avoid having to type -j 2 by hand every time, you can set the external environment variable SCONSFLAGS to a string containing -j 2, as well as any other command-line options that you want SCons to always use. SCONSFLAGS is an exception to the usual rule that SCons itself avoids looking at environment variables from the shell you are running.

If, for example, you are using a POSIX shell such as bash or zsh and you always want SCons to use the -Q option, you can set the SCONSFLAGS environment as follows:

% scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
    ... [build output] ...
scons: done building targets.
% export SCONSFLAGS="-Q"
% scons
    ... [build output] ...

For csh-style shells on POSIX systems you can set the SCONSFLAGS environment variable as follows:

$ setenv SCONSFLAGS "-Q"
      

For the Windows command shell (cmd) you can set the SCONSFLAGS environment variable as follows:

C:\Users\foo> set SCONSFLAGS="-Q"
      

To set SCONSFLAGS more permanently you can add the setting to the shell's startup file on POSIX systems, and on Windows you can use the System Properties control panel applet to select Environment Variables and set it there.

10.1.2. Getting Values Set by Command-Line Options: the GetOption Function

The GetOption function lets you query the values set by the various command-line options.

One use case for GetOption is to check the operation mode in order to bypass some steps, for example, checking whether the -h (or --help) option was given. Normally, SCons does not print its help text until after it has read all of the SConscript files, since any SConscript can make additions to the help text. Of course, reading all of the SConscript files takes extra time. If you know that your configuration does not define any additional help text in subsidiary SConscript files, you can speed up displaying the command-line help by using a GetOption query as a guard for whether to load the subsidiary SConscript files:

if not GetOption('help'):
    SConscript('src/SConscript', export='env')
      

The same technique can be used to special-case the clean (GetOption('clean')) and no-execute (GetOption('no_exec')) modes.

In general, the string that you pass to the GetOption function to fetch the value of a command-line option setting is the same as the "most common" long option name (beginning with two hyphen characters), although there are some exceptions. The list of SCons command-line options and the GetOption strings for fetching them, are available in the Section 10.1.4, “Strings for Getting or Setting Values of SCons Command-Line Options” section, below.

GetOption can be used to retrieve the values of options defined by calls to AddOption. A GetOption call must appear after the AddOption call for that option (unlike the defining of build targets, this is a case where "order matters" in SCons). If the AddOption call supplied a dest keyword argument, a string with that name is what to pass as the argument to GetOption, otherwise it is a (possibly modified) version of the first long option name - see AddOption.

10.1.3. Setting Values of Command-Line Options: the SetOption Function

You can also set the values of certain (but not all) SCons command-line options from within the SConscript files by using the SetOption function. The strings that you use to set the values of SCons command-line options are available in the Section 10.1.4, “Strings for Getting or Setting Values of SCons Command-Line Options” section, below.

One use of the SetOption function is to specify a value for the -j or --jobs option, so that you get the improved performance of a parallel build without having to specify the option by hand. A complicating factor is that a good value for the -j option is somewhat system-dependent. One rough guideline is that the more processors your system has, the higher you want to set the -j value, in order to take advantage of the number of CPUs.

For example, suppose the administrators of your development systems have standardized on setting a NUM_CPU environment variable to the number of processors on each system. A little bit of Python code to access the environment variable and the SetOption function provides the right level of flexibility:

import os

num_cpu = int(os.environ.get('NUM_CPU', 2))
SetOption('num_jobs', num_cpu)
print("running with -j %s" % GetOption('num_jobs'))
        

The above snippet of code sets the value of the --jobs option to the value specified in the NUM_CPU environment variable. (This is one of the exception cases where the string is spelled differently from the command-line option. The string for fetching or setting the --jobs value is num_jobs for historical reasons.) The code in this example prints the num_jobs value for illustrative purposes. It uses a default value of 2 to provide some minimal parallelism even on single-processor systems:

% scons -Q
running with -j 2
scons: `.' is up to date.

But if the NUM_CPU environment variable is set, then use that for the default number of jobs:

% export NUM_CPU="4"
% scons -Q
running with -j 4
scons: `.' is up to date.

But any explicit -j or --jobs value you specify on the command line is used first, whether the NUM_CPU environment variable is set or not:

% scons -Q -j 7
running with -j 7
scons: `.' is up to date.
% export NUM_CPU="4"
% scons -Q -j 3
running with -j 3
scons: `.' is up to date.

10.1.4. Strings for Getting or Setting Values of SCons Command-Line Options

The strings that you can pass to the GetOption and SetOption functions usually correspond to the first long-form option name (that is, name beginning with two hyphen characters: --), after replacing any remaining hyphen characters with underscores.

SetOption works for options added with AddOption, but only if they were created with settable=True in the call to AddOption (only available in SCons 4.8.0 and later).

The full list of strings and the variables they correspond to is as follows:

String for GetOption and SetOptionCommand-Line Option(s)
cache_debug--cache-debug
cache_disable--cache-disable
cache_force--cache-force
cache_show--cache-show
clean-c, --clean, --remove
config--config
directory-C, --directory
diskcheck--diskcheck
duplicate--duplicate
file-f, --file, --makefile , --sconstruct
help-h, --help
ignore_errors--ignore-errors
implicit_cache--implicit-cache
implicit_deps_changed--implicit-deps-changed
implicit_deps_unchanged--implicit-deps-unchanged
interactive--interact, --interactive
keep_going-k, --keep-going
max_drift--max-drift
no_exec-n, --no-exec, --just-print, --dry-run, --recon
no_site_dir--no-site-dir
num_jobs-j, --jobs
profile_file--profile
question-q, --question
random--random
repository-Y, --repository, --srcdir
silent-s, --silent, --quiet
site_dir--site-dir
stack_size--stack-size
taskmastertrace_file--taskmastertrace
warn--warn --warning

10.1.5. Adding Custom Command-Line Options: the AddOption Function

You can also define your own command-line options for the project with the AddOption function. The AddOption function takes the same arguments as the add_option method from the Python standard library module optparse [2] (see https://docs.python.org/3/library/optparse.html).

Once you add a custom command-line option with the AddOption function, the value of the option (if any) is immediately available using the GetOption function. The argument to GetOption must be the name of the variable which holds the option. If the dest keyword argument to AddOption is specified, the value is the variable name. given. If not given, it is the name (without the leading hyphens) of the first long option name given to AddOption after replacing any remaining hyphen characters with underscores, since hyphens are not legal in Python identifier names.

SetOption works for options added with AddOption, but only if they were created with settable=True in the call to AddOption (only available in SCons 4.8.0 and later).

One useful example of using this functionality is to provide a --prefix to help describe where to install files:

AddOption(
    '--prefix',
    dest='prefix',
    type='string',
    nargs=1,
    action='store',
    metavar='DIR',
    help='installation prefix',
)

env = Environment(PREFIX=GetOption('prefix'))

installed_foo = env.Install('$PREFIX/usr/bin', 'foo.in')
Default(installed_foo)
        

The above code uses the GetOption function to set the $PREFIX construction variable to a value you specify with a command-line option of --prefix. Because $PREFIX expands to a null string if it's not initialized, running SCons without the option of --prefix installs the file in the /usr/bin/ directory:

% scons -Q -n
Install file: "foo.in" as "/usr/bin/foo.in"

But specifying --prefix=/tmp/install on the command line causes the file to be installed in the /tmp/install/usr/bin/ directory:

% scons -Q -n --prefix=/tmp/install
Install file: "foo.in" as "/tmp/install/usr/bin/foo.in"

Note

The optparse parser which SCons uses allows option-arguments to follow their options after either an = or space separator, however the latter form does not work well in SCons for added options and should be avoided. SCons does not place an ordering constraint on the types of command-line arguments, so while --input=ARG is unambiguous, for --input ARG it is not possible to tell without instructions whether ARG is an argument belonging to the input option or a standalone word. SCons considers words on the command line which do not begin with hyphen as either command-line build variables or command-line targets, both of which are made available for use in an SConscript (see the immediately following sections for details). Thus, they must be collected before SConscript processing takes place. AddOption calls do provide the necessary instructions to resolve the ambiguity, but as they appear in SConscript files, SCons does not have the information early enough, and unexpected things may happen, such as option-arguments appearing in the list of targets, and processing exceptions due to missing option-arguments.

As a result, this usage style should be avoided when invoking scons. For single-argument options, tell your users to use the --input=ARG form on the command line. For multiple-argument options (nargs value greater than one), set nargs to one in the AddOption call and either: combine the option-arguments into one word with a separator, and parse the result in your own code (see the built-in --debug option, which allows specifying multiple arguments as a single comma-separated word, for an example of such usage); or allow the option to be specified multiple times by setting action='append'. Both methods can be supported at the same time.



[2] The AddOption function is, in fact, implemented using a subclass of optparse.OptionParser.