diff options
28 files changed, 2236 insertions, 483 deletions
@@ -865,7 +865,10 @@ if change: for f in pf + cf: u[f] = 1 for f in df: - del u[f] + try: + del u[f] + except KeyError: + pass sfiles = filter(lambda x: x[-9:] != '.aeignore' and x[-9:] != '.sconsign', u.keys()) diff --git a/doc/scons.mod b/doc/scons.mod index 32283c3..f9deaa1 100644 --- a/doc/scons.mod +++ b/doc/scons.mod @@ -14,14 +14,20 @@ --> +<!ENTITY Aegis "<application>Aegis</application>"> <!ENTITY Autoconf "<application>Autoconf</application>"> <!ENTITY Cons "<application>Cons</application>"> <!ENTITY gcc "<application>gcc</application>"> +<!ENTITY Jam "<application>Jam</application>"> <!ENTITY Make "<application>Make</application>"> <!ENTITY Makepp "<application>Make++</application>"> +<!ENTITY ranlib "<application>ranlib</application>"> <!ENTITY SCons "<application>SCons</application>"> <!ENTITY scons "<application>scons</application>"> <!ENTITY ScCons "<application>ScCons</application>"> +<!ENTITY tar "<application>tar</application>"> +<!ENTITY touch "<application>touch</application>"> +<!ENTITY zip "<application>zip</application>"> <!-- @@ -57,10 +63,11 @@ <!-- - File names. + File and directory names. --> +<!ENTITY build "<filename>build</filename>"> <!ENTITY Makefile "<filename>Makefile</filename>"> <!ENTITY Makefiles "<filename>Makefiles</filename>"> <!ENTITY SConscript "<filename>SConscript</filename>"> @@ -68,6 +75,7 @@ <!ENTITY Sconstruct "<filename>Sconstruct</filename>"> <!ENTITY sconstruct "<filename>sconstruct</filename>"> <!ENTITY sconsign "<filename>.sconsign</filename>"> +<!ENTITY src "<filename>src</filename>"> @@ -106,10 +114,17 @@ <!ENTITY Repository "<function>Repository</function>"> <!ENTITY RuleSet "<function>RuleSet</function>"> <!ENTITY Salt "<function>Salt</function>"> +<!ENTITY SetBuildSignatureType "<function>SetBuildSignatureType</function>"> +<!ENTITY SetContentSignatureType "<function>SetContentSignatureType</function>"> <!ENTITY SourceSignature "<function>SourceSignature</function>"> +<!ENTITY SourceSignatures "<function>SourceSignatures</function>"> <!ENTITY Split "<function>Split</function>"> +<!ENTITY TargetSignatures "<function>TargetSignatures</function>"> <!ENTITY Task "<function>Task</function>"> +<!ENTITY str "<function>str</function>"> +<!ENTITY zipfile "<function>zipfile</function>"> + <!-- Obsolete, but referenced in old documents. --> <!ENTITY Cache "<function>Cache</function>"> @@ -125,6 +140,8 @@ <!ENTITY BUILDERS "<varname>BUILDERS</varname>"> <!ENTITY SCANNERMAP "<varname>SCANNERMAP</varname>"> <!ENTITY SCANNERS "<varname>SCANNERS</varname>"> +<!ENTITY TARFLAGS "<varname>TARFLAGS</varname>"> +<!ENTITY TARSUFFIX "<varname>TARSUFFIX</varname>"> @@ -137,6 +154,7 @@ <!ENTITY CC "<varname>CC</varname>"> <!ENTITY CCFLAGS "<varname>CCFLAGS</varname>"> <!ENTITY LIBPATH "<varname>LIBPATH</varname>"> +<!ENTITY LIBS "<varname>LIBS</varname>"> <!ENTITY PYTHONPATH "<varname>PYTHONPATH</varname>"> <!ENTITY SCONSFLAGS "<varname>SCONSFLAGS</varname>"> @@ -144,6 +162,18 @@ <!-- + Function and method arguments. + +--> + +<!ENTITY build_dir "<varname>build_dir</varname>"> +<!ENTITY source "<varname>source</varname>"> +<!ENTITY target "<varname>target</varname>"> + + + +<!-- + Builder and Scanner objects. --> @@ -151,6 +181,10 @@ <!ENTITY BuildDir "<function>BuildDir</function>"> <!ENTITY CFile "<function>CFile</function>"> <!ENTITY CXXFile "<function>CXXFile</function>"> +<!ENTITY DVI "<function>DVI</function>"> +<!ENTITY Jar "<function>Jar</function>"> +<!ENTITY Java "<function>Java</function>"> +<!ENTITY JavaH "<function>JavaH</function>"> <!ENTITY Library "<function>Library</function>"> <!ENTITY Object "<function>Object</function>"> <!ENTITY PCH "<function>PCH</function>"> @@ -158,10 +192,13 @@ <!ENTITY PostScript "<function>PostScript</function>"> <!ENTITY Program "<function>Program</function>"> <!ENTITY RES "<function>RES</function>"> +<!ENTITY RMIC "<function>RMIC</function>"> <!ENTITY SharedLibrary "<function>SharedLibrary</function>"> <!ENTITY SharedObject "<function>SharedObject</function>"> <!ENTITY StaticLibrary "<function>StaticLibrary</function>"> <!ENTITY StaticObject "<function>StaticObject</function>"> +<!ENTITY Tar "<function>Tar</function>"> +<!ENTITY Zip "<function>Zip</function>"> <!-- Obsolete, but referenced in old documents. --> <!ENTITY MakeBuilder "<function>Make</function>"> @@ -175,6 +212,8 @@ --> +<!ENTITY buildfunc "<literal>builder function</literal>"> + <!ENTITY ConsEnv "<literal>Construction Environment</literal>"> <!ENTITY ConsEnvs "<literal>Construction Environments</literal>"> <!ENTITY Consenv "<literal>Construction environment</literal>"> @@ -193,14 +232,29 @@ <!ENTITY Dictionary "<literal>Dictionary</literal>"> +<!ENTITY Emitter "<literal>Emitter</literal>"> +<!ENTITY emitter "<literal>emitter</literal>"> +<!ENTITY Generator "<literal>Generator</literal>"> +<!ENTITY generator "<literal>generator</literal>"> + +<!ENTITY signature "<literal>signature</literal>"> +<!ENTITY buildsignature "<literal>build signature</literal>"> + <!-- File and program names used in examples. --> +<!ENTITY common1_c "<application>common1.c</application>"> +<!ENTITY common2_c "<application>common2.c</application>"> <!ENTITY goodbye "<application>goodbye</application>"> <!ENTITY hello "<application>hello</application>"> <!ENTITY hello_c "<filename>hello.c</filename>"> +<!ENTITY hello_exe "<filename>hello.exe</filename>"> <!ENTITY hello_h "<filename>hello.h</filename>"> +<!ENTITY hello_o "<filename>hello.o</filename>"> +<!ENTITY prog "<filename>prog</filename>"> +<!ENTITY prog_c "<filename>prog.c</filename>"> +<!ENTITY prog_exe "<filename>prog.exe</filename>"> <!ENTITY stdio_h "<filename>stdio.h</filename>"> diff --git a/doc/user/actions.sgml b/doc/user/actions.sgml index 447b331..c35ccdd 100644 --- a/doc/user/actions.sgml +++ b/doc/user/actions.sgml @@ -224,16 +224,16 @@ solutions to the above limitations. <para> - X + XXX </para> <section> - <title>X</title> + <title>XXX</title> <para> - X + XXX </para> diff --git a/doc/user/ant.sgml b/doc/user/ant.sgml new file mode 100644 index 0000000..f83ab63 --- /dev/null +++ b/doc/user/ant.sgml @@ -0,0 +1,41 @@ +<!-- + + 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> + + XXX + + </para> + + <section> + <title>XXX</title> + + <para> + + XXX + + </para> + + </section> diff --git a/doc/user/builders-built-in.sgml b/doc/user/builders-built-in.sgml new file mode 100644 index 0000000..bb29cc4 --- /dev/null +++ b/doc/user/builders-built-in.sgml @@ -0,0 +1,628 @@ +<!-- + + 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 the ability to build a lot of different + types of files right "out of the box." + So far, we've been using &SCons;' ability to build + programs, objects and libraries to + illustrate much of the underlying functionality of &SCons; + This section will describe all of the different + types of files that you can build with &SCons;, + and the built-in &Builder; objects used to build them. + + </para> + + <section> + <title>Programs: the &Program; Builder</title> + + <para> + + As we've seen, the &Program; Builder + is used to build an executable program. + The &source; argument is one or more + source-code files or object files, + and the ⌖ argument is the + name of the executable program name to be created. + For example: + + </para> + + <programlisting> + env = Environment() + env.Program('prog', 'file1.o') + </programlisting> + + <para> + + Will create the &prog; + executable on a POSIX system, + the &prog_exe; executable on a Windows system. + + </para> + + <para> + + The target file's prefix and suffix may be omitted, + and the values from the + $PROGPREFIX + and + $PROGSUFFIX + construction variables + will be appended appropriately. + For example: + + </para> + + <programlisting> + env = Environment(PROGPREFIX='my', PROGSUFFIX='.xxx') + env.Program('prog', ['file1.o', 'file2.o']) + </programlisting> + + <para> + + Will create a program named + <filename>myprog.xxx</filename> + regardless of the system on which it is run. + + </para> + + <para> + + If you omit the ⌖, + the base of the first input + file name specified + because the base of the target + program created. + For example: + + </para> + + <programlisting> + env = Environment() + env.Program(['hello.c', 'goodbye.c']) + </programlisting> + + <para> + + Will create the &hello; + executable on a POSIX system, + the &hello_exe; executable on a Windows system. + + </para> + + </section> + + <section> + <title>Object-File Builders</title> + + <para> + + &SCons; provides separate Builder objects + to create both static and shared object files. + + </para> + + <section> + <title>The &StaticObject; Builder</title> + + <para> + + XXX + + </para> + + <programlisting> + XXX + </programlisting> + + <literallayout> + XXX + </literallayout> + + </section> + + <section> + <title>The &SharedObject; Builder</title> + + <para> + + XXX + + </para> + + <programlisting> + XXX + </programlisting> + + <literallayout> + XXX + </literallayout> + + </section> + + <section> + <title>The &Object; Builder</title> + + <para> + + XXX + + </para> + + <programlisting> + XXX + </programlisting> + + <para> + + Creates a static object file. + + </para> + + </section> + + </section> + + <section> + <title>Library Builders</title> + + <para> + + &SCons; provides separate Builder objects + to create both static and shared libraries. + + </para> + + <section> + <title>The &StaticLibrary; Builder</title> + + <para> + + XXX + + </para> + + <programlisting> + XXX + </programlisting> + + <literallayout> + XXX + </literallayout> + + </section> + + <section> + <title>The &SharedLibrary; Builder</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>The &Library; Builder</title> + + <para> + + XXX + + </para> + + <programlisting> + XXX + </programlisting> + + <literallayout> + XXX + </literallayout> + + <para> + + Creates a static library file. + + </para> + + </section> + + </section> + + <section> + <title>Pre-Compiled Headers: the &PCH; Builder</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Microsoft Visual C++ Resource Files: the &RES; Builder</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Source Files</title> + + <para> + + By default + &SCons; supports two Builder objects + that know how to build source files + from other input files. + + </para> + + <section> + <title>The &CFile; Builder</title> + + <para> + + XXX + + </para> + + <programlisting> + XXX + </programlisting> + + <literallayout> + XXX + </literallayout> + + </section> + + <section> + <title>The &CXXFile; Builder</title> + + <para> + + XXX + + </para> + + <programlisting> + XXX + </programlisting> + + <literallayout> + XXX + </literallayout> + + </section> + + </section> + + <section> + <title>Documents</title> + + <para> + + &SCons; provides a number of Builder objects + for creating different types of documents. + + </para> + + <section> + <title>The &DVI; Builder</title> + + <para> + + XXX + + </para> + + <programlisting> + XXX + </programlisting> + + <literallayout> + XXX + </literallayout> + + </section> + + <section> + <title>The &PDF; Builder</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>The &PostScript; Builder</title> + + <para> + + XXX + + </para> + + <programlisting> + XXX + </programlisting> + + <literallayout> + XXX + </literallayout> + + </section> + + </section> + + <section> + <title>Archives</title> + + <para> + + &SCons; provides Builder objects + for creating two different types of archive files. + + </para> + + <section> + <title>The &Tar; Builder</title> + + <para> + + The &Tar; Builder object uses the &tar; + utility to create archives of files + and/or directory trees: + + </para> + + <programlisting> + env = Environment() + env.Tar('out1.tar', ['file1', 'file2']) + env.Tar('out2', 'directory') + </programlisting> + + <literallayout> + % <userinput>scons .</userinput> + tar -c -f out1.tar file1 file2 + tar -c -f out2.tar directory + </literallayout> + + <para> + + One common requirement when creating a &tar; archive + is to create a compressed archive using the + <option>-z</option> option. + This is easily handled by specifying + the value of the &TARFLAGS; variable + when you create the construction environment. + Note, however, that the <option>-c</option> used to + to instruct &tar; to create the archive + is part of the default value of &TARFLAGS;, + so you need to set it both options: + + </para> + + <programlisting> + env = Environment(TARFLAGS = '-c -z') + env.Tar('out.tar.gz', 'directory') + </programlisting> + + <literallayout> + % <userinput>scons .</userinput> + tar -c -z -f out.tar.gz directory + </literallayout> + + <para> + + you may also wish to set the value of the + &TARSUFFIX; construction variable + to your desired suffix for compress &tar; archives, + so that &SCons; can append it to the target file name + without your having to specify it explicitly: + + </para> + + <programlisting> + env = Environment(TARFLAGS = '-c -z', + TARSUFFIX = '.tgz') + env.Tar('out', 'directory') + </programlisting> + + <literallayout> + % <userinput>scons .</userinput> + tar -c -z -f out.tgz directory + </literallayout> + + </section> + + <section> + <title>The &Zip; Builder</title> + + <para> + + The &Zip; Builder object creates archives of files + and/or directory trees in the ZIP file format. + Python versions 1.6 or later + contain an internal &zipfile; module + that &SCons; will use. + In this case, given the following + &SConstruct; file: + + </para> + + <programlisting> + env = Environment() + env.Zip('out', ['file1', 'file2']) + </programlisting> + + <para> + + Your output will reflect the fact + that an internal Python function + is being used to create the output ZIP archive: + + </para> + + <literallayout> + % <userinput>scons .</userinput> + zip("out.zip", ["file1", "file2"]) + </literallayout> + + <para> + + If you're using Python version 1.5.2 to run &SCons;, + then &SCons; will try to use an external + &zip; program as follows: + + </para> + + <literallayout> + % <userinput>scons .</userinput> + zip /home/my/project/zip.out file1 file2 + </literallayout> + + </section> + + </section> + + <section> + <title>Java</title> + + <para> + + &SCons; provides Builder objects + for creating various types of Java output files. + + </para> + + <section> + <title>Building Class Files: the &Java; Builder</title> + + <para> + + The &Java; builder takes one or more input + <filename>.java</filename> files + and turns them into one or more + <filename>.class</filename> files + Unlike most builders, however, + the &Java; builder takes + target and source <emphasis>directories</emphasis>, + not files, as input. + + </para> + + <programlisting> + env = Environment() + env.Java(target = 'classes', source = 'src') + </programlisting> + + <para> + + The &Java; builder will then + search the specified source directory + tree for all <filename>.java</filename> files, + and pass any out-of-date + + </para> + + <literallayout> + XXX + </literallayout> + + </section> + + <section> + <title>The &Jar; Builder</title> + + <para> + + The &Jar; builder object XXX + + </para> + + <programlisting> + env = Environment() + env.Java(target = 'classes', source = 'src') + env.Jar(target = '', source = 'classes') + </programlisting> + + <literallayout> + XXX + </literallayout> + + </section> + + <section> + <title>Building C header and stub files: the &JavaH; Builder</title> + + <para> + + XXX + + </para> + + <programlisting> + XXX + </programlisting> + + <literallayout> + XXX + </literallayout> + + </section> + + <section> + <title>Building RMI stub and skeleton class files: the &RMIC; Builder</title> + + <para> + + XXX + + </para> + + <programlisting> + XXX + </programlisting> + + <literallayout> + XXX + </literallayout> + + </section> + + </section> diff --git a/doc/user/command.sgml b/doc/user/builders-commands.sgml index 945c656..e21f6d0 100644 --- a/doc/user/command.sgml +++ b/doc/user/builders-commands.sgml @@ -23,41 +23,41 @@ --> -<!-- + <!-- -=head2 The C<Command> method + =head2 The C<Command> method -The C<Command> method is called as follows: + The C<Command> method is called as follows: - Command $env <target>, <inputs>, <build action>; + Command $env <target>, <inputs>, <build action>; -The target is made dependent upon the list of input files specified, and the -inputs must be built successfully or Cons will not attempt to build the -target. + The target is made dependent upon the list of input files specified, and the + inputs must be built successfully or Cons will not attempt to build the + target. -To specify a command with multiple targets, you can specify a reference to a -list of targets. In Perl, a list reference can be created by enclosing a -list in square brackets. Hence the following command: + To specify a command with multiple targets, you can specify a reference to a + list of targets. In Perl, a list reference can be created by enclosing a + list in square brackets. Hence the following command: - Command $env ['foo.h', 'foo.c'], 'foo.template', q( - gen %1 - ); + Command $env ['foo.h', 'foo.c'], 'foo.template', q( + gen %1 + ); -could be used in a case where the command C<gen> creates two files, both -F<foo.h> and F<foo.c>. + could be used in a case where the command C<gen> creates two files, both + F<foo.h> and F<foo.c>. ---> + --> <para> Creating a &Builder; and attaching it to a &consenv; allows for a lot of flexibility when you - want to re-use the same actions + want to re-use actions to build multiple files of the same type. This can, however, be cumbersome if you only need to execute one specific command - to build a single file (or single group of files). + to build a single file (or group of files). For these situations, &SCons; supports a &Command; &Builder; that arranges for a specific action to be executed @@ -90,7 +90,7 @@ F<foo.h> and F<foo.c>. <para> - Note that the action you + Note that the action you </para> diff --git a/doc/user/builders.sgml b/doc/user/builders-writing.sgml index c1b4269..27a48b9 100644 --- a/doc/user/builders.sgml +++ b/doc/user/builders-writing.sgml @@ -97,20 +97,24 @@ This functionality could be invoked as in the following example: <para> - &SCons; provides many useful methods - for building common software products: - programs, libraries, documents. - Frequently, however, you want to be - able to build some other type of file - not supported directly by &SCons; - Fortunately, &SCons; makes it very easy - to define your own &Builder; objects - for any custom file types you want to build. + Although &SCons; provides many useful methods + for building common software products: + programs, libraries, documents. + you frequently want to be + able to build some other type of file + not supported directly by &SCons; + Fortunately, &SCons; makes it very easy + to define your own &Builder; objects + for any custom file types you want to build. + (In fact, the &SCons; interfaces for creating + &Builder; objects are flexible enough and easy enough to use + that all of the the &SCons; built-in &Builder; objects + are created the mechanisms described in this section.) </para> <section> - <title>Builders That Execute External Commands</title> + <title>Writing Builders That Execute External Commands</title> <para> @@ -128,6 +132,14 @@ This functionality could be invoked as in the following example: bld = Builder(action = 'foobuild < $TARGET > $SOURCE') </programlisting> + <para> + + All the above line does is create a free-standing + &Builder; object. + The next section will show us how to actually use it. + + </para> + </section> <section> @@ -135,17 +147,17 @@ This functionality could be invoked as in the following example: <para> - A &Builder; object by itself, though, - isn't useful until it's attached to a &consenv; + A &Builder; object isn't useful + until it's attached to a &consenv; so that we can call it to arrange for files to be built. This is done through the &BUILDERS; &consvar; in an environment. The &BUILDERS; variable is a Python dictionary - that maps the names by which you want to call various &Builder; - to the &Builder; objects themselves. + that maps the names by which you want to call + various &Builder; objects to the objects themselves. For example, if we want to call the - &Builder; we defined by the name + &Builder; we just defined by the name <function>Foo</function>, our &SConstruct; file might look like: @@ -154,6 +166,16 @@ This functionality could be invoked as in the following example: <programlisting> bld = Builder(action = 'foobuild < $TARGET > $SOURCE') env = Environment(BUILDERS = {'Foo' : bld}) + </programlisting> + + <para> + + With the &Builder; so attached to our &consenv; + we can now actually call it like so: + + </para> + + <programlisting> env.Foo('file.foo', 'file.input') </programlisting> @@ -310,6 +332,7 @@ This functionality could be invoked as in the following example: You can, instead, define a Python function that a &Builder; object can invoke to build your target file (or files). + Such a &buildfunc; definition looks like: </para> @@ -321,8 +344,70 @@ This functionality could be invoked as in the following example: <para> - XXX explain the function - XXX define the arguments + The arguments of a &buildfunc; are: + + </para> + + <variablelist> + + <varlistentry> + <term>target</term> + + <listitem> + <para> + + A list of Node objects representing + the target or targets to be + built by this builder function. + The file names of these target(s) + may be extracted using the Python &str; funcion. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>source</term> + + <listitem> + <para> + + A list of Node objects representing + the sources to be + used by this builder function to build the targets. + The file names of these source(s) + may be extracted using the Python &str; funcion. + + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>env</term> + + <listitem> + <para> + + The &consenv; used for building the target(s). + The builder function may use any of the + environment's construction variables + in any way to affect how it builds the targets. + + </para> + </listitem> + </varlistentry> + + </variablelist> + + <para> + + The builder function must + return a <literal>0</literal> or <literal>None</literal> value + if the target(s) are built successfully. + The builder function + may raise an exception + or return any non-zero value + to indicate that the build is unsuccessful, </para> @@ -367,17 +452,120 @@ This functionality could be invoked as in the following example: </section> <section> - <title>Builders That Generate Actions</title> + <title>Builders That Create Actions Using a &Generator;</title> <para> - X + &SCons; Builder objects can create an action "on the fly" + by using a function called a &generator;. + This provides a great deal of flexibility XXX + A &generator; looks like: </para> <programlisting> - def generate_actions(XXX): + def generate_actions(source, target, env, for_signature): return XXX + </programlisting> + + <para> + + The arguments of a &generator; are: + + </para> + + <variablelist> + + <varlistentry> + <term>source</term> + + <listitem> + <para> + + A list of Node objects representing + the sources to be built + by the command or other action + generated by this function. + The file names of these source(s) + may be extracted using the Python &str; funcion. + + </para> + </listitem> + + </varlistentry> + + <varlistentry> + <term>target</term> + + <listitem> + <para> + + A list of Node objects representing + the target or targets to be built + by the command or other action + generated by this function. + The file names of these target(s) + may be extracted using the Python &str; funcion. + + </para> + </listitem> + + </varlistentry> + + <varlistentry> + <term>env</term> + + <listitem> + <para> + + The &consenv; used for building the target(s). + The generator may use any of the + environment's construction variables + in any way to determine what command + or other action to return. + + </para> + </listitem> + + </varlistentry> + + <varlistentry> + <term>for_signature</term> + + <listitem> + <para> + + A flag that specifies whether the + generator is being called to contribute to a build signature, + as opposed to actually executing the command. + + XXX + + </para> + </listitem> + + </varlistentry> + + </variablelist> + + <para> + + The &generator; must return a + command string or other action that will be used to + build the specified target(s) from the specified source(s). + + </para> + + <para> + + Once you've defined a &generator;, + you create a &Builder; to use it + by specifying the generator keyword argument + instead of <literal>action</literal>. + + </para> + + <programlisting> bld = Builder(generator = generate_actions, suffix = '.foo', src_suffix = '.input') @@ -403,11 +591,12 @@ This functionality could be invoked as in the following example: </section> <section> - <title>Builders That Modify the Target List</title> + <title>Builders That Modify the Target or Source Lists Using an &Emitter;</title> <para> - X + &SCons; supports the ability for a Builder to modify the + lists of target(s) from the specified source(s). </para> @@ -451,7 +640,7 @@ This functionality could be invoked as in the following example: <para> - X + XXX </para> diff --git a/doc/user/caching.sgml b/doc/user/caching.sgml index ed72c1e..3d9158e 100644 --- a/doc/user/caching.sgml +++ b/doc/user/caching.sgml @@ -85,6 +85,8 @@ cc -c hello.c -o hello.o cc -o hello hello.o % <userinput>scons -c</userinput> + Removed hello.o + Removed hello % <userinput>scons</userinput> Retrieved `hello.o' from cache Retrieved `hello' from cache diff --git a/doc/user/cons.sgml b/doc/user/cons.sgml index 448777f..f83ab63 100644 --- a/doc/user/cons.sgml +++ b/doc/user/cons.sgml @@ -25,16 +25,16 @@ <para> - X + XXX </para> <section> - <title>X</title> + <title>XXX</title> <para> - X + XXX </para> diff --git a/doc/user/default.sgml b/doc/user/default.sgml index 981ac42..f44719f 100644 --- a/doc/user/default.sgml +++ b/doc/user/default.sgml @@ -87,7 +87,7 @@ default list. This &SConstruct; file knows how to build two programs, &hello; and &goodbye;, but only builds the - &hello program by default: + &hello; program by default: </para> diff --git a/doc/user/depends.sgml b/doc/user/depends.sgml index bc46618..fbbb54a 100644 --- a/doc/user/depends.sgml +++ b/doc/user/depends.sgml @@ -25,8 +25,6 @@ <!-- - - =head2 The C<Salt> method The C<Salt> method adds a constant value to the signature calculation @@ -97,58 +95,282 @@ operating system on which the build is performed (as reported by C<uname </para> <section> - <title>MD5 Signatures</title> + <title>Source File Signatures</title> <para> - &SCons; keeps track of whether a file has changed - based on the file's contents, - not the modification time. - This means that you may be surprised by the - behavior of &SCons; if you are used to the - &Make; convention of forcing - a rebuild by updating the file's - modification time like so: + The other side of avoiding unnecessary rebuilds + is the fundamental build tool behavior + of <emphasis>rebuilding</emphasis> + things when a source file changes. + &SCons; keeps track of this through a + &signature; for each source file, + and allows you to configure + whether you want to use the source + file contents or the modification time (timestamp) + as the signature. </para> - <literallayout> - % <userinput>scons hello</userinput> - cc -c hello.c -o hello.o - cc -o hello hello.o - % <userinput>touch hello.c</userinput> - % <userinput>scons hello</userinput> - scons: `hello' is up to date. - % - </literallayout> - - <para> - - This avoids unnecessary rebuilds when, - for example, someone rewrites the - contents of a file without making a change. - But if the contents of the file really change, - then &SCons; detects the change - and rebuilds the program as required: + <section> + <title>MD5 Signatures</title> + + <para> + + By default, + &SCons; keeps track of whether a source file has changed + based on the file's contents, + not the modification time. + This means that you may be surprised by the + default &SCons; behavior if you are used to the + &Make; convention of forcing + a rebuild by updating the file's modification time + (using the &touch; command, for example): + + </para> + + <literallayout> + % <userinput>scons hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + % <userinput>touch hello.c</userinput> + % <userinput>scons hello</userinput> + scons: `hello' is up to date. + % + </literallayout> + + <para> + + Even though the file's modification time has changed, + &SCons; realizes that the contents of the + &hello_c; file have <emphasis>not</emphasis> changed, + and therefore that the &hello; program + need not be rebuilt. + This avoids unnecessary rebuilds when, + for example, someone rewrites the + contents of a file without making a change. + But if the contents of the file really do change, + then &SCons; detects the change + and rebuilds the program as required: + + </para> + + <literallayout> + % <userinput>scons hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + % <userinput>edit hello.c</userinput> + [CHANGE THE CONTENTS OF hello.c] + % <userinput>scons hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + % + </literallayout> + + <para> + + Note that you can, if you wish, + specify this default behavior + (MD5 signatures) explicitly + using the &SourceSignatures; function as follows: + + </para> + + <programlisting> + env = Environment() + env.Program('hello.c') + SourceSignatures('MD5') + </programlisting> + + </section> + + <section> + <title>Time Stamps</title> + + <para> + + If you prefer, you can + configure &SCons; to use the modification time + of source files, + not the file contents, + when deciding if something needs to be rebuilt. + To do this, call the &SourceSignatures; + function as follows: + + </para> + + <programlisting> + env = Environment() + env.Program('hello.c') + SourceSignatures('timestamp') + </programlisting> + + <para> + + This makes &SCons; act like &Make; + when a file's modification time is updated + (using the &touch; command, for example): + + </para> + + <literallayout> + % <userinput>scons hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + % <userinput>touch hello.c</userinput> + % <userinput>scons hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + % + </literallayout> + + </section> - </para> + </section> - <literallayout> - % <userinput>scons hello</userinput> - cc -c hello.c -o hello.o - cc -o hello hello.o - % <userinput>edit hello.c</userinput> + <section> + <title>Target File Signatures</title> + + <section> + <title>Build Signatures</title> + + <para> + + We've already seen how modifying a source file + will cause not only its direct target file to be rebuilt, + but also the target file(s) + that depend on that direct target file. + In our example, + changing the contents of &hello_c; cause + the &hello_o; file to be rebuilt, + which in turn causes the + &hello; program to be rebuilt: + + </para> + + <literallayout> + % <userinput>scons hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + % <userinput>edit hello.c</userinput> [CHANGE THE CONTENTS OF hello.c] - % <userinput>scons hello</userinput> - cc -c hello.c -o hello.o - cc -o hello hello.o - % - </literallayout> + % <userinput>scons hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + % + </literallayout> + + <para> + + What's not obvious, though, + is that &SCons; internally handles the signature of + the target file(s) + (&hello_o; in the above example) + differently from the signature of the source file + (&hello_c;). + By default, + &SCons; tracks whether a target file must be rebuilt + by using a &buildsignature; + that consists of the combined + signatures of all the files + that go into making the target file. + This is efficient because + the accumulated signatures + actually give &SCons; all of the + information it needs + to decide if the target file is out of date. + + </para> + + <para> + + If you wish, you can + specify this default behavior + (build signatures) explicitly + using the &TargetSignatures; function: + + </para> + + <programlisting> + env = Environment() + env.Program('hello.c') + TargetSignatures('build') + </programlisting> + + </section> + + <section> + <title>File Contents</title> + + <para> + + Sometimes, however, + a source file can be changed + in such a way that the + target file(s) built from it + will be rebuilt + exactly the same as the last time. + If so, then any target files + that depend on built-but-not-changed target + file actually need not be rebuilt. + You can have &SCons; + realize that a dependent target file + need not be rebuilt in this situation + using the &TargetSignatures; function as follows: + + </para> + + <programlisting> + env = Environment() + env.Program('hello.c') + TargetSignatures('content') + </programlisting> + + <para> + + So if, for example, + a user were to only change a comment in a C file, + then the rebuilt &hello_o; file + would be exactly the same as the one previously built + (assuming the compiler doesn't put any build-specific + information in the object file). + &SCons; would then realize that it would not + need to rebuild the &hello; program as follows: + + </para> + + <literallayout> + % <userinput>scons hello</userinput> + cc -c hello.c -o hello.o + cc -o hello hello.o + % <userinput>edit hello.c</userinput> + [CHANGE A COMMENT IN hello.c] + % <userinput>scons hello</userinput> + cc -c hello.c -o hello.o + % + </literallayout> + + <para> + + In essence, &SCons; has + "short-circuited" any dependent builds + when it realizes that a target file + has been rebuilt to exactly the same file as the last build. + So configured, + &SCons; does take some extra processing time + to scan the contents of the target (&hello_o;) file, + but this may save time + if the rebuild that was avoided + would have been very time-consuming and expensive. + + </para> + + </section> </section> <section> - <title>Implicit Dependencies</title> + <title>Implicit Dependencies: The &CPPPATH; Construction Variable</title> <para> @@ -188,7 +410,7 @@ operating system on which the build is performed (as reported by C<uname </para> <programlisting> - env = Environment(CPPPATH = '.') XXX IS CPPPATH NECESSARY? + env = Environment(CPPPATH = '.') hello = env.Program('hello.c') </programlisting> @@ -199,27 +421,37 @@ operating system on which the build is performed (as reported by C<uname (<literal>'.'</literal>) for any files included by C source files (<filename>.c</filename> or <filename>.h</filename> files). - With this assignment in the &SConstruct file: + With this assignment in the &SConstruct; file: </para> <literallayout> % <userinput>scons hello</userinput> - cc -c hello.c -o hello.o + cc -I. -c hello.c -o hello.o cc -o hello hello.o % <userinput>scons hello</userinput> scons: `hello' is up to date. % <userinput>edit hello.h</userinput> [CHANGE THE CONTENTS OF hello.h] % <userinput>scons hello</userinput> - cc -c hello.c -o hello.o + cc -I. -c hello.c -o hello.o cc -o hello hello.o % </literallayout> <para> - &SCons; knows that the &hello; + First, notice that &SCons; + added the <literal>-I.</literal> argument + from the &CPPPATH; variable + so that the compilation would find the + &hello_h; file in the local directory. + + </para> + + <para> + + Second, realize that &SCons; knows that the &hello; program must be rebuilt because it scans the contents of the &hello_c; file @@ -236,6 +468,49 @@ operating system on which the build is performed (as reported by C<uname </para> + <para> + + Like the &LIBPATH; variable, + the &CPPPATH; variable + may be a list of directories, + or a string separated by + the system-specific path separate character + (':' on POSIX/Linux, ';' on Windows). + Either way, &SCons; creates the + right command-line options + so that the followin example: + + </para> + + <programlisting> + env = Environment(CPPPATH = ['include', '/home/project/inc']) + hello = env.Program('hello.c') + </programlisting> + + <para> + + Will look like this on POSIX or Linux: + + </para> + + <literallayout> + % <userinput>scons hello</userinput> + cc -Iinclude -I/home/project/inc -c hello.c -o hello.o + cc -o hello hello.o + </literallayout> + + <para> + + And like this on Windows: + + </para> + + <literallayout> + % <userinput>scons hello</userinput> + cl /Iinclude /I\home\project\inc /Fohello.obj hello.c + link /OUT:hello.exe hello.obj + </literallayout> + </section> <section> @@ -246,7 +521,7 @@ operating system on which the build is performed (as reported by C<uname Scanning each file for <literal>#include</literal> lines does take some extra processing time. When you're doing a full build of a large system, - the scanning time is a small percentage + the scanning time is usually a very small percentage of the overall time spent on the build. You're most likely to notice the scanning time, however, when you rebuild all or part of a large system: @@ -406,32 +681,10 @@ operating system on which the build is performed (as reported by C<uname <para> - X + XXX </para> </section> --> - - <section> - <title>Time Stamps</title> - - <para> - - X - - </para> - - </section> - - <section> - <title>The &SourceSignature; Method</title> - - <para> - - X - - </para> - - </section> diff --git a/doc/user/environments.sgml b/doc/user/environments.sgml index 77d9c6b..d3c3b0c 100644 --- a/doc/user/environments.sgml +++ b/doc/user/environments.sgml @@ -452,18 +452,20 @@ environment undisturbed. <para> - So far, we've always created a &consenv; named + So far, + all of our examples have + created a single &consenv; named <literal>env</literal>. <literal>env</literal>, however, is simply a Python variable name, - and you can use any other variable name that we like. + and you can use any other variable name that you like. For example: </para> <programlisting> my_env = Environment(CC = 'gcc', - CCFLAGS = '-O2') + CCFLAGS = '-O2') my_env.Program('foo.c') </programlisting> @@ -535,7 +537,7 @@ environment undisturbed. <literal>-O2</literal> and one with a &CCFLAGS; value of <literal>-g</literal>. - To work around this, + To avoid this problem, we must explicitly specify that each environment compile <filename>foo.c</filename> @@ -566,7 +568,7 @@ environment undisturbed. This avoids having to specify explicitly the object file name in multiple places, and makes for a compact, readable - &SConstruct file. + &SConstruct; file. Our &SCons; output then looks like: </para> @@ -586,8 +588,8 @@ environment undisturbed. <para> - Sometimes you want to more than one &consenv; - to use the same values for one or more variables. + Sometimes you want more than one &consenv; + to share the same values for one or more variables. Rather than always having to repeat all of the common variables when you create each &consenv;, you can use the &Copy; method diff --git a/doc/user/errors.sgml b/doc/user/errors.sgml index 448777f..f83ab63 100644 --- a/doc/user/errors.sgml +++ b/doc/user/errors.sgml @@ -25,16 +25,16 @@ <para> - X + XXX </para> <section> - <title>X</title> + <title>XXX</title> <para> - X + XXX </para> diff --git a/doc/user/example.sgml b/doc/user/example.sgml index 448777f..f83ab63 100644 --- a/doc/user/example.sgml +++ b/doc/user/example.sgml @@ -25,16 +25,16 @@ <para> - X + XXX </para> <section> - <title>X</title> + <title>XXX</title> <para> - X + XXX </para> diff --git a/doc/user/hierarchy.sgml b/doc/user/hierarchy.sgml index 617eb59..e39da8f 100644 --- a/doc/user/hierarchy.sgml +++ b/doc/user/hierarchy.sgml @@ -274,7 +274,7 @@ make no difference to the build. <para> - X + XXX </para> @@ -290,7 +290,7 @@ make no difference to the build. <para> - X + XXX </para> @@ -304,7 +304,7 @@ make no difference to the build. <para> - X + XXX </para> @@ -320,7 +320,7 @@ make no difference to the build. <para> - X + XXX </para> @@ -336,7 +336,7 @@ make no difference to the build. <para> - X + XXX </para> diff --git a/doc/user/install.sgml b/doc/user/install.sgml index 2cebbd4..7f522e5 100644 --- a/doc/user/install.sgml +++ b/doc/user/install.sgml @@ -72,7 +72,7 @@ should be installed. This is an area where the &Alias; function comes in handy, - allowing you, if you wish, + allowing you, for example, to create a pseudo-target named <literal>install</literal> that can expand to the specified destination directory: @@ -104,7 +104,7 @@ <para> You can install multiple files into a directory - simploy by calling the &Install; function multiple times: + simply by calling the &Install; function multiple times: </para> diff --git a/doc/user/libraries.sgml b/doc/user/libraries.sgml new file mode 100644 index 0000000..ea41f5d --- /dev/null +++ b/doc/user/libraries.sgml @@ -0,0 +1,250 @@ +<!-- + + 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> + + One of the more useful ways in which you can use multiple + construction environments is to link programs + with different sets of libraries. + + </para> + + <section> + <title>Building Libraries</title> + + <para> + + You build your own libraries by specifying &Library; + instead of &Program;: + + </para> + + <programlisting> + env = Environment() + env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) + </programlisting> + + <para> + + &SCons; uses the appropriate library prefix and suffix for your system. + So on POSIX or Linux systems, + the above example would build as follows + (although &ranlib may not be called on all systems): + + </para> + + <literallayout> + % <userinput>scons</userinput> + cc -c f1.c -o f1.o + cc -c f2.c -o f2.o + cc -c f3.c -o f3.o + ar r libfoo.a f1.o f2.o f3.o + ranlib libfoo.a + </literallayout> + + <para> + + On a Windows system, + a build of the above example would look like: + + </para> + + <literallayout> + C:\><userinput>scons</userinput> + cl /Fof1.obj f1.c + cl /Fof2.obj f2.c + cl /Fof3.obj f3.c + lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj + </literallayout> + + <para> + + The rules for the target name of the library + are similar to those for programs: + if you don't explicitly specify a target library name, + &SCons; will deduce one from the + name of the first source file specified, + and &SCons; will add an appropriate + file prefix and suffix if you leave them off. + + </para> + + </section> + + <section> + <title>Linking with Libraries</title> + + <para> + + Usually, the goal of building a library + is to link it with one or more programs. + You link libraries with a program by specifying + the libraries in the &LIBS; construction variable, + and by specifying the directory in which + the library will be found in the + &LIBPATH; construction variable: + + </para> + + <programlisting> + env = Environment(LIBS = 'foo', LIBPATH = '.') + env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) + env.Program('prog.c') + </programlisting> + + <para> + + Notice, of course, that you don't need to specify a library + prefix (like <literal>lib</literal>) + or suffix (like <literal>.a</literal> or <literal>.lib</literal>). + &SCons; uses the correct prefix or suffix for the current system. + + </para> + + <para> + + On a POSIX or Linux system, + a build of the above example would look like: + + </para> + + <literallayout> + % <userinput>scons</userinput> + cc -c f1.c -o f1.o + cc -c f2.c -o f2.o + cc -c f3.c -o f3.o + ar r libfoo.a f1.o f2.o f3.o + ranlib libfoo.a + cc -c prog.c -o prog.o + cc -o prog -L. -lfoo prog.o + </literallayout> + + <para> + + On a Windows system, + a build of the above example would look like: + + </para> + + <literallayout> + C:\><userinput>scons</userinput> + cl /Fof1.obj f1.c + cl /Fof2.obj f2.c + cl /Fof3.obj f3.c + lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj + cl /Foprog.obj prog.c + link /OUT:prog.exe /LIBPATH:. foo.lib prog.obj + </literallayout> + + <para> + + As usual, notice that &SCons; has taken care + of constructing the correct command lines + to link with the specified library on each system. + + </para> + + </section> + + <section> + <title>Finding Libraries: the &LIBPATH; Construction Variable</title> + + <para> + + By default, the linker will only look in + certain system-defined directories for libraries. + &SCons; knows how to look for libraries + in directories that you specify with the + &LIBPATH; construction variable. + &LIBPATH; consists of a list of + directory names, like so: + + </para> + + <programlisting> + env = Environment(LIBS = 'm', + LIBPATH = ['/usr/lib', '/usr/local/lib']) + env.Program('prog.c') + </programlisting> + + <para> + + Using a Python list is preferred because it's portable + across systems. Alternatively, you could put all of + the directory names in a single string, separated by the + system-specific path separator character: + a colon on POSIX systems: + + </para> + + <programlisting> + LIBPATH = '/usr/lib:/usr/local/lib' + </programlisting> + + <para> + + or a semi-colon on Windows systems: + + </para> + + <programlisting> + LIBPATH = 'C:\lib;D:\lib' + </programlisting> + + <para> + + On a POSIX or Linux system, + a build of the above example would look like: + + </para> + + <literallayout> + % <userinput>scons</userinput> + cc -c prog.c -o prog.o + cc -o prog -L/usr/lib -L/usr/local/lib -lm prog.o + </literallayout> + + <para> + + On a Windows system, + a build of the above example would look like: + + </para> + + <literallayout> + C:\><userinput>scons</userinput> + cl /Foprog.obj prog.c + link /nologo /OUT:program.exe /LIBPATH:\usr\lib;\usr\local\lib m.lib prog.obj + </literallayout> + + <para> + + Note again that &SCons; has taken care of + the system-specific details of creating + the right command-line options. + + </para> + + </section> diff --git a/doc/user/main.sgml b/doc/user/main.sgml index 9ea4dd5..12b0480 100644 --- a/doc/user/main.sgml +++ b/doc/user/main.sgml @@ -34,9 +34,11 @@ <!ENTITY actions SYSTEM "actions.sgml"> <!ENTITY alias SYSTEM "alias.sgml"> - <!ENTITY builders SYSTEM "builders.sgml"> + <!ENTITY ant SYSTEM "ant.sgml"> + <!ENTITY builders-built-in SYSTEM "builders-built-in.sgml"> + <!ENTITY builders-commands SYSTEM "builders-commands.sgml"> + <!ENTITY builders-writing SYSTEM "builders-writing.sgml"> <!ENTITY caching SYSTEM "caching.sgml"> - <!ENTITY command SYSTEM "command.sgml"> <!ENTITY cons SYSTEM "cons.sgml"> <!ENTITY copyright SYSTEM "copyright.sgml"> <!ENTITY default SYSTEM "default.sgml"> @@ -47,6 +49,7 @@ <!ENTITY help SYSTEM "help.sgml"> <!ENTITY hierarchy SYSTEM "hierarchy.sgml"> <!ENTITY install SYSTEM "install.sgml"> + <!ENTITY libraries SYSTEM "libraries.sgml"> <!ENTITY make SYSTEM "make.sgml"> <!ENTITY precious SYSTEM "precious.sgml"> <!ENTITY preface SYSTEM "preface.sgml"> @@ -102,6 +105,11 @@ &environments; </chapter> + <chapter id="chap-libraries"> + <title>Building and Linking with Libraries</title> + &libraries; + </chapter> + <chapter id="chap-depends"> <title>Dependencies</title> &depends; @@ -142,14 +150,19 @@ &variants; </chapter> - <chapter id="chap-builders"> - <title>Writing Builders</title> - &builders; + <chapter id="chap-builders-built-in"> + <title>Built-In Builders</title> + &builders-built-in; + </chapter> + + <chapter id="chap-builders-writing"> + <title>Writing Your Own Builders</title> + &builders-writing; </chapter> - <chapter id="chap-command"> - <title>Not Writing a Builder (for One-Time Builds)</title> - &command; + <chapter id="chap-builders-commands"> + <title>Not Writing a Builder: The &Command; Builder</title> + &builders-commands; </chapter> <chapter id="chap-actions"> @@ -222,4 +235,9 @@ &cons; </appendix> + <appendix id="app-ant"> + <title>Converting From Ant</title> + &ant; + </appendix> + </book> diff --git a/doc/user/make.sgml b/doc/user/make.sgml index 5666ea6..c7ecc63 100644 --- a/doc/user/make.sgml +++ b/doc/user/make.sgml @@ -94,16 +94,16 @@ the makefiles. <para> - X + XXX </para> <section> - <title>X</title> + <title>XXX</title> <para> - X + XXX </para> diff --git a/doc/user/preface.sgml b/doc/user/preface.sgml index 82ea44a..bba7f49 100644 --- a/doc/user/preface.sgml +++ b/doc/user/preface.sgml @@ -23,63 +23,182 @@ --> - <para> + <para> - X + XXX - </para> + </para> - <section> - <title>Why &SCons;?</title> + <section> + <title>Why &SCons;?</title> - <para> + <para> - X + XXX - </para> + </para> - </section> + </section> - <section> - <title>History</title> + <section> + <title>&SCons; Principles</title> - <para> + <para> - X + By default, &SCons; guarantees a correct build + regardless of what end case you may have. - </para> + </para> - </section> + <para> - <section> - <title>Conventions</title> + &SCons; makes it easy to speed up the build through + optimization options that trade off + guaranteed correctness for speed. - <para> + </para> - X + <para> - </para> + &SCons; tries to do as much for you out of the box as reasonable. - </section> + </para> - <section> - <title>Acknowledgements</title> + </section> - <para> + <section> + <title>History</title> - X + <para> - </para> + &SCons; originated with a design + that was submitted to the Software Carpentry + design competition in 2000. - </section> + </para> - <section> - <title>Contact</title> + <para> - <para> + &SCons; is the direct descendant + of a Perl utility called &Cons;. + &Cons; in turn based some of its ideas on &Jam;, + a build tool from Perforce Systems. - X + </para> - </para> + </section> - </section> + <section> + <title>Conventions</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Acknowledgements</title> + + <para> + + &SCons; would not exist without a lot of help + from a lot of people, + many of whom may not even be aware + that they helped or served as inspiration. + So in no particular order, + and at the risk of leaving out someone: + + </para> + + <para> + + First and foremost, + &SCons; owes a tremendous debt to Bob Sidebotham, + the original author of the classic Perl-based &Cons; tool + which Bob first released to the world back around 1996. + Bob's work on Cons classic provided the underlying architecture + and model of specifying a build configuration + using a real scripting language. + My real-world experience working on Cons + informed many of the design decisions in SCons, + including the improved parallel build support, + making Builder objects easily definable by users, + and separating the build engine from the wrapping interface. + + </para> + + <para> + + Greg Wilson was instrumental in getting + &SCons; started as a real project + when he initiated the Software Carpentry design + competition in February 2000. + Without that nudge, + marrying the advantages of the Cons classic + architecture with the readability of Python + might have just stayed no more than a nice idea. + + </para> + + <para> + + The entire &SCons; team have been + absolutely wonderful to work with, + and &SCons; would be nowhere near as useful a + tool without the energy, enthusiasm + and time people have contributed over the past few years. + The "core team" + of Chad Austin, Anthony Roach, Charles Crain, and Steve Leblanc + have been great about reviewing my (and other) changes + and catching problems before they get in the code base. + Technically, + Anthony's outstanding and innovative work on the tasking engine + has given &SCons; a vastly superior parallel build model, + and Charles has been the master of the crucial Node infrastructure. + &SCons; has received contributions + from many other people, of course: + Matt Balvin (extending long command-line support on Win32), + Michael Cook (avoiding losing signal bits from executed commands), + Derrick 'dman' Hudson (), + Alex Jacques (work on the Win32 scons.bat file), + Stephen Kennedy (performance enhancements), + Lachlan O'Dea (SharedObject() support for masm + and normalized paths for the WhereIs() function), + Jeff Petkau (fixes for CacheDir and other areas), + Zed Shaw (Append() and Replace() environment methods), + Terrel Shumway (build and test fixes, as well as the SCons Wiki), + sam th (dynamic checks for utilities) + and Moshe Zadke (Debian packaging). + + </para> + + <para> + + Thanks to Peter Miller + for his splendid change management system, &Aegis;, + which has provided the &SCons; project + with a robust development methodology from day one, + and which showed me how you could + integrate incremental regression tests into + a practical development cycle + (years before eXtreme Programming arrived on the scene). + + </para> + + </section> + + <section> + <title>Contact</title> + + <para> + + The best way to contact people involved with SCons, + including the author, + is through the SCons mailing lists. + + </para> + + </section> diff --git a/doc/user/repositories.sgml b/doc/user/repositories.sgml index 616e903..07af115 100644 --- a/doc/user/repositories.sgml +++ b/doc/user/repositories.sgml @@ -288,7 +288,7 @@ subdirectories under the repository tree. about the pathname of the repository? To solve this problem, &SCons; allows you to specify repository directories - on the command line using the <literal>-Y</literal>: + on the command line using the <literal>-Y</literal> option: </para> diff --git a/doc/user/run.sgml b/doc/user/run.sgml index 30b61ca..83ca3d2 100644 --- a/doc/user/run.sgml +++ b/doc/user/run.sgml @@ -266,48 +266,6 @@ rebuilt, if necessary, and then installed there. Note that C<cons build> might build files that C<cons export> doesn't build, and vice-versa. -=head2 No ``special'' targets - -With Cons, make-style ``special'' targets are not required. The simplest -analog with Cons is to use special F<export> directories, instead. Let's -suppose, for example, that you have a whole series of unit tests that are -associated with your code. The tests live in the source directory near the -code. Normally, however, you don't want to build these tests. One solution -is to provide all the build instructions for creating the tests, and then to -install the tests into a separate part of the tree. If we install the tests -in a top-level directory called F<tests>, then: - - % cons tests - -will build all the tests. - - % cons export - -will build the production version of the system (but not the tests), and: - - % cons build - -should probably be avoided (since it will compile tests unnecessarily). - -If you want to build just a single test, then you could explicitly name the -test (in either the F<tests> directory or the F<build> directory). You could -also aggregate the tests into a convenient hierarchy within the tests -directory. This hierarchy need not necessarily match the source hierarchy, -in much the same manner that the include hierarchy probably doesn't match -the source hierarchy (the include hierarchy is unlikely to be more than two -levels deep, for C programs). - -If you want to build absolutely everything in the tree (subject to whatever -options you select), you can use: - - % cons . - -This is not particularly efficient, since it will redundantly walk all the -trees, including the source tree. The source tree, of course, may have -buildable objects in it-,-nothing stops you from doing this, even if you -normally build in a separate build tree. - - =head1 Build Pruning In conjunction with target selection, B<build pruning> can be used to reduce @@ -351,52 +309,56 @@ do an unconstrained build before committing the integration). --> - <para> + <para> + + XXX + + </para> - X + <section> + <title>Selective Builds</title> - </para> + <para> - <section> - <title>Selective Builds</title> + XXX - <para> + </para> - X + </section> - </para> + <!-- - </section> + <section> + <title>Build Pruning</title> - <section> - <title>Build Pruning</title> + <para> - <para> + XXX - X + </para> - </para> + </section> - </section> + --> - <section> - <title>Overriding Construction Variables</title> + <section> + <title>Overriding Construction Variables</title> - <para> + <para> - X + XXX - </para> + </para> - </section> + </section> - <section> - <title>The &SCONSFLAGS; Environment Variable</title> + <section> + <title>The &SCONSFLAGS; Environment Variable</title> - <para> + <para> - X + XXX - </para> + </para> - </section> + </section> diff --git a/doc/user/scanners.sgml b/doc/user/scanners.sgml index 8d13b0c..76b2a1a 100644 --- a/doc/user/scanners.sgml +++ b/doc/user/scanners.sgml @@ -123,16 +123,16 @@ over the file scanning rather than being called for each input line: <para> - X + XXX </para> <section> - <title>X</title> + <title>XXX</title> <para> - X + XXX </para> diff --git a/doc/user/separate.sgml b/doc/user/separate.sgml index 21fcabc..ac3c0f3 100644 --- a/doc/user/separate.sgml +++ b/doc/user/separate.sgml @@ -110,228 +110,322 @@ program using the F<build/foo.c> path name. --> - <para> + <para> - It's often useful to keep any built files completely - separate from the source files. - This is usually done by creating one or more separate - <emphasis>build directories</emphasis> - that are used to hold the built objects files, libraries, - and executable programs, etc. - for a specific flavor of build. - &SCons; provides two ways of doing this, - one with a little more flexibility. + It's often useful to keep any built files completely + separate from the source files. + This is usually done by creating one or more separate + <emphasis>build directories</emphasis> + that are used to hold the built objects files, libraries, + and executable programs, etc. + for a specific flavor of build. + &SCons; provides two ways to do this, + one through the &SConscript; function that we've already seen, + and the second through a more flexible &BuildDir; function. - </para> + </para> - <section> - <title>The &BuildDir; Function</title> + <section> + <title>Specifying a Build Directory as Part of an &SConscript; Call</title> - <para> + <para> - Use the &BuildDir; function to establish that target - files should be built in a separate directory - from the source files: + The most straightforward way to establish a build directory + uses the fact that the usual way to + set up a build hierarcy is to have an + &SConscript; file in the source subdirectory. + If you then pass a &build_dir; argument to the + &SConscript; function call: - </para> + </para> - <programlisting> - BuildDir('build', 'src') - env = Environment() - env.Program('build/hello.c') - </programlisting> + <programlisting> + SConscript('src/SConscript', build_dir='build') + </programlisting> - <para> + <para> - Note that XXX + &SCons; will then build all of the files in + the &build; subdirectory: - </para> + </para> - <literallayout> - % <userinput>ls src</userinput> - hello.c - % <userinput>scons</userinput> - cc -c build/hello.c -o build/hello.o - cc -o build/hello build/hello.o - % <userinput>ls -1 build</userinput> - hello - hello.c - hello.o - </literallayout> + <literallayout> + % <userinput>ls -1 src</userinput> + SConscript + hello.c + % <userinput>scons</userinput> + cc -c build/hello.c -o build/hello.o + cc -o build/hello build/hello.o + % <userinput>ls -1 build</userinput> + hello + hello.c + hello.o + </literallayout> - </section> + <para> - <section> - <title>Avoiding Duplicate Source Files in the Build Directory</title> + But wait a minute--what's going on here? + &SCons; created the object file + <filename>build/hello.o</filename> + in the &build; subdirectory, + as expected. + But even though our &hello_c; file lives in the &src; subdirectory, + &SCons; has actually compiled a + <filename>build/hello.c</filename> file + to create the object file. - <para> + </para> - X + <para> - </para> + What's happened is that &SCons; has <emphasis>duplicated</emphasis> + the &hello_c; file from the &src; subdirectory + to the &build; subdirectory, + and built the program from there. + The next section explains why &SCons; does this. - <programlisting> - BuildDir('build', 'src', duplicate=0) - env = Environment() - env.Program('build/hello.c') - </programlisting> + </para> - <para> + </section> - X + <section> + <title>Why &SCons; Duplicates Source Files in a Build Directory</title> - </para> + <para> - <literallayout> - % <userinput>ls -1 src</userinput> - hello.c - % <userinput>scons</userinput> - cc -c src/hello.c -o build/hello.o - cc -o build/hello build/hello.o - % <userinput>ls -1 build</userinput> - hello - hello.o - </literallayout> + &SCons; duplicates source files in build directories + because it's the most straightforward way to guarantee a correct build + <emphasis>regardless of include-file directory paths</emphasis>, + and the &SCons; philosophy is to, by default, + guarantee a correct build in all cases. + Here is an example of an end case where duplicating + source files in a build directory + is necessary for a correct build: - <para> + </para> - X + <para> - </para> + XXX - </section> + </para> - <section> - <title>Why &SCons; Duplicates Source Files by Default</title> + <programlisting> + env = Environmnet() + </programlisting> - <para> + <para> - X + XXX - </para> + </para> - <programlisting> - env = Environmnet() - </programlisting> + <literallayout> + % <userinput>scons</userinput> + cc -c build/hello.c -o build/hello.o + cc -o build/hello build/hello.o + </literallayout> - <para> + </section> - X + <section> + <title>Telling &SCons; to Not Duplicate Source Files in the Build Directory</title> - </para> + <para> - <literallayout> - % <userinput>scons</userinput> - cc -c build/hello.c -o build/hello.o - cc -o build/hello build/hello.o - </literallayout> + In most cases, however, + having &SCons; place its target files in a build subdirectory + <emphasis>without</emphasis> + duplicating the source files works just fine. + You can disable the default &SCons; behavior + by specifying <literal>duplicate=0</literal> + when you call the &SConscript; function: - </section> + </para> - <section> - <title>Using &BuildDir; With an &SConscript; File</title> + <programlisting> + SConscript('src/SConscript', build_dir='build', duplicate=0) + </programlisting> - <para> + <para> - X + When this flag is specified, + &SCons; uses the build directory + like most people expect--that is, + the output files are placed in the build directory + while the source files stay in the source directory: - </para> + </para> - <programlisting> - env = Environment() - env.Program('hello.c') - </programlisting> + <literallayout> + % <userinput>ls -1 src</userinput> + SConscript + hello.c + % <userinput>scons</userinput> + cc -c src/hello.c -o build/hello.o + cc -o build/hello build/hello.o + % <userinput>ls -1 build</userinput> + hello + hello.o + </literallayout> - <para> + </section> - X + <section> + <title>The &BuildDir; Function</title> - </para> + <para> - <programlisting> - BuildDir('build', 'src') - SConscript('build/SConscript') - </programlisting> + Use the &BuildDir; function to establish that target + files should be built in a separate directory + from the source files: - <para> + </para> - X + <programlisting> + BuildDir('build', 'src') + env = Environment() + env.Program('build/hello.c') + </programlisting> - </para> + <para> - <literallayout> - % <userinput>ls -1 src</userinput> - SConscript - hello.c - % <userinput>scons</userinput> - cc -c build/hello.c -o build/hello.o - cc -o build/hello build/hello.o - % <userinput>ls -1 build</userinput> - hello - hello.c - hello.o - </literallayout> + Note that when you're not using + an &SConscript; file in the &src; subdirectory, + you must actually specify that + the program must be built from + the <filename>build/hello.c</filename> + file that &SCons; will duplicate in the + &build; subdirectory. - </section> + </para> - <section> - <title>Specifying a Build Directory as Part of an &SConscript; Call</title> + <para> - <para> + XXX - X + </para> - </para> + <para> - <programlisting> - SConscript('src/SConscript', build_dir='build') - </programlisting> + When using the &BuildDir; function directly, + &SCons; still duplicates the source files + in the build directory by default: - <para> + </para> - X + <literallayout> + % <userinput>ls src</userinput> + hello.c + % <userinput>scons</userinput> + cc -c build/hello.c -o build/hello.o + cc -o build/hello build/hello.o + % <userinput>ls -1 build</userinput> + hello + hello.c + hello.o + </literallayout> - </para> + <para> - <literallayout> - % <userinput>ls -1 src</userinput> - SConscript - hello.c - % <userinput>scons</userinput> - cc -c build/hello.c -o build/hello.o - cc -o build/hello build/hello.o - % <userinput>ls -1 build</userinput> - hello - hello.c - hello.o - </literallayout> + You can specify the same <literal>duplicate=0</literal> argument + that you can specify for an &SConscript; call: - <para> + </para> - X + <programlisting> + BuildDir('build', 'src', duplicate=0) + env = Environment() + env.Program('build/hello.c') + </programlisting> - </para> + <para> - <programlisting> - SConscript('src/SConscript', build_dir='build', duplicate=0) - </programlisting> + In which case &SCons; + will disable duplication of the source files: - <para> + </para> - X + <literallayout> + % <userinput>ls src</userinput> + hello.c + % <userinput>scons</userinput> + cc -c src/hello.c -o build/hello.o + cc -o build/hello build/hello.o + % <userinput>ls -1 build</userinput> + hello + hello.o + </literallayout> - </para> + </section> - <literallayout> - % <userinput>ls -1 src</userinput> - SConscript - hello.c - % <userinput>scons</userinput> - cc -c src/hello.c -o build/hello.o - cc -o build/hello build/hello.o - % <userinput>ls -1 build</userinput> - hello - hello.o - </literallayout> + <section> + <title>Using &BuildDir; With an &SConscript; File</title> - </section> + <para> + + Even when using the &BuildDir; function, + it's much more natural to use it with + a subsidiary &SConscript; file. + For example, if the + <filename>src/SConscript</filename> + looks like this: + + </para> + + <programlisting> + env = Environment() + env.Program('hello.c') + </programlisting> + + <para> + + Then our &SConscript; file could look like: + + </para> + + <programlisting> + BuildDir('build', 'src') + SConscript('build/SConscript') + </programlisting> + + <para> + + Yielding the following output: + + </para> + + <literallayout> + % <userinput>ls -1 src</userinput> + SConscript + hello.c + % <userinput>scons</userinput> + cc -c build/hello.c -o build/hello.o + cc -o build/hello build/hello.o + % <userinput>ls -1 build</userinput> + hello + hello.c + hello.o + </literallayout> + + <para> + + Notice that this is completely equivalent + to the use of &SConscript; that we + learned about in the previous section. + + </para> + + </section> + + <section> + <title>Why You'd Want to Call &BuildDir; Instead of &SConscript;</title> + + <para> + + XXX + + </para> + + </section> diff --git a/doc/user/simple.sgml b/doc/user/simple.sgml index 2acd669..8f76f2a 100644 --- a/doc/user/simple.sgml +++ b/doc/user/simple.sgml @@ -43,7 +43,7 @@ requirements of a build. <para> - Here's how to build the famous "Hello, World!" example using &SCons;. + Here's the famous "Hello, World!" program in C: </para> @@ -57,7 +57,8 @@ requirements of a build. <para> - Enter the following into a file name &SConstruct;: + And here's how to build it using &SCons;. + Enter the following into a file named &SConstruct;: </para> @@ -144,7 +145,7 @@ requirements of a build. What may not be obvious, though, is that there's an important difference between - an &SConstruct; file and a &Makefile: + an &SConstruct; file and a &Makefile;: the &SConstruct; file is actually a Python script. If you're not already familiar with Python, don't worry; Python is very easy to learn, @@ -193,29 +194,58 @@ requirements of a build. To do this, you need to put the source files in a Python list (enclosed in square brackets), - and slide that list over to to the right - to make room for the output program file name. - For example: + like so: </para> <programlisting> env = Environment() - env.Program('program', ['main.c', 'file1.c', 'file2.']) + env.Program(['prog.c', 'file1.c', 'file2.']) </programlisting> <para> + A build of the above example would look like: + + </para> + + <literallayout> + % <userinput>scons</userinput> + cc -c file1.c -o file1.o + cc -c file2.c -o file2.o + cc -c prog.c -o prog.o + cc -o prog prog.o file1.o file2.o + </literallayout> + + <para> + + Notice that &SCons; + deduces the output program name + from the first source file specified + in the list--that is, + because the first source file was &prog_c;, + &SCons; will name the resulting program &prog; + (or &prog_exe; on a Windows system). + If you want to specify a different program name, + then you slide the list of source files + over to the right + to make room for the output program file name. (&SCons; puts the output file name to the left of the source file names so that the order mimics that of an assignment statement: "program = source files".) + This makes our example: </para> + <programlisting> + env = Environment() + env.Program('program', ['main.c', 'file1.c', 'file2.']) + </programlisting> + <para> - A build of the above example would look: + On Linux, a build of this example would look like: </para> @@ -227,11 +257,7 @@ requirements of a build. cc -o program main.o file1.o file2.o </literallayout> - <!-- - - XXX DO WE NEED WINDOWS EXAMPLE OUTPUT HERE? - - </para> + <para> Or on Windows: @@ -245,8 +271,6 @@ requirements of a build. link /Foprogram.exe main.obj file1.obj file2.obj </literallayout> - --> - </section> <section> @@ -260,8 +284,8 @@ requirements of a build. (either single quotes or double quotes). This can get cumbersome and difficult to read when the list of file names is long. - Fortunately, there are a number of things - we can do to make sure that + Fortunately, &SCons; and Python provide a number of ways + to make sure that the &SConstruct; file stays easy to read. </para> @@ -363,7 +387,7 @@ requirements of a build. In order to compile multiple programs within the same &SConstruct; file, - simply call <function>env.Program</function> + simply call the <function>env.Program</function> method multiple times, once for each program you need to build: @@ -390,6 +414,19 @@ requirements of a build. cc -o foo foo.o </literallayout> + <para> + + Notice that &SCons; does not necessarily build the + programs in the same order in which you specify + them in the &SConstruct; file. + &SCons; does, however, recognize that + the individual object files must be built + before the resulting program can be built. + We'll discuss this in greater detail in + the "Dependencies" section, below. + + </para> + </section> <section> @@ -397,17 +434,40 @@ requirements of a build. <para> - XXX + It's common to re-use code by sharing source files + between multiple programs. + One way to do this is to create a library + from the common source files, + which can then be linked into resulting programs. + (Creating libraries is discussed in + section XXX, below.) + + </para> + + <para> + + A more straightforward, but perhaps less convenient, + way to share source files between multiple programs + is to simply include the common source files + when listing the source files for each program: </para> <programlisting> - common = ['common1.c', 'common2.c'] env = Environment() - env.Program(['foo.c'] + common) - env.Program('bar', ['bar1.c', 'bar2.c'] + common) + env.Program(Split('foo.c common1.c common2.c')) + env.Program('bar', Split('bar1.c bar2.c common1.c common2.c')) </programlisting> + <para> + + &SCons; recognizes that the object files for + the &common1_c; and &common2_c; source files + each only need to be built once, + even though the files are listed multiple times: + + </para> + <literallayout> % <userinput>scons</userinput> cc -c bar1.c -o bar1.o @@ -419,4 +479,33 @@ requirements of a build. cc -o foo foo.o common1.o common2.o </literallayout> + <para> + + If two or more programs + share a lot of common source files, + repeating the common files in the list for each program + a maintenance problem if you need to change the + list of common files. + You can simplify this by creating a separate Python list + to hold the common file names, + and concatenating it with other lists + using the Python &+; operator: + + </para> + + <programlisting> + common = ['common1.c', 'common2.c'] + foo_files = ['foo.c'] + common + bar_files = ['bar1.c', 'bar2.c'] + common + env = Environment() + env.Program('foo', foo_files) + env.Program('bar', bar_files) + </programlisting> + + <para> + + This is functionally equivalent to the previous example. + + </para> + </section> diff --git a/doc/user/sourcecode.sgml b/doc/user/sourcecode.sgml index 4ee49d4..6bbccee 100644 --- a/doc/user/sourcecode.sgml +++ b/doc/user/sourcecode.sgml @@ -44,7 +44,7 @@ <programlisting> env = Environment() - env.SourceCode('.', env.BitKeeper('XXX') + env.SourceCode('.', env.BitKeeper('XXX')) env.Program('hello.c') </programlisting> @@ -66,7 +66,7 @@ <programlisting> env = Environment() - env.SourceCode('.', env.CVS('XXX') + env.SourceCode('.', env.CVS('XXX')) env.Program('hello.c') </programlisting> @@ -88,7 +88,7 @@ <programlisting> env = Environment() - env.SourceCode('.', env.RCS() + env.SourceCode('.', env.RCS()) env.Program('hello.c') </programlisting> @@ -110,7 +110,7 @@ <programlisting> env = Environment() - env.SourceCode('.', env.SCCS() + env.SourceCode('.', env.SCCS()) env.Program('hello.c') </programlisting> @@ -132,7 +132,7 @@ <programlisting> env = Environment() - env.SourceCode('.', env.Subversion('XXX') + env.SourceCode('.', env.Subversion('XXX')) env.Program('hello.c') </programlisting> diff --git a/doc/user/troubleshoot.sgml b/doc/user/troubleshoot.sgml index 448777f..f83ab63 100644 --- a/doc/user/troubleshoot.sgml +++ b/doc/user/troubleshoot.sgml @@ -25,16 +25,16 @@ <para> - X + XXX </para> <section> - <title>X</title> + <title>XXX</title> <para> - X + XXX </para> diff --git a/doc/user/variants.sgml b/doc/user/variants.sgml index 6ad9360..09dd16d 100644 --- a/doc/user/variants.sgml +++ b/doc/user/variants.sgml @@ -107,40 +107,89 @@ is pretty smart about rebuilding things when you change options. --> - <para> - - X - - </para> - - <section> - <title>X</title> - - <para> - - X - - </para> - - <programlisting> - env = Environment(OS = ARGUMENT['os']) - SConscript('src/SConscript', build_dir='build/$OS') - </programlisting> - - <para> - - X - - </para> - - <programlisting> - env = Environment(OS = ) - for os in ['newell', 'post']: - SConscript('src/SConscript', build_dir='build/' + os) - </programlisting> - - <literallayout> - % <userinput>scons</userinput> - </literallayout> - - </section> + <para> + + The &BuildDir; function now gives us everything + we need to show how easy it is to create + variant builds using &SCons;. + Suppose, for example, that we want to + build a program for both Windows and Linux platforms, + but that we want to build it in a shared directory + with separate side-by-side build directories + for the Windows and Linux versions of the program. + + </para> + + <programlisting> + platform = ARGUMENT.get('OS', Platform()) + + include = "#export/$PLATFORM/include" + lib = "#export/$PLATFORM/lib" + bin = "#export/$PLATFORM/bin" + + env = Environment(PLATFORM = platform, + CPPPATH = [include], + LIB = lib, + LIBS = '-lworld') + + Export('env') + + SConscript('src/SConscript', build_dir='build/$PLATFORM') + + # + #BuildDir("#build/$PLATFORM", 'src') + #SConscript("build/$PLATFORM/hello/SConscript") + #SConscript("build/$PLATFORM/world/SConscript") + </programlisting> + + <para> + + This SConstruct file, + when run on a Linux system, yields: + + </para> + + <literallayout> + $ <userinput>scons OS=linux</userinput> + Install build/linux/world/world.h as export/linux/include/world.h + cc -Iexport/linux/include -c build/linux/hello/hello.c -o build/linux/hello/hello.o + cc -Iexport/linux/include -c build/linux/world/world.c -o build/linux/world/world.o + ar r build/linux/world/libworld.a build/linux/world/world.o + ar: creating build/linux/world/libworld.a + ranlib build/linux/world/libworld.a + Install build/linux/world/libworld.a as export/linux/lib/libworld.a + cc -o build/linux/hello/hello build/linux/hello/hello.o -Lexport/linux/lib -lworld + Install build/linux/hello/hello as export/linux/bin/hello + </literallayout> + + <para> + + The same SConstruct file on Windows would build: + + </para> + + <!-- + cl /Fohello.obj hello.c + link /Fohello.exe hello.obj + --> + <literallayout> + C:\test\><userinput>scons OS=linux</userinput> + Install build\linux\world\world.h as export\linux\include\world.h + cl /Iexport\linux\include /Fobuild\linux\hello\hello.obj build\linux\hello\hello.c + cl /Iexport\linux\include /Fobuild\linux\world\world.obj build\linux\world\world.c + XXX + ar r build\linux\world\world.lib build\linux\world\world.obj + Install build\linux\world\world.lib as export\linux\lib\libworld.a + link /Fobuild\linux\hello\hello.exe build\linux\hello\hello.obj -Lexport\linux\lib world.lib + Install build\linux\hello\hello.exe as export\linux\bin\hello.exe + </literallayout> + + <programlisting> + env = Environment(OS = ) + for os in ['newell', 'post']: + SConscript('src/SConscript', build_dir='build/' + os) + </programlisting> + + <literallayout> + % <userinput>scons</userinput> + </literallayout> |