10.2. Command-Line `variable`=`value` Build Variables
Prev | Chapter 10. Controlling a Build From the Command Line | Next

## 10.2. Command-Line `variable`=`value` Build Variables

You may want to control various aspects of your build by allowing `variable`=`value` values to be specified on the command line. For example, suppose you want to be able to build a debug version of a program by running SCons as follows:

    % scons -Q debug=1

SCons provides an `ARGUMENTS` dictionary that stores all of the `variable`=`value` assignments from the command line. This allows you to modify aspects of your build in response to specifications on the command line.

The following code sets the `$CCFLAGS` construction variable in response to the `debug` flag being set in the `ARGUMENTS` dictionary:

    env = Environment()
    debug = ARGUMENTS.get('debug', 0)
    if int(debug):
        env.Append(CCFLAGS='-g')
    env.Program('prog.c')

This results in the `-g` compiler option being used when `debug=1` is used on the command line:

    % scons -Q debug=0
    cc -o prog.o -c prog.c
    cc -o prog prog.o
    % scons -Q debug=0
    scons: `.' is up to date.
    % scons -Q debug=1
    cc -o prog.o -c -g prog.c
    cc -o prog prog.o
    % scons -Q debug=1
    scons: `.' is up to date.

### Note

Two usage notes (both shown in the example above):

- No matter how you intend to use them, the values read from a command line (i.e., external to the program) are always strings. You may need to do type conversion.

- When you retrieve from the `ARGUMENTS` dictionary, it is useful to use the Python dictionary `get` method, so you can supply a default value if the variable is not given on the command line. Otherwise, the build will fail with a `KeyError` if the variable is not set.

SCons keeps track of the precise build command used to build each object file, and as a result can determine that the object and executable files need rebuilding when the value of the `debug` argument has changed.

The `ARGUMENTS` dictionary has two minor drawbacks. First, because it is a dictionary, it can only map each keyword to one value, and thus only "remembers" the last setting for each keyword on the command line. This makes the `ARGUMENTS` dictionary less than ideal if you want to allow specifying multiple values on the command line for a given keyword. Second, it does not preserve the order in which the variable settings were specified, which is a problem if you want the configuration to behave differently in response to the order in which the build variable settings were specified on the command line (Python versions since 3.6 now maintain dictionaries in insertion order, so this problem is mitigated).

To accommodate these requirements, SCons also provides an `ARGLIST` variable that gives you direct access to build variable settings from the command line, in the exact order they were specified, and without removing any duplicate settings. Each element in the `ARGLIST` variable is itself a two-element list containing the keyword and the value of the setting, and you must loop through, or otherwise select from, the elements of `ARGLIST` to process the specific settings you want in whatever way is appropriate for your configuration. For example, the following code lets you add to the `CPPDEFINES` construction variable by specifying multiple `define=` settings on the command line:

    cppdefines = []
    for key, value in ARGLIST:
        if key == 'define':
            cppdefines.append(value)
    env = Environment(CPPDEFINES=cppdefines)
    env.Object('prog.c')

Yields the following output:

    % scons -Q define=FOO
    cc -o prog.o -c -DFOO prog.c
    % scons -Q define=FOO define=BAR
    cc -o prog.o -c -DFOO -DBAR prog.c

Note that the `ARGLIST` and `ARGUMENTS` variables do not interfere with each other, but rather provide slightly different views into how you specified `variable`=`value` settings on the command line. You can use both variables in the same SCons configuration. In general, the `ARGUMENTS` dictionary is more convenient to use, (since you can just fetch variable settings through Python dictionary access), and the `ARGLIST` list is more flexible (since you can examine the specific order in which the command-line variable settings were given).

### 10.2.1. Controlling Command-Line Build Variables

Being able to use a command-line build variable like `debug=1` is handy, but it can be a chore to write specific Python code to recognize each such variable, check for errors and provide appropriate messages, and apply the values to a construction variable. To help with this, SCons provides a `Variables` container class to hold definitions of such build variables, and a mechanism to apply the build variables to a construction environment. This allows you to control how the build variables affect construction environments.

For example, suppose that you want to set a `RELEASE` construction variable on the command line whenever the time comes to build a program for release, and that the value of this variable should be added to the build command with the appropriate define to pass the value to the C compiler. Here's how you might do that by setting the appropriate value in a dictionary for the `$CPPDEFINES` construction variable:

    vars = Variables(None, ARGUMENTS)
    vars.Add('RELEASE', default=0)
    env = Environment(variables=vars, CPPDEFINES={'RELEASE_BUILD': '${RELEASE}'})
    env.Program(['foo.c', 'bar.c'])

