From 72c578fd4b0b4a5a43e18594339ac4ff26c376dc Mon Sep 17 00:00:00 2001 From: Luca Falavigna Date: Sat, 2 Jan 2010 20:56:27 +0100 Subject: Imported Upstream version 1.2.0.d20091224 --- doc/user/command-line.xml | 2243 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2243 insertions(+) create mode 100644 doc/user/command-line.xml (limited to 'doc/user/command-line.xml') diff --git a/doc/user/command-line.xml b/doc/user/command-line.xml new file mode 100644 index 0000000..630a9b2 --- /dev/null +++ b/doc/user/command-line.xml @@ -0,0 +1,2243 @@ + + + + + &SCons; provides a number of ways + for the writer of the &SConscript; files + to give the users who will run &SCons; + a great deal of control over the build execution. + The arguments that the user can specify on + the command line are broken down into three types: + + + + + + + Options + + + + + Command-line options always begin with + one or two - (hyphen) characters. + &SCons; provides ways for you to examine + and set options values from within your &SConscript; files, + as well as the ability to define your own + custom options. + See , below. + + + + + + + Variables + + + + + Any command-line argument containing an = + (equal sign) is considered a variable setting with the form + variable=value + &SCons; provides direct access to + all of the command-line variable settings, + the ability to apply command-line variable settings + to construction environments, + and functions for configuring + specific types of variables + (Boolean values, path names, etc.) + with automatic validation of the user's specified values. + See , below. + + + + + + + Targets + + + + + Any command-line argument that is not an option + or a variable setting + (does not begin with a hyphen + and does not contain an equal sign) + is considered a target that the user + (presumably) wants &SCons; to build. + A list of Node objects representing + the target or targets 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 , below. + + + + + + + +
+ Command-Line Options + + + + &SCons; has many command-line options + that control its behavior. + A &SCons; command-line option + always begins with one or two - (hyphen) + characters. + + + +
+ Not Having to Specify Command-Line Options Each Time: the &SCONSFLAGS; Environment Variable + + + + Users may find themselves supplying + the same command-line options every time + they run &SCons;. + For example, you might find it saves time + to specify a value of -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 + command-line options that you want &SCons; to use. + + + + + + If, for example, + you're using a POSIX shell that's + compatible with the Bourne shell, + 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] ... + + + + + Users of &csh;-style shells on POSIX systems + can set the &SCONSFLAGS; environment as follows: + + + + + $ setenv SCONSFLAGS "-Q" + + + + + Windows users may typically want to set the + &SCONSFLAGS; in the appropriate tab of the + System Properties window. + + + +
+ +
+ Getting Values Set by Command-Line Options: the &GetOption; Function + + + + &SCons; provides the &GetOption; function + to get the values set by the various command-line options. + One common use of this is to check whether or not + the -h or --help option + has been specified. + Normally, &SCons; does not print its help text + until after it has read all of the &SConscript; files, + because it's possible that help text has been added + by some subsidiary &SConscript; file deep in the + source tree hierarchy. + 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 the command-line help available to users + by using the &GetOption; function to load the + subsidiary &SConscript; files only if the + the user has not specified + the -h or --help option, + like so: + + + + + + + + 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, + below. + + + +
+ +
+ Setting Values of Command-Line Options: the &SetOption; Function + + + + You can also set the values of &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, + below. + + + + + + One use of the &SetOption; function is to + specify a value for the -j + or --jobs option, + so that users 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 + provide 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", 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 from 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 we 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 the user specifies an the command line is used first, + regardless of whether or not + the $NUM_CPU environment + variable is set: + + + + + % 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. + + +
+ +
+ 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 + (beginning with two hyphen characters: --), + after replacing any remaining hyphen characters + with underscores. + + + + + + The full list of strings and the variables they + correspond to is as follows: + + + + + + + + + + String for &GetOption; and &SetOption; + Command-Line Option(s) + + + + + + + + cache_debug + + + + + cache_disable + + + + + cache_force + + + + + cache_show + + + + + clean + , + , + + + + + config + + + + + directory + , + + + + + diskcheck + + + + + duplicate + + + + + file + , + , + , + + + + + help + , + + + + + ignore_errors + + + + + implicit_cache + + + + + implicit_deps_changed + + + + + implicit_deps_unchanged + + + + + interactive + , + + + + + keep_going + , + + + + + max_drift + + + + + no_exec + , + , + , + , + + + + + no_site_dir + + + + + num_jobs + , + + + + + profile_file + + + + + question + , + + + + + random + + + + + repository + , + , + + + + + silent + , + , + + + + + site_dir + + + + + stack_size + + + + + taskmastertrace_file + + + + + warn + + + + + + + + +
+ +
+ Adding Custom Command-Line Options: the &AddOption; Function + + + + &SCons; also allows you to define your own + command-line options with the &AddOption; function. + The &AddOption; function takes the same arguments + as the optparse.add_option function + from the standard Python library. + + + The &AddOption; function is, + in fact, implemented using a subclass + of the optparse.OptionParser. + + + Once you have added a custom command-line option + with the &AddOption; function, + the value of the option (if any) is immediately available + using the standard &GetOption; function. + (The value can also be set using &SetOption;, + although that's not very useful in practice + because a default value can be specified in + directly in the &AddOption; call.) + + + + + + One useful example of using this functionality + is to provide a for users: + + + + + 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 any + value that the user specifies with a command-line + option of --prefix. + Because $PREFIX + will expand to a null string if it's not initialized, + running &SCons; without the + option of --prefix + will install 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" + + +
+ +
+ +
+ Command-Line <varname>variable</varname>=<varname>value</varname> Build Variables + + + + You may want to control various aspects + of your build by allowing the user + to specify variable=value + values on the command line. + For example, suppose you + want users 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. + (Note that unless you want to require + that users always + specify a variable, + you probably want to use + the Python + ARGUMENTS.get() function, + which allows you to specify a default value + to be used if there is no specification + on the command line.) + + + + + + The following code sets the &cv-link-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 + scons: `.' is up to date. + % scons -Q debug=1 + scons: `.' is up to date. + + + + + Notice that &SCons; keeps track of + the last values used to build the object files, + and as a result correctly rebuilds + the object and executable files + only 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 store one value for each specified keyword, + and thus only "remembers" the last setting + for each keyword on the command line. + This makes the &ARGUMENTS; dictionary + inappropriate if users should be able to + specify 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. + + + + + + To accomodate these requirements, + &SCons; provides an &ARGLIST; variable + that gives you direct access to + variable=value + settings on 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 to let the user + 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 + scons: `.' is up to date. + + + + + Note that the &ARGLIST; and &ARGUMENTS; + variables do not interfere with each other, + but merely provide slightly different views + into how the user 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 a dictionary access), + and the &ARGLIST; list + is more flexible + (since you can examine the + specific order in which + the user's command-line variabe settings). + + + +
+ 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; supports a class to + define such build variables easily, + 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 users 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 command line + with the appropriate -D option + (or other command line option) + 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 + &cv-link-CPPDEFINES; construction variable: + + + + + vars = Variables() + vars.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(variables = vars, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + env.Program(['foo.c', 'bar.c']) + + + + + This &SConstruct; file first creates a &Variables; object + (the vars = Variables() call), + and then uses the object's &Add; + method to indicate that the &RELEASE; + variable can be set on the command line, + and that its default value will be 0 + (the third argument to the &Add; method). + The second argument is a line of help text; + we'll learn how to use it in the next section. + + + + + + We then pass the created &Variables; + object as a &variables; keyword argument + to the &Environment; call + used to create the construction environment. + This then allows a user 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 + + + + + NOTE: Before &SCons; release 0.98.1, these build variables + were known as "command-line build options." + The class was actually named the &Options; class, + and in the sections below, + the various functions were named + &BoolOption;, &EnumOption;, &ListOption;, + &PathOption;, &PackageOption; and &AddOptions;. + These older names still work, + and you may encounter them in older + &SConscript; fles, + but their use is discouraged + and will be officially deprecated some day. + + + +
+ +
+ Providing Help for Command-Line Build Variables + + + + To make command-line build variables most useful, + you ideally want to provide + some help text that will describe + the available variables + when the user runs scons -h. + You could write this text by hand, + but &SCons; provides an easier way. + &Variables; objects support a + &GenerateHelpText; method + that will, as its name suggests, + generate text that describes + the various variables that + have been added to it. + You then pass the output from this method to + the &Help; function: + + + + + vars = Variables('custom.py') + vars.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(variables = vars) + Help(vars.GenerateHelpText(env)) + + + + + &SCons; will now display 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 command-line options. + + + + + Notice that the help output shows the default value, + and the current actual value of the build variable. + + + +
+ +
+ Reading Build Variables From a File + + + + Giving the user a way to specify the + value of a build variable on the command line + is useful, + but can still be tedious + if users must specify the variable + every time they run &SCons;. + We can let users provide customized build variable settings + in a local file by providing a + file name when we create the + &Variables; object: + + + + + vars = Variables('custom.py') + vars.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(variables = vars, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + env.Program(['foo.c', 'bar.c']) + Help(vars.GenerateHelpText(env)) + + + + + This then allows the user to control the &RELEASE; + variable by setting it in the &custom_py; file: + + + + + RELEASE = 1 + + + + + Note that this file is actually executed + like a Python script. + Now when we 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 we 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 + + +
+ +
+ Pre-Defined Build Variable Functions + + + + &SCons; provides a number of functions + that provide ready-made behaviors + for various types of command-line build variables. + + + +
+ True/False Values: the &BoolVariable; Build Variable Function + + + + It's 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 accomodate + users who have different preferences for how to represent + &true; or &false; values. + The &BoolVariable; function + makes it easy to accomodate 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', 'Set to build for release', 0)) + env = Environment(variables = vars, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + env.Program('foo.c') + + + + + With this build variable, + 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 a user tries 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 option: bad_value + File "/home/my/project/SConstruct", line 4, in ? + + +
+ +
+ Single Value From a List: the &EnumVariable; Build Variable Function + + + + Suppose that we want a user to be able to + set a &COLOR; variable + that selects a background color to be + displayed by an application, + but that we want to restrict the + choices to a specific set of allowed colors. + This can be set up quite easily + using the &EnumVariable;, + 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', 'Set background color', 'red', + allowed_values=('red', 'green', 'blue'))) + env = Environment(variables = vars, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + + + + + The user can now explicity 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 + scons: `foo.o' is up to date. + % scons -Q COLOR=green foo.o + scons: `foo.o' is up to date. + + + + + But, almost more 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 option COLOR: magenta + File "/home/my/project/SConstruct", line 5, in ? + + + + + The &EnumVariable; function also supports a way + to map alternate names to allowed values. + Suppose, for example, + that we want to allow the user + to use the word navy as a synonym for + blue. + We do this by adding a ↦ dictionary + that will map its key values + to the desired legal value: + + + + + vars = Variables('custom.py') + vars.Add(EnumVariable('COLOR', 'Set background color', 'red', + allowed_values=('red', 'green', 'blue'), + map={'navy':'blue'})) + env = Environment(variables = vars, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + + + + + As desired, the user can then use + navy on the command line, + and &SCons; will translate it 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, + arguments that differ + from the legal values + only in case + are treated as illegal values: + + + + + % scons -Q COLOR=Red foo.o + + scons: *** Invalid value for option COLOR: Red + File "/home/my/project/SConstruct", line 5, in ? + % scons -Q COLOR=BLUE foo.o + + scons: *** Invalid value for option COLOR: BLUE + File "/home/my/project/SConstruct", line 5, in ? + % scons -Q COLOR=nAvY foo.o + + scons: *** Invalid value for option COLOR: nAvY + File "/home/my/project/SConstruct", line 5, in ? + + + + + 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', 'Set background color', '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 + scons: `foo.o' is up to date. + % scons -Q COLOR=nAvY foo.o + scons: `foo.o' is up to date. + % scons -Q COLOR=green foo.o + scons: `foo.o' is up to date. + + + + + Notice that an &ignorecase; value of 1 + preserves the case-spelling that the user supplied. + 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', 'Set background color', 'red', + allowed_values=('red', 'green', 'blue'), + map={'navy':'blue'}, + ignorecase=2)) + env = Environment(variables = vars, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + + + + + Now &SCons; will use values of + red, + green or + blue + regardless of how the user spells + those values 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 + scons: `foo.o' is up to date. + % scons -Q COLOR=GREEN foo.o + scons: `foo.o' is up to date. + + +
+ +
+ Multiple Values From a List: the &ListVariable; Build Variable Function + + + + Another way in which you might want to allow users + to control a build variable is to + specify a list of one or more legal values. + &SCons; supports this through the &ListVariable; function. + If, for example, we want a user to be able to set a + &COLORS; variable to one or more of the legal list of values: + + + + + vars = Variables('custom.py') + vars.Add(ListVariable('COLORS', 'List of colors', 0, + ['red', 'green', 'blue'])) + env = Environment(variables = vars, + CPPDEFINES={'COLORS' : '"${COLORS}"'}) + env.Program('foo.c') + + + + + A user can now specify a comma-separated list + of legal values, + which will get translated into a space-separated + list for passing to the any build commands: + + + + + % scons -Q COLORS=red,blue foo.o + cc -o foo.o -c -DCOLORS="red blue" foo.c + % scons -Q COLORS=blue,green,red foo.o + scons: `foo.o' is up to date. + + + + + In addition, the &ListVariable; function + allows the user to specify explicit keywords of + &all; or &none; + to select all of the legal values, + or none of them, respectively: + + + + + % scons -Q COLORS=all foo.o + cc -o foo.o -c -DCOLORS="red green blue" foo.c + % scons -Q COLORS=none foo.o + scons: `foo.o' is up to date. + + + + + And, of course, an illegal value + still generates an error message: + + + + + % scons -Q COLORS=magenta foo.o + + scons: *** Error converting option: COLORS + Invalid value(s) for option: magenta + File "/home/my/project/SConstruct", line 5, in ? + + +
+ +
+ Path Names: the &PathVariable; Build Variable Function + + + + &SCons; supports 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 variable in the preprocessor + that controls the location of a + configuration file: + + + + + vars = Variables('custom.py') + vars.Add(PathVariable('CONFIG', + 'Path to configuration file', + '/etc/my_config')) + env = Environment(variables = vars, + CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'}) + env.Program('foo.c') + + + + + This then allows the user 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 option CONFIG does not exist: /does/not/exist + File "/home/my/project/SConstruct", line 6, in ? + + + + + &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: + + + + + vars = Variables('custom.py') + vars.Add(PathVariable('CONFIG', + 'Path to configuration file', + '/etc/my_config', + 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: + + + + + vars = Variables('custom.py') + vars.Add(PathVariable('DBDIR', + 'Path to database directory', + '/var/my_dbdir', + 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: + + + + + vars = Variables('custom.py') + vars.Add(PathVariable('DBDIR', + 'Path to database directory', + '/var/my_dbdir', + 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 that the user supplies: + + + + + vars = Variables('custom.py') + vars.Add(PathVariable('OUTPUT', + 'Path to output file or directory', + None, + PathVariable.PathAccept)) + env = Environment(variables = vars, + CPPDEFINES={'OUTPUT' : '"$OUTPUT"'}) + env.Program('foo.c') + + +
+ +
+ Enabled/Disabled Path Names: the &PackageVariable; Build Variable Function + + + + Sometimes you want to give users + even more control over a path name variable, + allowing them to explicitly enable or + disable the path name + by using yes or no keywords, + in addition to allow them + to supply an explicit path name. + &SCons; supports the &PackageVariable; + function to support this: + + + + + vars = Variables('custom.py') + vars.Add(PackageVariable('PACKAGE', + 'Location package', + '/opt/location')) + env = Environment(variables = vars, + CPPDEFINES={'PACKAGE' : '"$PACKAGE"'}) + env.Program('foo.c') + + + + + When the &SConscript; file uses the &PackageVariable; funciton, + user can now still use the default + or supply an overriding path name, + but 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 + scons: `foo.o' is up to date. + % scons -Q PACKAGE=yes foo.o + scons: `foo.o' is up to date. + % scons -Q PACKAGE=no foo.o + scons: `foo.o' is up to date. + + +
+ +
+ +
+ 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 a list of build variables + to be added to the object. + Each build variable is specified + as either a tuple of arguments, + just like you'd pass to the &Add; method itself, + or as a call to one of the pre-defined + functions for pre-packaged command-line build variables. + in any order: + + + + + vars = Variables() + vars.AddVariables( + ('RELEASE', 'Set to 1 to build for release', 0), + ('CONFIG', 'Configuration file', '/etc/my_config'), + BoolVariable('warnings', 'compilation with -Wall and similiar', 1), + EnumVariable('debug', 'debug output and symbols', 'no', + allowed_values=('yes', 'no', 'full'), + map={}, ignorecase=0), # case sensitive + ListVariable('shared', + 'libraries to build as shared libraries', + 'all', + names = list_of_libs), + PackageVariable('x11', + 'use X11 installed here (yes = search some places)', + 'yes'), + PathVariable('qtdir', 'where the root of Qt is installed', qtdir), + ) + + + + + +
+ +
+ Handling Unknown Command-Line Build Variables: the &UnknownVariables; Function + + + + Users may, of course, + occasionally misspell variable names in their command-line settings. + &SCons; does not generate an error or warning + for any unknown variables the users specifies on the command line. + (This is in no small part because you may be + processing the arguments directly using the &ARGUMENTS; dictionary, + and therefore &SCons; can't know in the general case + whether a given "misspelled" variable is + really unknown and a potential problem, + or something that your &SConscript; file + will handle directly with some Python code.) + + + + + + If, however, you're using a &Variables; object to + define a specific set of command-line build variables + that you expect users to be able to set, + you may want to provide an error + message or warning of your own + if the user supplies a variable setting + 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: + + + + + vars = Variables(None) + vars.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(variables = vars, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + unknown = vars.UnknownVariables() + if unknown: + print "Unknown variables:", unknown.keys() + Exit(1) + env.Program('foo.c') + + + + + The &UnknownVariables; method returns a dictionary + containing the keywords and values + of any variables the user 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). + In the examble above, + we check for whether the dictionary + returned by the &UnknownVariables; is non-empty, + and if so print the Python list + containing the names of the unknwown variables + and then call 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. + + + +
+ +
+ +
+ Command-Line Targets + +
+ Fetching Command-Line Targets: the &COMMAND_LINE_TARGETS; Variable + + + + &SCons; supports a &COMMAND_LINE_TARGETS; variable + that lets you fetch the list of targets that the + user specified on the command line. + You can use the targets to manipulate the + build in any way you wish. + As a simple example, + suppose that you want to print a reminder + to the user whenever a specific program is built. + You can do this by checking for the + target in the &COMMAND_LINE_TARGETS; list: + + + + + if 'bar' in COMMAND_LINE_TARGETS: + print "Don't forget to copy `bar' to the archive!" + Default(Program('foo.c')) + Program('bar.c') + + + + + Then, running &SCons; with the default target + works as it always does, + but explicity specifying the &bar; target + on the command line generates the warning message: + + + + + % scons -Q + cc -o foo.o -c foo.c + cc -o foo foo.o + % scons -Q bar + Don't forget to copy `bar' to the archive! + cc -o bar.o -c bar.c + cc -o bar bar.o + + + + + Another practical use for the &COMMAND_LINE_TARGETS; variable + might be to speed up a build + by only reading certain subsidiary &SConscript; + files if a specific target is requested. + + + +
+ +
+ Controlling the Default Targets: the &Default; Function + + + + One of the most basic things you can control + is which targets &SCons; will build by default--that is, + when there are no targets specified on the command line. + As mentioned previously, + &SCons; will normally build every target + in or below the current directory + by default--that is, when you don't + explicitly specify one or more targets + on the command line. + Sometimes, however, you may want + to specify explicitly that only + certain programs, or programs in certain directories, + should be built by default. + You do this with the &Default; function: + + + + + env = Environment() + hello = env.Program('hello.c') + env.Program('goodbye.c') + Default(hello) + + + + + This &SConstruct; file knows how to build two programs, + &hello; and &goodbye;, + but only builds the + &hello; program by default: + + + + + % scons -Q + cc -o hello.o -c hello.c + cc -o hello hello.o + % scons -Q + scons: `hello' is up to date. + % scons -Q goodbye + cc -o goodbye.o -c goodbye.c + cc -o goodbye goodbye.o + + + + + Note that, even when you use the &Default; + function in your &SConstruct; file, + you can still explicitly specify the current directory + (.) on the command line + to tell &SCons; to build + everything in (or below) the current directory: + + + + + % scons -Q . + cc -o goodbye.o -c goodbye.c + cc -o goodbye goodbye.o + cc -o hello.o -c hello.c + cc -o hello hello.o + + + + + You can also call the &Default; + function more than once, + in which case each call + adds to the list of targets to be built by default: + + + + + env = Environment() + prog1 = env.Program('prog1.c') + Default(prog1) + prog2 = env.Program('prog2.c') + prog3 = env.Program('prog3.c') + Default(prog3) + + + + + Or you can specify more than one target + in a single call to the &Default; function: + + + + + env = Environment() + prog1 = env.Program('prog1.c') + prog2 = env.Program('prog2.c') + prog3 = env.Program('prog3.c') + Default(prog1, prog3) + + + + + Either of these last two examples + will build only the + prog1 + and + prog3 + programs by default: + + + + + % scons -Q + cc -o prog1.o -c prog1.c + cc -o prog1 prog1.o + cc -o prog3.o -c prog3.c + cc -o prog3 prog3.o + % scons -Q . + cc -o prog2.o -c prog2.c + cc -o prog2 prog2.o + + + + + You can list a directory as + an argument to &Default;: + + + + + env = Environment() + env.Program(['prog1/main.c', 'prog1/foo.c']) + env.Program(['prog2/main.c', 'prog2/bar.c']) + Default('prog1') + + + + + In which case only the target(s) in that + directory will be built by default: + + + + + % scons -Q + cc -o prog1/foo.o -c prog1/foo.c + cc -o prog1/main.o -c prog1/main.c + cc -o prog1/main prog1/main.o prog1/foo.o + % scons -Q + scons: `prog1' is up to date. + % scons -Q . + cc -o prog2/bar.o -c prog2/bar.c + cc -o prog2/main.o -c prog2/main.c + cc -o prog2/main prog2/main.o prog2/bar.o + + + + + Lastly, if for some reason you don't want + any targets built by default, + you can use the Python None + variable: + + + + + env = Environment() + prog1 = env.Program('prog1.c') + prog2 = env.Program('prog2.c') + Default(None) + + + + + Which would produce build output like: + + + + + % scons -Q + scons: *** No targets specified and no Default() targets found. Stop. + % scons -Q . + cc -o prog1.o -c prog1.c + cc -o prog1 prog1.o + cc -o prog2.o -c prog2.c + cc -o prog2 prog2.o + + +
+ Fetching the List of Default Targets: the &DEFAULT_TARGETS; Variable + + + + &SCons; supports a &DEFAULT_TARGETS; variable + that lets you get at the current list of default targets. + The &DEFAULT_TARGETS variable has + two important differences from the &COMMAND_LINE_TARGETS; variable. + First, the &DEFAULT_TARGETS; variable is a list of + internal &SCons; nodes, + so you need to convert the list elements to strings + if you want to print them or look for a specific target name. + Fortunately, you can do this easily + by using the Python map function + to run the list through str: + + + + + prog1 = Program('prog1.c') + Default(prog1) + print "DEFAULT_TARGETS is", map(str, DEFAULT_TARGETS) + + + + + (Keep in mind that all of the manipulation of the + &DEFAULT_TARGETS; list takes place during the + first phase when &SCons; is reading up the &SConscript; files, + which is obvious if + we leave off the -Q flag when we run &SCons;:) + + + + + % scons + scons: Reading SConscript files ... + DEFAULT_TARGETS is ['prog1'] + scons: done reading SConscript files. + scons: Building targets ... + cc -o prog1.o -c prog1.c + cc -o prog1 prog1.o + scons: done building targets. + + + + + Second, + the contents of the &DEFAULT_TARGETS; list change + in response to calls to the &Default;: function, + as you can see from the following &SConstruct; file: + + + + + prog1 = Program('prog1.c') + Default(prog1) + print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS) + prog2 = Program('prog2.c') + Default(prog2) + print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS) + + + + + Which yields the output: + + + + + % scons + scons: Reading SConscript files ... + DEFAULT_TARGETS is now ['prog1'] + DEFAULT_TARGETS is now ['prog1', 'prog2'] + scons: done reading SConscript files. + scons: Building targets ... + cc -o prog1.o -c prog1.c + cc -o prog1 prog1.o + cc -o prog2.o -c prog2.c + cc -o prog2 prog2.o + scons: done building targets. + + + + + In practice, this simply means that you + need to pay attention to the order in + which you call the &Default; function + and refer to the &DEFAULT_TARGETS; list, + to make sure that you don't examine the + list before you've added the default targets + you expect to find in it. + + + +
+ +
+ +
+ Fetching the List of Build Targets, Regardless of Origin: the &BUILD_TARGETS; Variable + + + + We've already been introduced to the + &COMMAND_LINE_TARGETS; variable, + which contains a list of targets specified on the command line, + and the &DEFAULT_TARGETS; variable, + which contains a list of targets specified + via calls to the &Default; method or function. + Sometimes, however, + you want a list of whatever targets + &SCons; will try to build, + regardless of whether the targets came from the + command line or a &Default; call. + You could code this up by hand, as follows: + + + + + if COMMAND_LINE_TARGETS: + targets = COMMAND_LINE_TARGETS + else: + targets = DEFAULT_TARGETS + + + + + &SCons;, however, provides a convenient + &BUILD_TARGETS; variable + that eliminates the need for this by-hand manipulation. + Essentially, the &BUILD_TARGETS; variable + contains a list of the command-line targets, + if any were specified, + and if no command-line targets were specified, + it contains a list of the targets specified + via the &Default; method or function. + + + + + + Because &BUILD_TARGETS; may contain a list of &SCons; nodes, + you must convert the list elements to strings + if you want to print them or look for a specific target name, + just like the &DEFAULT_TARGETS; list: + + + + + prog1 = Program('prog1.c') + Program('prog2.c') + Default(prog1) + print "BUILD_TARGETS is", map(str, BUILD_TARGETS) + + + + + Notice how the value of &BUILD_TARGETS; + changes depending on whether a target is + specified on the command line: + + + + + % scons -Q + BUILD_TARGETS is ['prog1'] + cc -o prog1.o -c prog1.c + cc -o prog1 prog1.o + % scons -Q prog2 + BUILD_TARGETS is ['prog2'] + cc -o prog2.o -c prog2.c + cc -o prog2 prog2.o + % scons -Q -c . + BUILD_TARGETS is ['.'] + Removed prog1.o + Removed prog1 + Removed prog2.o + Removed prog2 + + +
+ +
-- cgit v1.2.3