diff options
Diffstat (limited to 'doc/user/command-line.sgml')
-rw-r--r-- | doc/user/command-line.sgml | 1138 |
1 files changed, 1138 insertions, 0 deletions
diff --git a/doc/user/command-line.sgml b/doc/user/command-line.sgml new file mode 100644 index 0000000..3377b69 --- /dev/null +++ b/doc/user/command-line.sgml @@ -0,0 +1,1138 @@ +<!-- + + Copyright (c) 2001, 2002, 2003 Steven Knight + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + + <para> + + &SCons; provides a number of ways that + allow the writer of the &SConscript; files + to give users a great deal of control over how to run the builds. + + </para> + + <section> + <title>Not Having to Specify Command-Line Options Each Time: the &SCONSFLAGS; Environment Variable</title> + + <para> + + Users may find themselves supplying + the same command-line options every time + they run &SCons;. + For example, a user might find that it saves time + to always specify a value of <literal>-j 2</literal> + to run the builds in parallel. + + </para> + + + + <literallayout> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + ... + scons: done reading SConscript files. + scons: Building targets ... + scons: `.' is up to date. + scons: done building targets. + % <userinput>export SCONSFLAGS="-Q"</userinput> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + ... + scons: done reading SConscript files. + scons: Building targets ... + scons: `.' is up to date. + scons: done building targets. + </literallayout> + + <para> + + </para> + + </section> + + <section> + <title>Controlling the Default Targets</title> + + <para> + + One of the most basic things you can control + is which targets &SCons; will build by default. + 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: + + </para> + + <programlisting> + env = Environment() + hello = env.Program('hello.c') + env.Program('goodbye.c') + Default(hello) + </programlisting> + + <para> + + This &SConstruct; file knows how to build two programs, + &hello; and &goodbye;, + but only builds the + &hello; program by default: + + </para> + + <literallayout> + % <userinput>scons -Q</userinput> + cc -c -o hello.o hello.c + cc -o hello hello.o + % <userinput>scons -Q</userinput> + scons: `hello' is up to date. + % <userinput>scons -Q goodbye</userinput> + cc -c -o goodbye.o goodbye.c + cc -o goodbye goodbye.o + </literallayout> + + <para> + + Note that, even when you use the &Default; + function in your &SConstruct; file, + you can still explicitly specify the current directory + (<literal>.</literal>) on the command line + to tell &SCons; to build + everything in (or below) the current directory: + + </para> + + <literallayout> + % <userinput>scons -Q .</userinput> + cc -c -o goodbye.o goodbye.c + cc -o goodbye goodbye.o + cc -c -o hello.o hello.c + cc -o hello hello.o + </literallayout> + + <para> + + 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: + + </para> + + <programlisting> + env = Environment() + prog1 = env.Program('prog1.c') + Default(prog1) + prog2 = env.Program('prog2.c') + prog3 = env.Program('prog3.c') + Default(prog3) + </programlisting> + + <para> + + Or you can specify more than one target + in a single call to the &Default; function: + + </para> + + <programlisting> + env = Environment() + prog1 = env.Program('prog1.c') + prog2 = env.Program('prog2.c') + prog3 = env.Program('prog3.c') + Default(prog1, prog3) + </programlisting> + + <para> + + Either of these last two examples + will build only the + <application>prog1</application> + and + <application>prog3</application> + programs by default: + + </para> + + <literallayout> + % <userinput>scons -Q</userinput> + cc -c -o prog1.o prog1.c + cc -o prog1 prog1.o + cc -c -o prog3.o prog3.c + cc -o prog3 prog3.o + % <userinput>scons -Q .</userinput> + cc -c -o prog2.o prog2.c + cc -o prog2 prog2.o + </literallayout> + + <para> + + You can list a directory as + an argument to &Default;: + + </para> + + <programlisting> + env = Environment() + env.Program(['prog1/main.c', 'prog1/foo.c']) + env.Program(['prog2/main.c', 'prog2/bar.c']) + Default('prog1') + </programlisting> + + <para> + + In which case only the target(s) in that + directory will be built by default: + + </para> + + <literallayout> + % <userinput>scons -Q</userinput> + cc -c -o prog1/foo.o prog1/foo.c + cc -c -o prog1/main.o prog1/main.c + cc -o prog1/main prog1/main.o prog1/foo.o + % <userinput>scons -Q</userinput> + scons: `prog1' is up to date. + % <userinput>scons -Q .</userinput> + cc -c -o prog2/bar.o prog2/bar.c + cc -c -o prog2/main.o prog2/main.c + cc -o prog2/main prog2/main.o prog2/bar.o + </literallayout> + + <para> + + Lastly, if for some reason you don't want + any targets built by default, + you can use the Python <literal>None</literal> + variable: + + </para> + + <programlisting> + env = Environment() + prog1 = env.Program('prog1.c') + prog2 = env.Program('prog2.c') + Default(None) + </programlisting> + + <para> + + Which would produce build output like: + + </para> + + <literallayout> + % <userinput>scons -Q</userinput> + scons: *** No targets specified and no Default() targets found. Stop. + % <userinput>scons -Q .</userinput> + cc -c -o prog1.o prog1.c + cc -o prog1 prog1.o + cc -c -o prog2.o prog2.c + cc -o prog2 prog2.o + </literallayout> + + </section> + + <!-- + + <section> + <title>Getting at Command-Line Targets</title> + + <para> + + XXX + + </para> + + </section> + + --> + + <section> + <title>Command-Line <varname>variable</varname>=<varname>value</varname> Build Options</title> + + <para> + + You may want to control various aspects + of your build by allowing the user + to specify <varname>variable</varname>=<varname>value</varname> + 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: + + </para> + + <literallayout> + % scons -Q debug=1 + </literallayout> + + <para> + + &SCons; provides an &ARGUMENTS; dictionary + that stores all of the + <varname>variable</varname>=<varname>value</varname> + 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 <emphasis>always</emphasis> + specify an option, + you probably want to use + the Python + <literal>ARGUMENTS.get()</literal> function, + which allows you to specify a default value + to be used if there is no specification + on the command line.) + + </para> + + <para> + + The following code sets the &CCFLAGS; construction + variable in response to the <varname>debug</varname> + flag being set in the &ARGUMENTS; dictionary: + + </para> + + <programlisting> + env = Environment() + debug = ARGUMENTS.get('debug', 0) + if int(debug): + env.Append(CCFLAGS = '-g') + env.Program('prog.c') + </programlisting> + + <para> + + This results in the <varname>-g</varname> + compiler option being used when + <literal>debug=1</literal> + is used on the command line: + + </para> + + <literallayout> + % <userinput>scons -Q debug=0</userinput> + cc -c -o prog.o prog.c + cc -o prog prog.o + % <userinput>scons -Q debug=0</userinput> + scons: `.' is up to date. + % <userinput>scons -Q debug=1</userinput> + cc -g -c -o prog.o prog.c + cc -o prog prog.o + % <userinput>scons -Q debug=1</userinput> + scons: `.' is up to date. + </literallayout> + + <para> + + 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 <literal>debug</literal> + argument has changed. + + </para> + + </section> + + <section> + <title>Controlling Command-Line Build Options</title> + + <para> + + Being able to use a command-line build option like + <literal>debug=1</literal> is handy, + but it can be a chore to write specific Python code + to recognize each such option + and apply the values to a construction variable. + To help with this, + &SCons; supports a class to + define such build options easily, + and a mechanism to apply the + build options to a construction environment. + This allows you to control how the build options affect + construction environments. + + </para> + + <para> + + 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 <literal>-D</literal> 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 + &CPPDEFINES; construction variable: + + </para> + + <programlisting> + opts = Options() + opts.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(options = opts, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + env.Program(['foo.c', 'bar.c']) + </programlisting> + + <para> + + This &SConstruct; file first creates an + &Options; object + (the <literal>opts = Options()</literal> call), + and then uses the object's &Add; + method to indicate that the &RELEASE; + option can be set on the command line, + and that it's default value will be <literal>0</literal> + (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. + + </para> + + <para> + + We then pass the created &Options; + object as an &options; keyword argument + to the &Environment; call + used to create the construction environment. + This then allows a user to set the + &RELEASE; build option on the command line + and have the variable show up in + the command line used to build each object from + a C source file: + + </para> + + <literallayout> + % <userinput>scons -Q RELEASE=1</userinput> + cc -DRELEASE_BUILD=1 -c -o bar.o bar.c + cc -DRELEASE_BUILD=1 -c -o foo.o foo.c + cc -o foo foo.o bar.o + </literallayout> + + </section> + + <section> + <title>Providing Help for Command-Line Build Options</title> + + <para> + + To make command-line build options most useful, + you ideally want to provide + some help text that will describe + the available options + when the user runs <literal>scons -h</literal>. + You could write this text by hand, + but &SCons; provides an easier way. + &Options; objects support a + &GenerateHelpText; method + that will, as its name indicates, + generate text that describes + the various options that + have been added to it. + You then pass the output from this method to + the &Help; function: + + </para> + + <programlisting> + opts = Options('custom.py') + opts.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(options = opts) + Help(opts.GenerateHelpText(env)) + </programlisting> + + <para> + + &SCons; will now display some useful text + when the <literal>-h</literal> option is used: + + </para> + + <literallayout> + % <userinput>scons -Q -h</userinput> + + RELEASE: Set to 1 to build for release + default: 0 + actual: 0 + + Use scons -H for help about command-line options. + </literallayout> + + <para> + + Notice that the help output shows the default value, + and the current actual value of the build option. + + </para> + + </section> + + <section> + <title>Reading Build Options From a File</title> + + <para> + + Being able to use a command-line build option like + <literal>debug=1</literal> is handy, + but it can be a chore to write specific Python code + to recognize each such option + and apply the values to a construction variable. + To help with this, + &SCons; supports a class to + define such build options easily + and to read build option values from a file. + This allows you to control how the build options affect + construction environments. + The way you do this is by specifying + a file name when you call &Options;, + like &custom_py; in the following example: + + </para> + + <programlisting> + opts = Options('custom.py') + opts.Add('RELEASE', 'Set to 1 to build for release', 0) + env = Environment(options = opts, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + env.Program(['foo.c', 'bar.c']) + Help(opts.GenerateHelpText(env)) + </programlisting> + + <para> + + This then allows us to control the &RELEASE; + variable by setting it in the &custom_py; file: + + </para> + + <programlisting> + RELEASE = 1 + </programlisting> + + <para> + + Note that this file is actually executed + like a Python script. + Now when we run &SCons;: + + </para> + + <literallayout> + % <userinput>scons -Q</userinput> + cc -DRELEASE_BUILD=1 -c -o bar.o bar.c + cc -DRELEASE_BUILD=1 -c -o foo.o foo.c + cc -o foo foo.o bar.o + </literallayout> + + <para> + + And if we change the contents of &custom_py; to: + + </para> + + <programlisting> + RELEASE = 0 + </programlisting> + + <para> + + The object files are rebuilt appropriately + with the new option: + + </para> + + <literallayout> + % <userinput>scons -Q</userinput> + cc -DRELEASE_BUILD=0 -c -o bar.o bar.c + cc -DRELEASE_BUILD=0 -c -o foo.o foo.c + cc -o foo foo.o bar.o + </literallayout> + + </section> + + <section> + <title>Canned Build Options</title> + + <para> + + &SCons; provides a number of functions + that provide ready-made behaviors + for various types of command-line build options. + + </para> + + <section> + <title>True/False Values: the &BoolOption; Build Option</title> + + <para> + + It's often handy to be able to specify an + option 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 &BoolOption; function + makes it easy to accomodate a variety of + common values that represent + &true; or &false;. + + </para> + + <para> + + The &BoolOption; function takes three arguments: + the name of the build option, + the default value of the build option, + and the help string for the option. + It then returns appropriate information for + passing to the &Add; method of an &Options; object, like so: + + </para> + + <programlisting> + opts = Options('custom.py') + opts.Add(BoolOption('RELEASE', 0, 'Set to build for release')) + env = Environment(options = opts, + CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) + env.Program('foo.c') + </programlisting> + + <para> + + With this build option, + the &RELEASE; variable can now be enabled by + setting it to the value <literal>yes</literal> + or <literal>t</literal>: + + </para> + + <literallayout> + % <userinput>scons -Q RELEASE=yes foo.o</userinput> + cc -DRELEASE_BUILD=1 -c -o foo.o foo.c + </literallayout> + + <literallayout> + % <userinput>scons -Q RELEASE=t foo.o</userinput> + cc -DRELEASE_BUILD=1 -c -o foo.o foo.c + </literallayout> + + <para> + + Other values that equate to &true; include + <literal>y</literal>, + <literal>1</literal>, + <literal>on</literal> + and + <literal>all</literal>. + + </para> + + <para> + + Conversely, &RELEASE; may now be given a &false; + value by setting it to + <literal>no</literal> + or + <literal>f</literal>: + + </para> + + <literallayout> + % <userinput>scons -Q RELEASE=no foo.o</userinput> + cc -DRELEASE_BUILD=0 -c -o foo.o foo.c + </literallayout> + + <literallayout> + % <userinput>scons -Q RELEASE=f foo.o</userinput> + cc -DRELEASE_BUILD=0 -c -o foo.o foo.c + </literallayout> + + <para> + + Other values that equate to &true; include + <literal>n</literal>, + <literal>0</literal>, + <literal>off</literal> + and + <literal>none</literal>. + + </para> + + <para> + + Lastly, if a user tries to specify + any other value, + &SCons; supplies an appropriate error message: + + </para> + + <literallayout> + % <userinput>scons -Q RELEASE=bad_value foo.o</userinput> + + scons: *** Error converting option: RELEASE + Invalid value for boolean option: bad_value + File "SConstruct", line 4, in ? + </literallayout> + + </section> + + <section> + <title>Single Value From a List: the &EnumOption; Build Option</title> + + <para> + + Suppose that we want a user to be able to + set a &COLOR; option + 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 &EnumOption;, + which takes a list of &allowed_values + in addition to the variable name, + default value, + and help text arguments: + + </para> + + <programlisting> + opts = Options('custom.py') + opts.Add(EnumOption('COLOR', 'red', 'Set background color', + allowed_values=('red', 'green', 'blue'))) + env = Environment(options = opts, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + </programlisting> + + <para> + + The user can now explicity set the &COLOR; build option + to any of the specified allowed values: + + </para> + + <literallayout> + % <userinput>scons -Q COLOR=red foo.o</userinput> + cc -DCOLOR="red" -c -o foo.o foo.c + % <userinput>scons -Q COLOR=blue foo.o</userinput> + cc -DCOLOR="blue" -c -o foo.o foo.c + % <userinput>scons -Q COLOR=green foo.o</userinput> + cc -DCOLOR="green" -c -o foo.o foo.c + </literallayout> + + <para> + + But, almost more importantly, + an attempt to set &COLOR; + to a value that's not in the list + generates an error message: + + </para> + + <literallayout> + % <userinput>scons -Q COLOR=magenta foo.o</userinput> + + scons: *** Invalid value for option COLOR: magenta + File "SConstruct", line 5, in ? + </literallayout> + + <para> + + The &EnumOption; 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 <literal>navy</literal> as a synonym for + <literal>blue</literal>. + We do this by adding a ↦ dictionary + that will map its key values + to the desired legal value: + + </para> + + <programlisting> + opts = Options('custom.py') + opts.Add(EnumOption('COLOR', 'red', 'Set background color', + allowed_values=('red', 'green', 'blue'), + map={'navy':'blue'})) + env = Environment(options = opts, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + </programlisting> + + <para> + + As desired, the user can then use + <literal>navy</literal> on the command line, + and &SCons; will translate it into <literal>blue</literal> + when it comes time to use the &COLOR; + option to build a target: + + </para> + + <literallayout> + % <userinput>scons -Q COLOR=navy foo.o</userinput> + cc -DCOLOR="blue" -c -o foo.o foo.c + </literallayout> + + <para> + + By default, when using the &EnumOption; function, + arguments that differ + from the legal values + only in case + are treated as illegal values: + + </para> + + <literallayout> + % <userinput>scons -Q COLOR=Red foo.o</userinput> + + scons: *** Invalid value for option COLOR: Red + File "SConstruct", line 5, in ? + % <userinput>scons -Q COLOR=BLUE foo.o</userinput> + + scons: *** Invalid value for option COLOR: BLUE + File "SConstruct", line 5, in ? + % <userinput>scons -Q COLOR=nAvY foo.o</userinput> + + scons: *** Invalid value for option COLOR: nAvY + File "SConstruct", line 5, in ? + </literallayout> + + <para> + + The &EnumOption; function can take an additional + &ignorecase; keyword argument that, + when set to <literal>1</literal>, + tells &SCons; to allow case differences + when the values are specified: + + </para> + + <programlisting> + opts = Options('custom.py') + opts.Add(EnumOption('COLOR', 'red', 'Set background color', + allowed_values=('red', 'green', 'blue'), + map={'navy':'blue'}, + ignorecase=1)) + env = Environment(options = opts, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + </programlisting> + + <para> + + Which yields the output: + + </para> + + <literallayout> + % <userinput>scons -Q COLOR=Red foo.o</userinput> + cc -DCOLOR="Red" -c -o foo.o foo.c + % <userinput>scons -Q COLOR=BLUE foo.o</userinput> + cc -DCOLOR="BLUE" -c -o foo.o foo.c + % <userinput>scons -Q COLOR=nAvY foo.o</userinput> + cc -DCOLOR="blue" -c -o foo.o foo.c + % <userinput>scons -Q COLOR=green foo.o</userinput> + cc -DCOLOR="green" -c -o foo.o foo.c + </literallayout> + + <para> + + Notice that an &ignorecase; value of <literal>1</literal> + 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 <literal>2</literal>: + + </para> + + <programlisting> + opts = Options('custom.py') + opts.Add(EnumOption('COLOR', 'red', 'Set background color', + allowed_values=('red', 'green', 'blue'), + map={'navy':'blue'}, + ignorecase=2)) + env = Environment(options = opts, + CPPDEFINES={'COLOR' : '"${COLOR}"'}) + env.Program('foo.c') + </programlisting> + + <para> + + Now &SCons; will use values of + <literal>red</literal>, + <literal>green</literal> or + <literal>blue</literal> + regardless of how the user spells + those values on the command line: + + </para> + + <literallayout> + % <userinput>scons -Q COLOR=Red foo.o</userinput> + cc -DCOLOR="red" -c -o foo.o foo.c + % <userinput>scons -Q COLOR=nAvY foo.o</userinput> + cc -DCOLOR="blue" -c -o foo.o foo.c + % <userinput>scons -Q COLOR=GREEN foo.o</userinput> + cc -DCOLOR="green" -c -o foo.o foo.c + </literallayout> + + </section> + + <section> + <title>Multiple Values From a List: the &ListOption; Build Option</title> + + <para> + + Another way in which you might want to allow users + to control build option is to + specify a list of one or more legal values. + &SCons; supports this through the &ListOption; function. + If, for example, we want a user to be able to set a + &COLORS; option to one or more of the legal list of values: + + </para> + + <programlisting> + opts = Options('custom.py') + opts.Add(ListOption('COLORS', 0, 'List of colors', + ['red', 'green', 'blue'])) + env = Environment(options = opts, + CPPDEFINES={'COLORS' : '"${COLORS}"'}) + env.Program('foo.c') + </programlisting> + + <para> + + 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: + + </para> + + <literallayout> + % <userinput>scons -Q COLORS=red,blue foo.o</userinput> + TypeError: sequence item 0: expected string, int found: + % <userinput>scons -Q COLORS=blue,green,red foo.o</userinput> + TypeError: sequence item 0: expected string, int found: + </literallayout> + + <para> + + In addition, the &ListOption; function + allows the user to specify explicit keywords of + &all; or &none; + to select all of the legal values, + or none of them, respectively: + + </para> + + <literallayout> + % <userinput>scons -Q COLORS=all foo.o</userinput> + TypeError: sequence item 0: expected string, int found: + % <userinput>scons -Q COLORS=none foo.o</userinput> + TypeError: sequence item 0: expected string, int found: + </literallayout> + + <para> + + And, of course, an illegal value + still generates an error message: + + </para> + + <literallayout> + % <userinput>scons -Q COLORS=magenta foo.o</userinput> + TypeError: sequence item 0: expected string, int found: + </literallayout> + + </section> + + <section> + <title>Path Names: the &PathOption; Build Option</title> + + <para> + + &SCons; supports a &PathOption; function + to make it easy to create a build option + to control an expected path name. + If, for example, you need to + define a variable in the preprocessor + that control the location of a + configuration file: + + </para> + + <programlisting> + opts = Options('custom.py') + opts.Add(PathOption('CONFIG', '/etc/my_config', 'Path to configuration file')) + env = Environment(options = opts, + CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'}) + env.Program('foo.c') + </programlisting> + + <para> + + This then allows the user to + override the &CONFIG; build option + on the command line as necessary: + + </para> + + <literallayout> + % <userinput>scons -Q foo.o</userinput> + + scons: *** Path does not exist for option CONFIG: Path to configuration file + File "SConstruct", line 4, in ? + % <userinput>scons -Q CONFIG=/usr/local/etc/other_config foo.o</userinput> + cc -DCONFIG_FILE="/usr/local/etc/other_config" -c -o foo.o foo.c + </literallayout> + + </section> + + <section> + <title>Enabled/Disabled Path Names: the &PackageOption; Build Option</title> + + <para> + + 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 <literal>yes</literal> or <literal>no</literal> keywords, + in addition to allow them + to supply an explicit path name. + &SCons; supports the &PackageOption; + function to support this: + + </para> + + <programlisting> + opts = Options('custom.py') + opts.Add(PackageOption('PACKAGE', '/opt/location', 'Location package')) + env = Environment(options = opts, + CPPDEFINES={'PACKAGE' : '"$PACKAGE"'}) + env.Program('foo.c') + </programlisting> + + <para> + + When the &SConscript; file uses the &PackageOption; 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: + + </para> + + <literallayout> + % <userinput>scons -Q foo.o</userinput> + + scons: *** Path does not exist for option PACKAGE: Location package + File "SConstruct", line 4, in ? + % <userinput>scons -Q PACKAGE=/usr/local/location foo.o</userinput> + cc -DPACKAGE="/usr/local/location" -c -o foo.o foo.c + % <userinput>scons -Q PACKAGE=yes foo.o</userinput> + cc -DPACKAGE="1" -c -o foo.o foo.c + % <userinput>scons -Q PACKAGE=no foo.o</userinput> + cc -DPACKAGE="0" -c -o foo.o foo.c + </literallayout> + + </section> + + </section> + + <section> + <title>Adding Multiple Command-Line Build Options at Once</title> + + <para> + + Lastly, &SCons; provides a way to add + multiple build options to an &Options; object at once. + Instead of having to call the &Add; method + multiple times, + you can call the &AddOptions; + method with a list of build options + to be added to the object. + Each build option 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 canned + functions for pre-packaged command-line build options. + in any order: + + </para> + + <programlisting> + opts = Options() + opts.AddOptions( + ('RELEASE', 'Set to 1 to build for release', 0), + ('CONFIG', 'Configuration file', '/etc/my_config'), + BoolOption('warnings', 'compilation with -Wall and similiar', 1), + EnumOption('debug', 'debug output and symbols', 'no', + allowed_values=('yes', 'no', 'full'), + map={}, ignorecase=0), # case sensitive + ListOption('shared', + 'libraries to build as shared libraries', + 'all', + names = list_of_libs), + PackageOption('x11', + 'use X11 installed here (yes = search some places)', + 'yes'), + PathOption('qtdir', 'where the root of Qt is installed', qtdir), + ) + </programlisting> + + <para> + </para> + + </section> |