This `SConstruct` snippet first creates a `Variables` object which uses the values from the command-line variables dictionary `ARGUMENTS`. It then uses the object's `Add` method to indicate that the `RELEASE` variable can be set on the command line, and that if not set the default value is `0`. The newly created `Variables` object is passed to the `Environment` call used to create the construction environment using a `variables` keyword argument. This then allows you to set the `RELEASE` build variable on the command line and have the variable show up in the command line used to build each object from a C source file:

    % scons -Q RELEASE=1
    cc -o bar.o -c -DRELEASE_BUILD=1 bar.c
    cc -o foo.o -c -DRELEASE_BUILD=1 foo.c
    cc -o foo foo.o bar.o

The `Variables()` call in this example looks a little awkward. The function takes two optional arguments: a script name and a dictionary. In order to specify the dictionary as the second argument, you must provide the script argument as the first; since there's actually no script, use `None` as a sentinel value. However, if you omit all the arguments, the default behavior is to read from the `ARGUMENTS` dictionary anyway, which is what we want. The example shows it this way because the arguments were introduced in this order, but you should feel free to just leave off the arguments if the default behavior is what you want.

Historical note: In old SCons (prior to 0.98.1 from 2008), these build variables were known as "command-line build options." At that time, the class was named `Options` and the predefined functions to construct options were named `BoolOption`, `EnumOption`, `ListOption`, `PathOption`, `PackageOption` and `AddOptions` (contrast with the current names in Section 10.2.4, “Pre-Defined Build Variable Functions”, below). Because the Internet has a very long memory, you may encounter these names in older `SConscript` files, wiki pages, blog entries, StackExchange articles, etc. These old names no longer work, but a mental substitution of “Variable” for “Option” allows the concepts to transfer to current usage models.

### 10.2.2. Providing Help for Command-Line Build Variables

To make command-line build variables more useful, you may want to provide some help text to describe the available variables when you ask for help (run `scons -h`). You can write this text by hand, but SCons provides some assistance. Variables objects provide a `GenerateHelpText` method to generate text that describes the various variables that have been added to it. The default text includes the help string itself plus other information such as allowed values. (The generated text can also be customized by replacing the `FormatVariableHelpText` method). You then pass the output from this method to the `Help` function:

    vars = Variables()
    vars.Add('RELEASE', help='Set to 1 to build for release', default=0)
    env = Environment(variables=vars)
    Help(vars.GenerateHelpText(env))

scons now displays some useful text when the `-h` option is used:

    % scons -Q -h

    RELEASE: Set to 1 to build for release
        default: 0
        actual: 0

    Use scons -H for help about SCons built-in command-line options.

You can see the help output shows the default value as well as the current actual value of the build variable.

### 10.2.3. Reading Build Variables From a File

Being able to specify the value of a build variable on the command line is useful, but can still become tedious if you have to specify the variable every time you run SCons. To make this easier, you can provide customized build variable settings in a Python script by providing a file name when the `Variables` object is created:

    vars = Variables('custom.py')
    vars.Add('RELEASE', help='Set to 1 to build for release', default=0)
    env = Environment(variables=vars, CPPDEFINES={'RELEASE_BUILD': '${RELEASE}'})
    env.Program(['foo.c', 'bar.c'])
    Help(vars.GenerateHelpText(env))

This then allows you to control the `RELEASE` variable by setting it in the `custom.py` script:

    RELEASE = 1

Note that this file is actually executed like a Python script. Now when you run SCons:

    % scons -Q
    cc -o bar.o -c -DRELEASE_BUILD=1 bar.c
    cc -o foo.o -c -DRELEASE_BUILD=1 foo.c
    cc -o foo foo.o bar.o

And if you change the contents of `custom.py` to:

    RELEASE = 0

The object files are rebuilt appropriately with the new variable:

    % scons -Q
    cc -o bar.o -c -DRELEASE_BUILD=0 bar.c
    cc -o foo.o -c -DRELEASE_BUILD=0 foo.c
    cc -o foo foo.o bar.o

Finally, you can combine both methods with:

    vars = Variables('custom.py', ARGUMENTS)

If both a variables script and a dictionary are supplied, the dictionary is evaluated last, so values from the command line "win" if there are any duplicate keys. This rule allows you to move some common settings to a variables script, but still be able to override those for a given build without changing the script.

### 10.2.4. Pre-Defined Build Variable Functions

SCons provides a number of convenience functions that provide behavior definitions for various types of command-line build variables. These functions all return a tuple which is ready to be passed to the `Add` or `AddVariables` method call. You are of course free to define your own behaviors as well.

#### 10.2.4.1. True/False Values: the `BoolVariable` Build Variable Function

It is often handy to be able to specify a variable that controls a simple Boolean variable with a `true` or `false` value. It would be even more handy to accommodate different preferences for how to represent `true` or `false` values. The `BoolVariable` function makes it easy to accommodate these common representations of `true` or `false`.

The `BoolVariable` function takes three arguments: the name of the build variable, the default value of the build variable, and the help string for the variable. It then returns appropriate information for passing to the `Add` method of a `Variables` object, like so:

    vars = Variables('custom.py')
    vars.Add(BoolVariable('RELEASE', help='Set to build for release', default=False))
    env = Environment(variables=vars, CPPDEFINES={'RELEASE_BUILD': '${RELEASE}'})
    env.Program('foo.c')

With this build variable in place, the `RELEASE` variable can now be enabled by setting it to the value `yes` or `t`:

    % scons -Q RELEASE=yes foo.o
    cc -o foo.o -c -DRELEASE_BUILD=True foo.c

    % scons -Q RELEASE=t foo.o
    cc -o foo.o -c -DRELEASE_BUILD=True foo.c

Other values that equate to `true` include `y`, `1`, `on` and `all`.

Conversely, `RELEASE` may now be given a `false` value by setting it to `no` or `f`:

    % scons -Q RELEASE=no foo.o
    cc -o foo.o -c -DRELEASE_BUILD=False foo.c

    % scons -Q RELEASE=f foo.o
    cc -o foo.o -c -DRELEASE_BUILD=False foo.c

Other values that equate to `false` include `n`, `0`, `off` and `none`.

Lastly, if you try to specify any other value, SCons supplies an appropriate error message:

    % scons -Q RELEASE=bad_value foo.o

    scons: *** Error converting option: 'RELEASE'
    Invalid value for boolean variable: 'bad_value'
    File "/home/my/project/SConstruct", line 3, in <module>

#### 10.2.4.2. Single Value From a Selection: the `EnumVariable` Build Variable Function

Suppose that you want to allow setting a `COLOR` variable that selects a background color to be displayed by an application, but that you want to restrict the choices to a specific set of allowed colors. You can set this up quite easily using the `EnumVariable` function, which takes a list of `allowed_values` in addition to the variable name, default value, and help text arguments:

    vars = Variables('custom.py')
    vars.Add(
        EnumVariable(
            'COLOR',
            help='Set background color',
            default='red',
            allowed_values=('red', 'green', 'blue'),
        )
    )
    env = Environment(variables=vars, CPPDEFINES={'COLOR': '"${COLOR}"'})
    env.Program('foo.c')
    Help(vars.GenerateHelpText(env))

You can now explicitly set the `COLOR` build variable to any of the specified allowed values:

    % scons -Q COLOR=red foo.o
    cc -o foo.o -c -DCOLOR="red" foo.c
    % scons -Q COLOR=blue foo.o
    cc -o foo.o -c -DCOLOR="blue" foo.c
    % scons -Q COLOR=green foo.o
    cc -o foo.o -c -DCOLOR="green" foo.c

But, importantly, an attempt to set `COLOR` to a value that's not in the list generates an error message:

    % scons -Q COLOR=magenta foo.o

    scons: *** Invalid value for enum variable 'COLOR': 'magenta'. Valid values are: ('red', 'green', 'blue')
    File "/home/my/project/SConstruct", line 10, in <module>

This example can also serve to further illustrate help generation: the help message here picks up not only the `help` text, but augments it with information gathered from `allowed_values` and `default`:

    % scons -Q -h

    COLOR: Set background color (red|green|blue)
        default: red
        actual: red

    Use scons -H for help about SCons built-in command-line options.

The `EnumVariable` function also provides a way to map alternate names to allowed values. Suppose, for example, you want to allow the word `navy` to be used as a synonym for `blue`. You do this by adding a `map` dictionary that maps its key values to the desired allowed value:

    vars = Variables('custom.py')
    vars.Add(
        EnumVariable(
            'COLOR',
            help='Set background color',
            default='red',
            allowed_values=('red', 'green', 'blue'),
            map={'navy': 'blue'},
        )
    )
    env = Environment(variables=vars, CPPDEFINES={'COLOR': '"${COLOR}"'})
    env.Program('foo.c')

Now you can supply `navy` on the command line, and SCons translates that into `blue` when it comes time to use the `COLOR` variable to build a target:

    % scons -Q COLOR=navy foo.o
    cc -o foo.o -c -DCOLOR="blue" foo.c

By default, when using the `EnumVariable` function, the allowed values are case-sensitive:

    % scons -Q COLOR=Red foo.o

    scons: *** Invalid value for enum variable 'COLOR': 'Red'. Valid values are: ('red', 'green', 'blue')
    File "/home/my/project/SConstruct", line 10, in <module>
    % scons -Q COLOR=BLUE foo.o

    scons: *** Invalid value for enum variable 'COLOR': 'BLUE'. Valid values are: ('red', 'green', 'blue')
    File "/home/my/project/SConstruct", line 10, in <module>
    % scons -Q COLOR=nAvY foo.o

    scons: *** Invalid value for enum variable 'COLOR': 'nAvY'. Valid values are: ('red', 'green', 'blue')
    File "/home/my/project/SConstruct", line 10, in <module>

The `EnumVariable` function can take an additional `ignorecase` keyword argument that, when set to `1`, tells SCons to allow case differences when the values are specified:

    vars = Variables('custom.py')
    vars.Add(
        EnumVariable(
            'COLOR',
            help='Set background color',
            default='red',
            allowed_values=('red', 'green', 'blue'),
            map={'navy': 'blue'},
            ignorecase=1,
        )
    )
    env = Environment(variables=vars, CPPDEFINES={'COLOR': '"${COLOR}"'})
    env.Program('foo.c')

Which yields the output:

    % scons -Q COLOR=Red foo.o
    cc -o foo.o -c -DCOLOR="Red" foo.c
    % scons -Q COLOR=BLUE foo.o
    cc -o foo.o -c -DCOLOR="BLUE" foo.c
    % scons -Q COLOR=nAvY foo.o
    cc -o foo.o -c -DCOLOR="blue" foo.c
    % scons -Q COLOR=green foo.o
    cc -o foo.o -c -DCOLOR="green" foo.c

Notice that an `ignorecase` value of `1` preserves the case-spelling supplied, only ignoring the case for matching. If you want SCons to translate the names into lower-case, regardless of the case used by the user, specify an `ignorecase` value of `2`:

    vars = Variables('custom.py')
    vars.Add(
        EnumVariable(
            'COLOR',
            help='Set background color',
            default='red',
            allowed_values=('red', 'green', 'blue'),
            map={'navy': 'blue'},
            ignorecase=2,
        )
    )
    env = Environment(variables=vars, CPPDEFINES={'COLOR': '"${COLOR}"'})
    env.Program('foo.c')

Now SCons uses values of `red`, `green` or `blue` regardless of how those values are spelled on the command line:

    % scons -Q COLOR=Red foo.o
    cc -o foo.o -c -DCOLOR="red" foo.c
    % scons -Q COLOR=nAvY foo.o
    cc -o foo.o -c -DCOLOR="blue" foo.c
    % scons -Q COLOR=GREEN foo.o
    cc -o foo.o -c -DCOLOR="green" foo.c

#### 10.2.4.3. Multiple Values From a List: the `ListVariable` Build Variable Function

Another way in which you might want to control a build variable is to specify a list of allowed values, of which one or more can be chosen (where `EnumVariable` allows exactly one value to be chosen). SCons provides this through the `ListVariable` function. If, for example, you want to be able to set a `COLORS` variable to one or more of the allowed values:

    vars = Variables('custom.py')
    vars.Add(
        ListVariable(
            'COLORS', help='List of colors', default=0, names=['red', 'green', 'blue']
        )
    )
    env = Environment(variables=vars, CPPDEFINES={'COLORS': '"${COLORS}"'})
    env.Program('foo.c')

You can now specify a comma-separated list of allowed values, which get translated into a space-separated list for passing to the build commands:

    % scons -Q COLORS=red,blue foo.o
    cc -o foo.o -c -DCOLORS="red -Dblue" foo.c
    % scons -Q COLORS=blue,green,red foo.o
    cc -o foo.o -c -DCOLORS="blue -Dgreen -Dred" foo.c

In addition, the `ListVariable` function lets you specify explicit keywords of `all` or `none` to select all of the allowed values, or none of them, respectively:

    % scons -Q COLORS=all foo.o
    cc -o foo.o -c -DCOLORS="red -Dgreen -Dblue" foo.c
    % scons -Q COLORS=none foo.o
    cc -o foo.o -c -DCOLORS="" foo.c

And, of course, an illegal value still generates an error message:

    % scons -Q COLORS=magenta foo.o

    scons: *** Invalid value(s) for variable 'COLORS': 'magenta'. Valid values are: blue,green,red,all,none
    File "/home/my/project/SConstruct", line 7, in <module>

You can use this last characteristic as a way to enforce at least one of your valid options being chosen by specifying the valid values with the `names` parameter and then giving a value not in that list as the `default` parameter - that way if no value is given on the command line, the default is chosen, SCons errors out as this is invalid. The example is, in fact, set up that way by using `0` as the default:

    % scons -Q foo.o

    scons: *** Invalid value(s) for variable 'COLORS': '0'. Valid values are: blue,green,red,all,none
    File "/home/my/project/SConstruct", line 7, in <module>

This technique works for `EnumVariable` as well.

#### 10.2.4.4. Path Names: the `PathVariable` Build Variable Function

SCons provides a `PathVariable` function to make it easy to create a build variable to control an expected path name. If, for example, you need to define a preprocessor macro that controls the location of a configuration file:

    vars = Variables('custom.py')
    vars.Add(
        PathVariable(
            'CONFIG', help='Path to configuration file', default='/etc/my_config'
        )
    )
    env = Environment(variables=vars, CPPDEFINES={'CONFIG_FILE': '"$CONFIG"'})
    env.Program('foo.c')

This allows you to override the `CONFIG` build variable on the command line as necessary:

    % scons -Q foo.o
    cc -o foo.o -c -DCONFIG_FILE="/etc/my_config" foo.c
    % scons -Q CONFIG=/usr/local/etc/other_config foo.o
    scons: `foo.o' is up to date.

By default, `PathVariable` checks to make sure that the specified path exists and generates an error if it doesn't:

    % scons -Q CONFIG=/does/not/exist foo.o

    scons: *** Path for variable 'CONFIG' does not exist: /does/not/exist
    File "/home/my/project/SConstruct", line 7, in <module>

`PathVariable` provides a number of methods that you can use to change this behavior. If you want to ensure that any specified paths are, in fact, files and not directories, use the `PathVariable.PathIsFile` method as the validation function:

    vars = Variables('custom.py')
    vars.Add(
        PathVariable(
            'CONFIG',
            help='Path to configuration file',
            default='/etc/my_config',
            validator=PathVariable.PathIsFile,
        )
    )
    env = Environment(variables=vars, CPPDEFINES={'CONFIG_FILE': '"$CONFIG"'})
    env.Program('foo.c')

Conversely, to ensure that any specified paths are directories and not files, use the `PathVariable.PathIsDir` method as the validation function:

    vars = Variables('custom.py')
    vars.Add(
        PathVariable(
            'DBDIR',
            help='Path to database directory',
            default='/var/my_dbdir',
            validator=PathVariable.PathIsDir,
        )
    )
    env = Environment(variables=vars, CPPDEFINES={'DBDIR': '"$DBDIR"'})
    env.Program('foo.c')

If you want to make sure that any specified paths are directories, and you would like the directory created if it doesn't already exist, use the `PathVariable.PathIsDirCreate` method as the validation function:

    vars = Variables('custom.py')
    vars.Add(
        PathVariable(
            'DBDIR',
            help='Path to database directory',
            default='/var/my_dbdir',
            validator=PathVariable.PathIsDirCreate,
        )
    )
    env = Environment(variables=vars, CPPDEFINES={'DBDIR': '"$DBDIR"'})
    env.Program('foo.c')

Lastly, if you don't care whether the path exists, is a file, or a directory, use the `PathVariable.PathAccept` method to accept any path you supply:

    vars = Variables('custom.py')
    vars.Add(
        PathVariable(
            'OUTPUT',
            help='Path to output file or directory',
            default=None,
            validator=PathVariable.PathAccept,
        )
    )
    env = Environment(variables=vars, CPPDEFINES={'OUTPUT': '"$OUTPUT"'})
    env.Program('foo.c')

#### 10.2.4.5. Enabled/Disabled Path Names: the `PackageVariable` Build Variable Function

Sometimes you want to give even more control over a path name variable, allowing them to be explicitly enabled or disabled by using `yes` or `no` keywords, in addition to allowing supplying an explicit path name. SCons provides the `PackageVariable` function to support this:

    vars = Variables("custom.py")
    vars.Add(
        PackageVariable("PACKAGE", help="Location package", default="/opt/location")
    )
    env = Environment(variables=vars, CPPDEFINES={"PACKAGE": '"$PACKAGE"'})
    env.Program("foo.c")

When the `SConscript` file uses the `PackageVariable` function, you can still use the default or supply an overriding path name, but you can now explicitly set the specified variable to a value that indicates the package should be enabled (in which case the default should be used) or disabled:

    % scons -Q foo.o
    cc -o foo.o -c -DPACKAGE="/opt/location" foo.c
    % scons -Q PACKAGE=/usr/local/location foo.o
    cc -o foo.o -c -DPACKAGE="/usr/local/location" foo.c
    % scons -Q PACKAGE=yes foo.o
    cc -o foo.o -c -DPACKAGE="True" foo.c
    % scons -Q PACKAGE=no foo.o
    cc -o foo.o -c -DPACKAGE="False" foo.c

### 10.2.5. Adding Multiple Command-Line Build Variables at Once

Lastly, SCons provides a way to add multiple build variables to a `Variables` object at once. Instead of having to call the `Add` method multiple times, you can call the `AddVariables` method with the build variables to be added to the object. Each build variable is specified as either a tuple of arguments, or as a call to one of the pre-defined functions for pre-packaged command-line build variables, which returns such a tuple. Note that an individual tuple cannot take keyword arguments in the way that a call to `Add` or one of the build variable functions can. The order of variables given to `AddVariables` does not matter.

    vars = Variables()
    vars.AddVariables(
        ('RELEASE', 'Set to 1 to build for release', 0),
        ('CONFIG', 'Configuration file', '/etc/my_config'),
        BoolVariable('warnings', help='compilation with -Wall and similar', default=True),
        EnumVariable(
            'debug',
            help='debug output and symbols',
            default='no',
            allowed_values=('yes', 'no', 'full'),
            map={},
            ignorecase=0,
        ),
        ListVariable(
            'shared',
            help='libraries to build as shared libraries',
            default='all',
            names=list_of_libs,
        ),
        PackageVariable(
            'x11', help='use X11 installed here (yes = search some places)', default='yes'
        ),
        PathVariable('qtdir', help='where the root of Qt is installed', default=qtdir),
    )

### 10.2.6. Handling Unknown Command-Line Build Variables: the `UnknownVariables` Function

Humans, of course, occasionally misspell variable names in their command-line settings. SCons does not generate an error or warning for any unknown variables specified on the command line, because it can not reliably tell whether a given "misspelled" variable is really unknown and a potential problem or not. After all, you might be processing arguments directly using `ARGUMENTS` or `ARGLIST` with some Python code in your `SConscript` file.

If, however, you are using a `Variables` object to define a specific set of command-line build variables that you expect to be able to set, you may want to provide an error message or warning of your own if a variable setting is specified that is not among the defined list of variable names known to the `Variables` object. You can do this by calling the `UnknownVariables` method of the `Variables` object to get the settings `Variables` did not recognize:

    vars = Variables(None)
    vars.Add('RELEASE', help='Set to 1 to build for release', default=0)
    env = Environment(variables=vars, CPPDEFINES={'RELEASE_BUILD': '${RELEASE}'})
    unknown = vars.UnknownVariables()
    if unknown:
        print("Unknown variables: %s" % " ".join(unknown.keys()))
        Exit(1)
    env.Program('foo.c')

The `UnknownVariables` method returns a dictionary containing the keywords and values of any variables specified on the command line that are not among the variables known to the `Variables` object (from having been specified using the `Variables` object's `Add` method). The example above, checks whether the dictionary returned by `UnknownVariables` is non-empty, and if so prints the Python list containing the names of the unknown variables and then calls the `Exit` function to terminate SCons:

    % scons -Q NOT_KNOWN=foo
    Unknown variables: NOT_KNOWN

Of course, you can process the items in the dictionary returned by the `UnknownVariables` function in any way appropriate to your build configuration, including just printing a warning message but not exiting, logging an error somewhere, etc.

Note that you must delay the call of `UnknownVariables` until after you have applied the `Variables` object to a construction environment with the `variables=` keyword argument of an `Environment` call: the variables in the object are not fully processed until this has happened.

Prev | Up | Next
Chapter 10. Controlling a Build From the Command Line | Home | 10.3. Command-Line Targets