#
#
-# __COPYRIGHT__
+# 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
'text' : 0,
'graphics' : [ 'arch', 'builder', 'job-task', 'node', 'scanner', 'sig' ],
},
+ 'reference' : {
+ 'htmlindex' : 'book1.html',
+ 'html' : 1,
+ 'ps' : 1,
+ 'pdf' : 1,
+ 'text' : 0,
+ },
'user' : {
'htmlindex' : 'book1.html',
'html' : 1,
--- /dev/null
+*,D
+.*.swp
+.consign
+.sconsign
</para>
<section>
- <title>The &Module; Method</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
-
- <section>
- <title>The &RuleSet; Method</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
-
- <section>
- <title>The &DefaultRules; Method</title>
+ <title>The &Alias; Method</title>
<para>
--- /dev/null
+<!--
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &CFile; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
--- /dev/null
+<!--
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &CXXFile; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
--- /dev/null
+<!--
+
+ 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.
+
+-->
+
+<!--
+
+=head2 The C<Command> method
+
+The C<Command> method is a catchall method which can be used to arrange for
+any build action to be executed to update the target. For this command, a
+target file and list of inputs is provided. In addition, a build action
+is specified as the last argument. The build action is typically a
+command line or lines, but may also contain Perl code to be executed;
+see the section above on build actions for details.
+
+The C<Command> method is called as follows:
+
+ 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.
+
+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
+ );
+
+could be used in a case where the command C<gen> creates two files, both
+F<foo.h> and F<foo.c>.
+
+-->
+
+ <para>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &Command; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
--- /dev/null
+<!--
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &Install; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
--- /dev/null
+<!--
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &InstallAs; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
-->
- <para>
+ <section>
+ <title>Linking With a Library</title>
+
+ <programlisting>
+ env = Environment(CC = 'gcc',
+ LIBS = 'world')
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ gcc -c hello.c -o hello.o
+ gcc -c world.c -o world.o
+ gcc -o hello hello.o -lworld
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Creating a Library</title>
+
+ <programlisting>
+ env = Environment(CC = 'gcc',
+ LIBS = 'world')
+ env.Program('hello.c')
+ env.Library('world.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ gcc -c hello.c -o hello.o
+ gcc -c world.c -o world.o
+ ar r libworld.a world.o
+ ar: creating libworld.a
+ ranlib libworld.a
+ gcc -o hello hello.o libworld.a
+ </literallayout>
+
+ </section>
+
+<!--
+
+A key simplification of Cons is the idea of a B<construction environment>. A
+construction environment is an B<object> characterized by a set of key/value
+pairs and a set of B<methods>. In order to tell Cons how to build something,
+you invoke the appropriate method via an appropriate construction
+environment. Consider the following example:
- X
- </para>
+
+ $env = new cons(
+ CC => 'gcc',
+ LIBS => 'libworld.a'
+ );
+
+ Program $env 'hello', 'hello.c';
+
+In this case, rather than using the default construction environment, as is,
+we have overridden the value of C<CC> so that the GNU C Compiler equivalent
+is used, instead. Since this version of B<Hello, World!> requires a library,
+F<libworld.a>, we have specified that any program linked in this environment
+should be linked with that library. If the library exists already, well and
+good, but if not, then we'll also have to include the statement:
+
+
+
+ Library $env 'libworld', 'world.c';
+
+Now if you type C<cons hello>, the library will be built before the program
+is linked, and, of course, C<gcc> will be used to compile both modules:
+
+
+
+ % cons hello
+
+-->
<section>
<title>The &Library; Builder</title>
--- /dev/null
+<!--
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &PCH; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
--- /dev/null
+<!--
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &PDF; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
--- /dev/null
+<!--
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &PostScript; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
--- /dev/null
+<!--
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &RES; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
--- /dev/null
+<!--
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &SharedLibrary; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
--- /dev/null
+<!--
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &SharedObject; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
--- /dev/null
+<!--
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &StaticLibrary; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
--- /dev/null
+<!--
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>The &StaticObject; Method</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
--- /dev/null
+<!--
+
+ 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.
+
+-->
+
+<blockquote>
+ <para>
+
+ SCons User's Guide Copyright (c) 2003 Steven Knight
+
+ </para>
+</blockquote>
</para>
- <section>
- <title>Command-Line Options</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
-
- <section>
- <title>Default Builders</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
-
<section>
<title>X</title>
--- /dev/null
+<!--
+
+ 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.
+
+-->
+
+<!doctype book PUBLIC "-//OASIS//DTD DocBook V4.1//EN"
+[
+
+ <!ENTITY % version SYSTEM "../version.sgml">
+ %version;
+
+ <!ENTITY % scons SYSTEM "../scons.mod">
+ %scons;
+
+ <!-- Builders -->
+ <!ENTITY Alias_file SYSTEM "Alias.sgml">
+ <!ENTITY CFile_file SYSTEM "CFile.sgml">
+ <!ENTITY CXXFile_file SYSTEM "CXXFile.sgml">
+ <!ENTITY Command_file SYSTEM "Command.sgml">
+ <!ENTITY Install_file SYSTEM "Install.sgml">
+ <!ENTITY InstallAs_file SYSTEM "InstallAs.sgml">
+ <!ENTITY Library_file SYSTEM "Library.sgml">
+ <!ENTITY Object_file SYSTEM "Object.sgml">
+ <!ENTITY PCH_file SYSTEM "PCH.sgml">
+ <!ENTITY PDF_file SYSTEM "PDF.sgml">
+ <!ENTITY PostScript_file SYSTEM "PostScript.sgml">
+ <!ENTITY Program_file SYSTEM "Program.sgml">
+ <!ENTITY RES_file SYSTEM "RES.sgml">
+ <!ENTITY SharedLibrary_file SYSTEM "SharedLibrary.sgml">
+ <!ENTITY SharedObject_file SYSTEM "SharedObject.sgml">
+ <!ENTITY StaticLibrary_file SYSTEM "StaticLibrary.sgml">
+ <!ENTITY StaticObject_file SYSTEM "StaticObject.sgml">
+
+ <!-- Construction Variables -->
+
+ <!ENTITY copyright SYSTEM "copyright.sgml">
+ <!ENTITY errors SYSTEM "errors.sgml">
+ <!ENTITY preface SYSTEM "preface.sgml">
+
+]>
+
+<book>
+ <bookinfo>
+ <title>SCons Reference Manual &buildversion;</title>
+
+ <author>
+ <firstname>Steven</firstname>
+ <surname>Knight</surname>
+ </author>
+
+ <edition>Revision &buildrevision; (&builddate;)</edition>
+
+ <pubdate>2003</pubdate>
+
+ <copyright>
+ <year>2003</year>
+ <holder>Steven Knight</holder>
+ </copyright>
+
+ <legalnotice>
+ ©right;
+ </legalnotice>
+
+ <releaseinfo>version &buildversion;</releaseinfo>
+
+ </bookinfo>
+
+ <chapter id="chap-preface">
+ <title>Preface</title>
+ &preface;
+ </chapter>
+
+ <chapter id="chap-builders">
+ <title>Builder Reference</title>
+
+ <section id="sect-Alias">
+ <title>The Alias Builder</title>
+ &Alias_file;
+ </section>
+
+ <section id="sect-CFile">
+ <title>The CFile Builder</title>
+ &CFile_file;
+ </section>
+
+ <section id="sect-Command">
+ <title>The Command Builder</title>
+ &Command_file;
+ </section>
+
+ <section id="sect-CXXFile">
+ <title>The CXXFile Builder</title>
+ &CXXFile_file;
+ </section>
+
+ <section id="sect-Install">
+ <title>The Install Builder</title>
+ &Install_file;
+ </section>
+
+ <section id="sect-InstallAs">
+ <title>The InstallAs Builder</title>
+ &InstallAs_file;
+ </section>
+
+ <section id="sect-Library">
+ <title>The Library Builder</title>
+ &Library_file;
+ </section>
+
+ <section id="sect-Object">
+ <title>The Object Builder</title>
+ &Object_file;
+ </section>
+
+ <section id="sect-PCH">
+ <title>The PCH Builder</title>
+ &PCH_file;
+ </section>
+
+ <section id="sect-PDF">
+ <title>The PDF Builder</title>
+ &PDF_file;
+ </section>
+
+ <section id="sect-PostScript">
+ <title>The PDF Builder</title>
+ &PostScript_file;
+ </section>
+
+ <section id="sect-Program">
+ <title>The Program Builder</title>
+ &Program_file;
+ </section>
+
+ <section id="sect-RES">
+ <title>The RES Builder</title>
+ &RES_file;
+ </section>
+
+ <section id="sect-SharedLibrary">
+ <title>The SharedLibrary Builder</title>
+ &SharedLibrary_file;
+ </section>
+
+ <section id="sect-SharedObject">
+ <title>The SharedObject Builder</title>
+ &SharedObject_file;
+ </section>
+
+ <section id="sect-StaticLibrary">
+ <title>The StaticLibrary Builder</title>
+ &StaticLibrary_file;
+ </section>
+
+ <section id="sect-StaticObject">
+ <title>The StaticObject Builder</title>
+ &StaticObject_file;
+ </section>
+
+ </chapter>
+
+ <chapter id="chap-variables">
+ <title>&ConsVar; Reference</title>
+
+ <section id="sect-AR">
+ <title>AR</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
+
+ </chapter>
+
+ <appendix id="chap-errors">
+ <title>Errors Generated by &SCons;</title>
+ &errors;
+ </appendix>
+
+</book>
--- /dev/null
+<!--
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>Why &SCons;?</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>History</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Conventions</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Acknowledgements</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Contact</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
<!ENTITY Autoconf "<application>Autoconf</application>">
<!ENTITY Cons "<application>Cons</application>">
+<!ENTITY gcc "<application>gcc</application>">
<!ENTITY Make "<application>Make</application>">
<!ENTITY Makepp "<application>Make++</application>">
<!ENTITY SCons "<application>SCons</application>">
<!ENTITY Alias "<function>Alias</function>">
<!ENTITY Aliases "<function>Aliases</function>">
+<!ENTITY Append "<function>Append</function>">
<!ENTITY Build "<function>Build</function>">
-<!ENTITY Cache "<function>Cache</function>">
+<!ENTITY CacheDir "<function>CacheDir</function>">
<!ENTITY Clean "<function>Clean</function>">
<!ENTITY Clone "<function>Clone</function>">
<!ENTITY Command "<function>Command</function>">
<!ENTITY Split "<function>Split</function>">
<!ENTITY Task "<function>Task</function>">
+<!-- Obsolete, but referenced in old documents. -->
+<!ENTITY Cache "<function>Cache</function>">
+
<!--
-->
+<!ENTITY CC "<varname>CC</varname>">
<!ENTITY CCFLAGS "<varname>CCFLAGS</varname>">
<!ENTITY LIBPATH "<varname>LIBPATH</varname>">
<!ENTITY PYTHONPATH "<varname>PYTHONPATH</varname>">
-->
-<!ENTITY Object "<function>Object</function>">
+<!ENTITY BuildDir "<function>BuildDir</function>">
+<!ENTITY CFile "<function>CFile</function>">
+<!ENTITY CXXFile "<function>CXXFile</function>">
<!ENTITY Library "<function>Library</function>">
-<!ENTITY SharedLibrary "<function>SharedLibrary</function>">
+<!ENTITY Object "<function>Object</function>">
+<!ENTITY PCH "<function>PCH</function>">
+<!ENTITY PDF "<function>PDF</function>">
+<!ENTITY PostScript "<function>PostScript</function>">
<!ENTITY Program "<function>Program</function>">
+<!ENTITY RES "<function>RES</function>">
+<!ENTITY SharedLibrary "<function>SharedLibrary</function>">
+<!ENTITY SharedObject "<function>SharedObject</function>">
+<!ENTITY StaticLibrary "<function>StaticLibrary</function>">
+<!ENTITY StaticObject "<function>StaticObject</function>">
+
+<!-- Obsolete, but referenced in old documents. -->
<!ENTITY MakeBuilder "<function>Make</function>">
-<!ENTITY BuildDir "<function>BuildDir</function>">
-->
-<!--
+ <para>
--->
+ We've already seen how you can use the &Alias;
+ function to create a target named <literal>install</literal>:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Install('/usr/bin', hello)
+ env.Alias('install', '/usr/bin')
+ </programlisting>
+
+ <para>
+
+ You can then use this alias on the command line
+ to tell &SCons; more naturally that you want to install files:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons install</userinput>
+ Install file: "hello" as "/usr/bin/hello"
+ </literallayout>
- <para>
+ <para>
- X
+ Like other &Builder; methods, though,
+ the &Alias; method returns an object
+ representing the alias being built.
+ You can then use this object as input to anothother &Builder;.
+ This is especially useful if you use such an object
+ as input to another call to the &Alias; &Builder;,
+ allowing you to create a hierarchy
+ of nested aliases:
- </para>
+ </para>
- <section>
- <title>Alias Targets</title>
+ <programlisting>
+ env = Environment()
+ p = env.Program('hello.c')
+ l = env.Library('hello.c')
+ env.Install('/usr/bin', p)
+ env.Install('/usr/lib', l)
+ ib = env.Alias('install-bin', '/usr/bin')
+ il = env.Alias('install-lib', '/usr/lib')
+ env.Alias('install', [ib, il])
+ </programlisting>
- <para>
+ <para>
- X
+ This example defines separate <literal>install</literal>,
+ <literal>install-bin</literal>,
+ and <literal>install-lib</literal> aliases,
+ allowing you finer control over what gets installed:
- </para>
+ </para>
- </section>
+ <literallayout>
+ % <userinput>scons install-bin</userinput>
+ Install file: "hello" as "/usr/bin/hello"
+ % <userinput>scons install-lib</userinput>
+ Install file: "libhello.a" as "/usr/lib/libhello.a"
+ % <userinput>scons -c /</userinput>
+ % <userinput>scons install</userinput>
+ Install file: "hello" as "/usr/bin/hello"
+ Install file: "libhello.a" as "/usr/lib/libhello.a"
+ </literallayout>
-->
- <para>
+ <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.
+
+ </para>
+
+ <section>
+ <title>Builders That Execute External Commands</title>
+
+ <para>
+
+ The simplest &Builder; to create is
+ one that executes an external command.
+ For example, if we want to build
+ an output file by running the contents
+ of the input file through a command named
+ <literal>foobuild</literal>,
+ creating that &Builder; might look like:
+
+ </para>
+
+ <programlisting>
+ bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Attaching a Builder to a &ConsEnv;</title>
+
+ <para>
+
+ A &Builder; object by itself, though,
+ 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.
+ For example, if we want to call the
+ &Builder; we defined by the name
+ <function>Foo</function>,
+ our &SConstruct; file might look like:
+
+ </para>
+
+ <programlisting>
+ bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file.foo', 'file.input')
+ </programlisting>
+
+ <para>
+
+ Then when we run &SCons; it looks like:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ foobuild < file.input > file.foo
+ </literallayout>
+
+ <para>
+
+ Note, however, that the default &BUILDERS;
+ variable in a &consenv;
+ comes with a default set of &Builder; objects
+ already defined:
+ &Program;, &Library;, etc.
+ And when we explicitly set the &BUILDERS; variable
+ when we create the &consenv;,
+ the default &Builder;s are no longer part of
+ the environment:
+
+ </para>
+
+ <programlisting>
+ bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ other errors
+ Traceback (most recent call last):
+ File "/usr/lib/scons/SCons/Script/__init__.py", line 901, in main
+ _main()
+ File "/usr/lib/scons/SCons/Script/__init__.py", line 762, in _main
+ SCons.Script.SConscript.SConscript(script)
+ File "/usr/lib/scons/SCons/Script/SConscript.py", line 207, in SConscript
+ exec _file_ in stack[-1].globals
+ File "SConstruct", line 4, in ?
+ env.Program('hello.c')
+ scons: Environment instance has no attribute 'Program'
+ </literallayout>
+
+ <para>
+
+ To be able use both our own defined &Builder; objects
+ and the default &Builder; objects in the same &consenv;,
+ you can either add to the &BUILDERS; variable
+ using the &Append; function:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
+ env.Append(BUILDERS = {'Foo' : bld})
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </programlisting>
+
+ <para>
+
+ Or you can explicitly set the appropriately-named
+ key in the &BUILDERS; dictionary:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
+ env['BUILDERS']['Foo'] = bld
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </programlisting>
+
+ <para>
+
+ Either way, the same &consenv;
+ can then use both the newly-defined
+ <function>Foo</function> &Builder;
+ and the default &Program; &Builder;:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ foobuild < file.input > file.foo
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Letting &SCons; Handle The File Suffixes</title>
+
+ <para>
+
+ By supplying additional information
+ when you create a &Builder;,
+ you can let &SCons; add appropriate file
+ suffixes to the target and/or the source file.
+ For example, rather than having to specify
+ explicitly that you want the <literal>Foo</literal>
+ &Builder; to build the <literal>file.foo</literal>
+ target file from the <literal>file.input</literal> source file,
+ you can give the <literal>.foo</literal>
+ and <literal>.input</literal> suffixes to the &Builder;,
+ making for more compact and readable calls to
+ the <literal>Foo</literal> &Builder;:
+
+ </para>
+
+ <programlisting>
+ bld = Builder(action = 'foobuild < $TARGET > $SOURCE',
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file1')
+ env.Foo('file2')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ foobuild < file1.input > file1.foo
+ foobuild < file2.input > file2.foo
+ </literallayout>
+
+ <para>
+
+ You can also supply a <literal>prefix</literal> keyword argument
+ if it's appropriate to have &SCons; append a prefix
+ to the beginning of target file names.
+
+ </para>
+
+ </section>
- X
+ <section>
+ <title>Builders That Execute Python Functions</title>
- </para>
+ <para>
- <section>
- <title>Builders That Execute External Commands</title>
+ In &SCons;, you don't have to call an external command
+ to build a file.
+ You can, instead, define a Python function
+ that a &Builder; object can invoke
+ to build your target file (or files).
- <para>
+ </para>
- X
+ <programlisting>
+ def build_function(target, source, env):
+ # XXX
+ return None
+ </programlisting>
- </para>
+ <para>
- </section>
+ XXX explain the function
+ XXX define the arguments
- <section>
- <title>Builders That Execute Python Functions</title>
+ </para>
- <para>
+ <para>
- X
+ Once you've defined the Python function
+ that will build your target file,
+ defining a &Builder; object for it is as
+ simple as specifying the name of the function,
+ instead of an external command,
+ as the &Builder;'s
+ <literal>action</literal>
+ argument:
+
+ </para>
+
+ <programlisting>
+ def build_function(target, source, env):
+ # XXX
+ return None
+ bld = Builder(action = build_function,
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file')
+ </programlisting>
+
+ <para>
+
+ And notice that the output changes slightly,
+ reflecting the fact that a Python function,
+ not an external command,
+ is now called to build the target file:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ build_function("file.foo", "file.input")
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Builders That Generate Actions</title>
- </para>
+ <para>
- </section>
+ X
+
+ </para>
+
+ <programlisting>
+ def generate_actions(XXX):
+ return XXX
+ bld = Builder(generator = generate_actions,
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ <para>
+
+ Note that it's illegal to specify both an
+ <literal>action</literal>
+ and a
+ <literal>generator</literal>
+ for a &Builder;.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Builders That Modify the Target List</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ def modify_targets(XXX):
+ return XXX
+ bld = Builder(action = 'XXX',
+ suffix = '.foo',
+ src_suffix = '.input',
+ emitter = modify_targets)
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ <programlisting>
+ bld = Builder(action = 'XXX',
+ suffix = '.foo',
+ src_suffix = '.input',
+ emitter = 'MY_EMITTER')
+ def modify1(XXX):
+ return XXX
+ def modify2(XXX):
+ return XXX
+ env1 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify1)
+ env2 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify2)
+ env1.Foo('file1')
+ env2.Foo('file2')
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Builders That Use Other Builders</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.BitKeeper('XXX')
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ </section>
-->
-<!--
+ <para>
-=head2 The C<UseCache> method
+ On multi-developer software projects,
+ you can sometimes speed up every developer's builds a lot by
+ allowing them to share the derived files that they build.
+ &SCons; makes this easy, as well as reliable.
-The C<UseCache> method instructs Cons to maintain a cache of derived
-files, to be shared among separate build trees of the same project.
+ </para>
- UseCache("cache/<buildname>") || warn("cache directory not found");
+ <section>
+ <title>Specifying the Shared Cache Directory</title>
--->
+ <para>
+
+ To enable sharing of derived files,
+ use the &CacheDir; function
+ in any &SConscript; file:
+
+ </para>
+
+ <programlisting>
+ CacheDir('/usr/local/build_cache')
+ </programlisting>
+
+ <para>
+
+ Note that the directory you specify must already exist
+ and be readable and writable by all developers
+ who will be sharing derived files.
+ It should also be in some central location
+ that all builds will be able to access.
+ In environments where developers are using separate systems
+ (like individual workstations) for builds,
+ this directory would typically be
+ on a shared or NFS-mounted file system.
+
+ </para>
+
+ <para>
+
+ Here's what happens:
+ When a build has a &CacheDir; specified,
+ every time a file is built,
+ it is stored in the shared cache directory
+ along with its MD5 build signature.
+ On subsequent builds,
+ before an action is invoked to build a file,
+ &SCons; will check the shared cache directory
+ to see if a file with the exact same build
+ signature already exists.
+ If so, the derived file will not be built locally,
+ but will be copied into the local build directory
+ from the shared cache directory,
+ like so:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons -c</userinput>
+ % <userinput>scons</userinput>
+ Retrieved `hello.o' from cache
+ Retrieved `hello' from cache
+ %
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Keeping Build Output Consistent</title>
+
+ <para>
+
+ One potential drawback to using a shared cache
+ is that your build output can be inconsistent
+ from invocation to invocation,
+ because any given file may be rebuilt one time
+ and retrieved from the shared cache the next time.
+ This can make analyzing build output more difficult,
+ especially for automated scripts that
+ expect consistent output each time.
+
+ </para>
+
+ <para>
+
+ If, however, you use the <literal>--cache-show</literal> option,
+ &SCons; will print the command line that it
+ <emphasis>would</emphasis> have executed
+ to build the file,
+ even when it is retrieving the file from the shared cache.
+ This makes the build output consistent
+ every time the build is run:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons --cache-show</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ %
+ </literallayout>
+
+ <para>
+
+ The trade-off, of course, is that you no longer
+ know whether or not &SCons;
+ has retrieved a derived file from cache
+ or has rebuilt it locally.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Not Retrieving Files From a Shared Cache</title>
+
+ <para>
+
+ Retrieving an already-built file
+ from the shared cache
+ is usually a significant time-savings
+ over rebuilding the file,
+ but how much of a savings
+ (or even whether it saves time at all)
+ can depend a great deal on your
+ system or network configuration.
+ For example, retrieving cached files
+ from a busy server over a busy network
+ might end up being slower than
+ rebuilding the files locally.
+
+ </para>
+
+ <para>
+
+ In these cases, you can specify
+ the <literal>--cache-disable</literal>
+ command-line option to tell &SCons;
+ to not retrieve already-built files from the
+ shared cache directory:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ 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
+ % <userinput>scons -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons --cache-disable</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ %
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Populating a Shared Cache With Already-Built Files</title>
+
+ <para>
+
+ Sometimes, you may have one or more derived files
+ already built in your local build tree
+ that you wish to make available to other people doing builds.
+ For example, you may find it more effective to perform
+ integration builds with the cache disabled
+ (per the previous section)
+ and only populate the shared cache directory
+ with the built files after the integration build
+ has completed successfully.
+ This way, the cache will only get filled up
+ with derived files that are part of a complete, successful build
+ not with files that might be later overwritten
+ while you debug integration problems.
+
+ </para>
- <para>
+ <para>
- X
+ In this case, you can use the
+ the <literal>--cache-force</literal> option
+ to tell &SCons; to put all derived files in the cache,
+ even if the files had already been built
+ by a previous invocation:
- </para>
+ </para>
- <section>
- <title>The &Cache; Method</title>
+ <literallayout>
+ % <userinput>scons --cache-disable</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons --cache-disable</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons --cache-force</userinput>
+ % <userinput>scons -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons</userinput>
+ Retrieved `hello.o' from cache
+ Retrieved `hello' from cache
+ %
+ </literallayout>
- <para>
+ <para>
- X
+ Notice how the above sample run
+ demonstrates that the <literal>--cache-disable</literal>
+ option avoids putting the built
+ <filename>hello.o</filename>
+ and
+ <filename>hello</filename> files in the cache,
+ but after using the <literal>--cache-force</literal> option,
+ the files have been put in the cache
+ for the next invocation to retrieve.
- </para>
+ </para>
- </section>
+ </section>
=head2 The C<Command> method
-The C<Command> method is a catchall method which can be used to arrange for
-any build action to be executed to update the target. For this command, a
-target file and list of inputs is provided. In addition, a build action
-is specified as the last argument. The build action is typically a
-command line or lines, but may also contain Perl code to be executed;
-see the section above on build actions for details.
The C<Command> method is called as follows:
-->
- <para>
-
- X
-
- </para>
-
- <section>
- <title>The &Command; Method</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
+ <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
+ 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).
+ For these situations, &SCons; supports a
+ &Command; &Builder; that arranges
+ for a specific action to be executed
+ to build a specific file or files.
+ This looks a lot like the other builders
+ (like &Program;, &Object;, etc.),
+ but takes as an additional argument
+ the command to be executed to build the file:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $TARGET > $SOURCE")
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons .</userinput>
+ sed 's/x/y' < foo.in > foo.out
+ </literallayout>
+
+ <para>
+
+ This is often more convenient than
+ creating a &Builder; object
+ and adding it to the &BUILDERS; variable
+ of a &consenv;
+
+ </para>
+
+ <para>
+
+ Note that the action you
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ def build(target, source, env)
+ XXX
+ return None
+ env.Command('foo.out', 'foo.in', build)
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons .</userinput>
+ build("foo.out", "foo.in")
+ </literallayout>
explicitly specify one or more targets
on the command line.
Sometimes, however, you may want
- to explicitly specify that only
- certain programs should be built by default,
- which you do using the &Default; function:
+ to specify explicitly that only
+ certain programs should be built by default.
+ You do this with the &Default; function:
</para>
<para>
- This &SConstruct; file builds two programs,
+ This &SConstruct; file knows how to build two programs,
&hello; and &goodbye;,
but only builds the
&hello program by default:
<application>prog1</application>
and
<application>prog3</application>
- programs:
+ programs by default:
</para>
-->
- <para>
-
- So far we've seen how &SCons; handles one-time builds.
- But the real point of a build tool like &SCons;
- is to rebuild the necessary things when source files change.
- The other side of rebuilding all the necessary things
- is that &SCons; should <emphasis>not</emphasis>
- unnecessarily rebuild things that have already
- been built.
- You can see this at work simply be re-invoking &SCons;
- after building our simple &hello; example:
-
- </para>
-
- <literallayout>
- % <userinput>scons</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- % <userinput>scons</userinput>
- %
- </literallayout>
-
- <para>
-
- &SCons; has remembered that the &hello; program
- is up-to-date with respect to the current &hello_c; source file,
- and avoids rebuilding it.
- You can see this more clearly by naming
- the &hello; program explicitly on the command line:
-
- </para>
-
- <literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- % <userinput>scons hello</userinput>
- scons: `hello' is up to date.
- %
- </literallayout>
-
- <para>
-
- Note that &SCons; only reports "...is up to date"
- for target files named explicitly on the command line,
- to avoid cluttering the output.
-
- </para>
-
- <section>
- <title>MD5 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:
-
- </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 saves time by avoiding unnecessary rebuilds when,
- for example, someone rewrites the
- contents of a file without making a change.
- But if the contents of the file 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>
-
- X
-
- </para>
-
- </section>
+ <para>
+
+ So far we've seen how &SCons; handles one-time builds.
+ But the real point of a build tool like &SCons;
+ is to rebuild the necessary things,
+ and only the necessary thing, when source files change.
+ Put another way,
+ &SCons; should <emphasis>not</emphasis>
+ waste time rebuilding things that have already been built.
+ You can see this at work simply be re-invoking &SCons;
+ after building our simple &hello; example:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons</userinput>
+ %
+ </literallayout>
+
+ <para>
+
+ The second time it is executed,
+ &SCons; realizes that the &hello; program
+ is up-to-date with respect to the current &hello_c; source file,
+ and avoids rebuilding it.
+ You can see this more clearly by naming
+ the &hello; program explicitly on the command line:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons hello</userinput>
+ scons: `hello' is up to date.
+ %
+ </literallayout>
+
+ <para>
+
+ Note that &SCons; only reports "...is up to date"
+ for target files named explicitly on the command line,
+ to avoid cluttering the output.
+
+ </para>
+
+ <section>
+ <title>MD5 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:
+
+ </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 saves time by avoiding unnecessary rebuilds when,
+ for example, someone rewrites the
+ contents of a file without making a change.
+ But if the contents of the file 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>
+
+ X
+
+ </para>
+
+ </section>
+
+ <!--
+
+ Now it turns out that F<hello.c> also includes the interface definition
+ file, F<world.h>:
+
+ How does Cons know that F<hello.c> includes F<world.h>, and that F<hello.o>
+ must therefore be recompiled? For now, suffice it to say that when
+ considering whether or not F<hello.o> is up-to-date, Cons invokes a scanner
+ for its dependency, F<hello.c>. This scanner enumerates the files included
+ by F<hello.c> to come up with a list of further dependencies, beyond those
+ made explicit by the Cons script. This process is recursive: any files
+ included by included files will also be scanned.
-<!--
-
-Now it turns out that F<hello.c> also includes the interface definition
-file, F<world.h>:
-
-How does Cons know that F<hello.c> includes F<world.h>, and that F<hello.o>
-must therefore be recompiled? For now, suffice it to say that when
-considering whether or not F<hello.o> is up-to-date, Cons invokes a scanner
-for its dependency, F<hello.c>. This scanner enumerates the files included
-by F<hello.c> to come up with a list of further dependencies, beyond those
-made explicit by the Cons script. This process is recursive: any files
-included by included files will also be scanned.
-
--->
-
- <section>
- <title>Implicit Dependencies</title>
+ -->
- <para>
+ <section>
+ <title>Implicit Dependencies</title>
+
+ <para>
+
+ Now suppose that our "Hello, World!" program
+ actually has a <literal>#include</literal> line
+ to include &hello_h; file in the compilation:
+
+ </para>
+
+ <programlisting>
+ #include "hello.h"
+ int
+ main()
+ {
+ printf("Hello, %s!\n", string);
+ }
+ </programlisting>
+
+ <para>
+
+ And, for completeness, the &hello_h; file looks like this:
+
+ </para>
+
+ <programlisting>
+ #define string "world"
+ </programlisting>
+
+ <para>
+
+ In this case, we want &SCons; to recognize that,
+ if the contents of the &hello_h; file change,
+ the &hello; program must be recompiled.
+ To do this, we need to modify the
+ &SConstruct; file like so:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CPPPATH = '.') XXX IS CPPPATH NECESSARY?
+ hello = env.Program('hello.c')
+ </programlisting>
+
+ <para>
+
+ The &CPPPATH; assignment in the &Environment; call
+ tells &SCons; to look in the current directory
+ (<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:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons hello</userinput>
+ cc -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 -o hello hello.o
+ %
+ </literallayout>
+
+ <para>
+
+ &SCons; knows that the &hello;
+ program must be rebuilt
+ because it scans the contents of
+ the &hello_c; file
+ for the <literal>#include</literal> lines that indicate
+ another file is being included in the compilation.
+ &SCons; records these as
+ <emphasis>implicit dependencies</emphasis>
+ of the target file,
+ Consequently,
+ when the &hello_h; file changes,
+ &SCons; realizes that the &hello_c; file includes it,
+ and rebuilds the resulting &hello; program
+ that depends on both the &hello_c; and &hello_h; files.
+
+ </para>
+
+ <para>
+
+ X
+
+ <!--
+ Isn't this expensive? The answer is, it depends. If you do a full build of a
+ large system, the scanning time is insignificant. If you do a rebuild of a
+ large system, then Cons will spend a fair amount of time thinking about it
+ before it decides that nothing has to be done (although not necessarily more
+ time than make!). The good news is that Cons makes it very easy to
+ intelligently subset your build, when you are working on localized changes.
+ -->
- Now suppose that our "Hello, World!" program
- actually looks like this:
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &Ignore; Method</title>
+
+ <para>
+
+ Sometimes it makes sense
+ to not rebuild a program,
+ even if a dependency file changes.
+ In this case,
+ you would tell &SCons; specifically
+ to ignore a dependency as follows:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Ignore(hello, 'hello.h')
+ </programlisting>
- </para>
+ <!-- XXX mention that you can use arrays for target and source? -->
- <programlisting>
- #include "hello.h"
- int
- main()
- {
- printf("Hello, %s!\n", string);
- }
- </programlisting>
+ <literallayout>
+ % <userinput>scons hello</userinput>
+ cc -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>
+ scons: `hello' is up to date.
+ </literallayout>
- <para>
+ <para>
- That is, the first line
- includes a &hello_h;
- that looks like this:
+ Now, the above example is a little contrived,
+ because it's hard to imagine a real-world situation
+ where you wouldn't to rebuild &hello;
+ if the &hello_h; file changed.
+ A more realistic example
+ might be if the &hello;
+ program is being built in a
+ directory that is shared between multiple systems
+ that have different copies of the
+ &stdio_h; include file.
+ In that case,
+ &SCons; would notice the differences between
+ the different systems' copies of &stdio_h;
+ and would rebuild &hello;
+ each time you change systems.
+ You could avoid these rebuilds as follows:
- </para>
+ </para>
- <programlisting>
- #define string "world"
- </programlisting>
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Ignore(hello, '/usr/include/stdio.h')
+ </programlisting>
- <para>
+ </section>
- In this case, we want &SCons; to recognize that,
- if the contents of the &hello_h; file change,
- the &hello; program must be recompiled.
- To do this, we need to modify the
- &SConstruct; file like so:
+ <section>
+ <title>The &Depends; Method</title>
- </para>
+ <para>
- <programlisting>
- env = Environment(CPPPATH = '.') XXX IS CPPPATH NECESSARY?
- hello = env.Program('hello.c')
- </programlisting>
+ On the other hand,
+ sometimes a file depends on another
+ file that the scanner(s) in &SCons; will not detect.
+ For this situation,
+ &SCons; allows you to specific that one file explicitly
+ depends on another file,
+ and must be rebuilt whenever that file changes,
+ using the &Depends; method:
- <para>
+ </para>
- The &CPPPATH; assignment in the &Environment; call
- tells &SCons; to look in the current directory
- (<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:
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Depends(hello, 'other_file')
+ </programlisting>
- </para>
+ <!-- XXX mention that you can use arrays for target and source? -->
- <literallayout>
- % <userinput>scons hello</userinput>
- cc -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 -o hello hello.o
- %
- </literallayout>
+ <literallayout>
+ % <userinput>scons hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons hello</userinput>
+ scons: `hello' is up to date.
+ % <userinput>edit other_file</userinput>
+ [CHANGE THE CONTENTS OF other_file]
+ % <userinput>scons hello</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ </literallayout>
- <para>
+ </section>
- &SCons; knows that the &hello;
- program must be rebuilt
- because it scans the contents of
- the &hello_c; file
- for the <literal>#include</literal> lines that indicate
- another file is being included in the compilation.
- &SCons; records these as
- <emphasis>implicit dependencies</emphasis>
- of the target file,
- Consequently,
- when the &hello_h; file changes,
- &SCons; realizes that the &hello_c; file includes it,
- and rebuilds the resulting &hello; program
- that depends on both the &hello_c; and &hello_h; files.
+ <!-->
- </para>
+ <section>
+ <title>The &Salt; Method</title>
- <para>
+ <para>
- X
+ X
-<!--
-Isn't this expensive? The answer is, it depends. If you do a full build of a
-large system, the scanning time is insignificant. If you do a rebuild of a
-large system, then Cons will spend a fair amount of time thinking about it
-before it decides that nothing has to be done (although not necessarily more
-time than make!). The good news is that Cons makes it very easy to
-intelligently subset your build, when you are working on localized changes.
--->
+ </para>
- </para>
-
- </section>
-
- <section>
- <title>The &Ignore; Method</title>
-
- <para>
-
- Sometimes it makes sense
- to not rebuild a program,
- even if a dependency file changes.
- In this case,
- you would tell &SCons; specifically
- to ignore a dependency as follows:
-
- </para>
-
- <programlisting>
- env = Environment()
- hello = env.Program('hello.c')
- env.Ignore(hello, 'hello.h')
- </programlisting>
-
- <!-- XXX mention that you can use arrays for target and source? -->
-
- <literallayout>
- % <userinput>scons hello</userinput>
- cc -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>
- scons: `hello' is up to date.
- </literallayout>
-
- <para>
-
- Now, the above example is a little contrived,
- because it's hard to imagine a real-world situation
- where you wouldn't to rebuild &hello;
- if the &hello_h; file changed.
- A more realistic example
- might be if the &hello;
- program is being built in a
- directory that is shared between multiple systems
- that have different copies of the
- &stdio_h; include file.
- In that case,
- &SCons; would notice the differences between
- the different systems' copies of &stdio_h;
- and would rebuild &hello;
- each time you change systems.
- You could avoid these rebuilds as follows:
-
- </para>
-
- <programlisting>
- env = Environment()
- hello = env.Program('hello.c')
- env.Ignore(hello, '/usr/include/stdio.h')
- </programlisting>
-
- </section>
-
- <section>
- <title>The &Depends; Method</title>
-
- <para>
-
- On the other hand,
- sometimes a file depends on another
- file that the scanner(s) in &SCons; will not detect.
- For this situation,
- &SCons; allows you to specific that one file explicitly
- depends on another file,
- and must be rebuilt whenever that file changes,
- using the &Depends; method:
-
- </para>
-
- <programlisting>
- env = Environment()
- hello = env.Program('hello.c')
- env.Depends(hello, 'other_file')
- </programlisting>
-
- <!-- XXX mention that you can use arrays for target and source? -->
-
- <literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- % <userinput>scons hello</userinput>
- scons: `hello' is up to date.
- % <userinput>edit other_file</userinput>
- [CHANGE THE CONTENTS OF other_file]
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- </literallayout>
-
- </section>
-
- <!-->
-
- <section>
- <title>The &Salt; Method</title>
-
- <para>
-
- X
-
- </para>
-
- </section>
+ </section>
- -->
+ -->
- <section>
- <title>Time Stamps</title>
+ <section>
+ <title>Time Stamps</title>
- <para>
+ <para>
- X
+ X
- </para>
+ </para>
- </section>
+ </section>
- <section>
- <title>The &SourceSignature; Method</title>
+ <section>
+ <title>The &SourceSignature; Method</title>
- <para>
+ <para>
- X
+ X
- </para>
+ </para>
- </section>
+ </section>
<!--
-=head2 Construction environments
-
-A key simplification of Cons is the idea of a B<construction environment>. A
-construction environment is an B<object> characterized by a set of key/value
-pairs and a set of B<methods>. In order to tell Cons how to build something,
-you invoke the appropriate method via an appropriate construction
-environment. Consider the following example:
-
-
-
- $env = new cons(
- CC => 'gcc',
- LIBS => 'libworld.a'
- );
-
- Program $env 'hello', 'hello.c';
-
-In this case, rather than using the default construction environment, as is,
-we have overridden the value of C<CC> so that the GNU C Compiler equivalent
-is used, instead. Since this version of B<Hello, World!> requires a library,
-F<libworld.a>, we have specified that any program linked in this environment
-should be linked with that library. If the library exists already, well and
-good, but if not, then we'll also have to include the statement:
-
-
-
- Library $env 'libworld', 'world.c';
-
-Now if you type C<cons hello>, the library will be built before the program
-is linked, and, of course, C<gcc> will be used to compile both modules:
-
-
-
- % cons hello
- gcc -c hello.c -o hello.o
- gcc -c world.c -o world.o
- ar r libworld.a world.o
- ar: creating libworld.a
- ranlib libworld.a
- gcc -o hello hello.o libworld.a
-
=head1 More on construction environments
As previously mentioned, a B<construction environment> is an object that
=back
+XXX
+
+DESCRIBE THE Literal() FUNCTION, TOO
+
+XXX
+
=head2 Expanding construction variables in file names
Cons expands construction variables in the source and target file names
This will leave anything else that might be in the default execution
environment undisturbed.
+-->
+
+ <para>
+ It is rare that all of the software in a large,
+ complicated system needs to be built the same way.
+ Different source files need different options
+ enabled on the command line;
+ different executable programs need to be linked
+ with different libraries (shared or static);
+ XXX
+ &SCons; accomodates these different build
+ requirements by allowing you to create and
+ configure multiple &consenvs;
+ that control how the software is built.
+ Technically, a &consenv; is an object
+ that has a number of associated
+ &consvars;, each with a name and a value.
+ (A &consenv; also has an attached
+ set of &Builder; methods,
+ about which we'll learn more later.)
-=head2 Overriding construction variables
+ </para>
-There are several ways of extending Cons, which vary in degree of
-difficulty. The simplest method is to define your own construction
-environment, based on the default environment, but modified to reflect your
-particular needs. This will often suffice for C-based applications. You can
-use the C<new> constructor, and the C<clone> and C<copy> methods to create
-hybrid environments. These changes can be entirely transparent to the
-underlying F<Conscript> files.
+ <para>
--->
+ A &consenv; is created by the &Environment;
+ method which you have already seen.
+ What you haven't seen, though,
+ is that when you initialize a &consenv;,
+ you can set the values of the
+ environment's &consvars;
+ to control how a program is built.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CC = 'gcc',
+ CCFLAGS = '-O2')
+
+ env.Program('foo.c')
+ </programlisting>
<para>
+
+ This example, rather than using the default,
+ explicitly specifies use of the
+ GNU C compiler &gcc;,
+ and further specifies that the <literal>-O2</literal>
+ (optimization level two)
+ flag should be used when compiling the object file.
+ So a run from this example would look like:
- X
+ </para>
-<!--
+ <literallayout>
+ % <userinput>scons</userinput>
+ gcc -c -O2 foo.c -o foo.o
+ gcc -o foo foo.o
+ </literallayout>
-A key simplification of Cons is the idea of a B<construction environment>. A
-construction environment is an B<object> characterized by a set of key/value
-pairs and a set of B<methods>. In order to tell Cons how to build something,
-you invoke the appropriate method via an appropriate construction
-environment. Consider the following example:
+ <section>
+ <title>Multiple &ConsEnvs;</title>
+ <para>
+ So far, we've always created a &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.
+ For example:
- $env = new cons(
- CC => 'gcc',
- LIBS => 'libworld.a'
- );
+ </para>
+
+ <programlisting>
+ my_env = Environment(CC = 'gcc',
+ CCFLAGS = '-O2')
- Program $env 'hello', 'hello.c';
+ my_env.Program('foo.c')
+ </programlisting>
-In this case, rather than using the default construction environment, as is,
-we have overridden the value of C<CC> so that the GNU C Compiler equivalent
-is used, instead. Since this version of B<Hello, World!> requires a library,
-F<libworld.a>, we have specified that any program linked in this environment
-should be linked with that library. If the library exists already, well and
-good, but if not, then we'll also have to include the statement:
+ <para>
+ This opens up the possibility of
+ using multiple &consenvs;,
+ each with a separate variable name.
+ We can then use these separate &consenvs;
+ to build different programs in different ways:
+ </para>
- Library $env 'libworld', 'world.c';
+ <programlisting>
+ opt = Environment(CCFLAGS = '-O2')
+ dbg = Environment(CCFLAGS = '-g')
-Now if you type C<cons hello>, the library will be built before the program
-is linked, and, of course, C<gcc> will be used to compile both modules:
+ opt.Program('foo', 'foo.c')
+ dbg.Program('bar', 'bar.c')
+ </programlisting>
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c -O2 bar.c -o bar.o
+ cc -o bar bar.o
+ cc -c -g foo.c -o foo.o
+ cc -o foo foo.o
+ </literallayout>
- % cons hello
- gcc -c hello.c -o hello.o
- gcc -c world.c -o world.o
- ar r libworld.a world.o
- ar: creating libworld.a
- ranlib libworld.a
- gcc -o hello hello.o libworld.a
+ <para>
--->
+ We can even use multiple &consenvs; to build
+ multiple versions of a single program.
+ If you do this by simply trying to use the
+ &Program; builder with both environments, though,
+ like this:
- </para>
+ </para>
- <programlisting>
- optimize = Environment(CCFLAGS = '-O2')
- debug = Environment(CCFLAGS = '-g')
+ <programlisting>
+ opt = Environment(CCFLAGS = '-O2')
+ dbg = Environment(CCFLAGS = '-g')
- o = optimize.Object('foo-opt', 'foo.c')
- optimize.Program(o)
+ opt.Program('foo', 'foo.c')
- d = debug.Object('foo-debug', 'foo.c')
- debug.Program(d)
- </programlisting>
+ dbg.Program('foo', 'foo.c')
+ </programlisting>
- <literallayout>
- % <userinput>scons .</userinput>
- cc -c -g foo.c -o foo-debug.o
- cc -o foo-debug foo-debug.o
- cc -c -O2 foo.c -o foo-opt.o
- cc -o foo-opt foo-opt.o
- </literallayout>
+ <para>
+
+ Then &SCons; generates the following error:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ scons: *** Two different environments were specified for the same target: foo.o
+ File "SConstruct", line 6, in ?
+ </literallayout>
+
+ <para>
+
+ This is because the two &Program; calls have
+ each implicitly told &SCons; to generate an object file named
+ <filename>foo.o</filename>,
+ one with a &CCFLAGS; value of
+ <literal>-O2</literal>
+ and one with a &CCFLAGS; value of
+ <literal>-g</literal>.
+ To work around this,
+ we must explicitly specify
+ that each environment compile
+ <filename>foo.c</filename>
+ to a separately-named object file
+ using the &Object; call, like so:
+
+ </para>
+
+ <programlisting>
+ opt = Environment(CCFLAGS = '-O2')
+ dbg = Environment(CCFLAGS = '-g')
+
+ o = opt.Object('foo-opt', 'foo.c')
+ opt.Program(o)
+
+ d = dbg.Object('foo-dbg', 'foo.c')
+ dbg.Program(d)
+ </programlisting>
+
+ <para>
+
+ Notice that each call to the &Object; builder
+ returns a value,
+ an internal &SCons; object that
+ represents the file that will be built.
+ We then use that object
+ as input to the &Program; builder.
+ This avoids having to specify explicitly
+ the object file name in multiple places,
+ and makes for a compact, readable
+ &SConstruct file.
+ Our &SCons; output then looks like:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c -g foo.c -o foo-dbg.o
+ cc -o foo-dbg foo-dbg.o
+ cc -c -O2 foo.c -o foo-opt.o
+ cc -o foo-opt foo-opt.o
+ </literallayout>
+
+ </section>
<section>
- <title>The &Environment; Constructor</title>
+ <title>Copying &ConsEnvs;</title>
<para>
- X
+ Sometimes you want to more than one &consenv;
+ to use 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
+ to create a copy of a &consenv;.
+ Like the &Environment; call that creates a &consenv;,
+ the &Copy; method takes &consvar; assignments,
+ which will override the values in the copied &consenv;.
+ For example, suppose we want to use &gcc;
+ to create three versions of a program,
+ one optimized, one debug, and one with neither.
+ We could do this by creating a "base" &consenv;
+ that sets &CC; to &gcc;,
+ and then creating two copies,
+ one which sets &CCFLAGS; for optimization
+ and the other with sets &CCFLAGS; for debugging:
+
+ </para>
+
+ <programlisting>
+ env = Environment(CC = 'gcc')
+ opt = env.Copy(CCFLAGS = '-O2')
+ dbg = env.Copy(CCFLAGS = '-g')
+
+ e = opt.Object('foo', 'foo.c')
+
+ o = opt.Object('foo-opt', 'foo.c')
+ opt.Program(o)
+
+ d = dbg.Object('foo-dbg', 'foo.c')
+ dbg.Program(d)
+ </programlisting>
+
+ <para>
+
+ Then our output would look like:
</para>
+ <literallayout>
+ % <userinput>scons</userinput>
+ gcc -c foo.c -o foo.o
+ gcc -o foo foo.o
+ gcc -c -g foo.c -o foo-dbg.o
+ gcc -o foo-dbg foo-dbg.o
+ gcc -c -O2 foo.c -o foo-opt.o
+ gcc -o foo-opt foo-opt.o
+ </literallayout>
+
</section>
<section>
- <title>The &Copy; Method</title>
+ <title>Fetching Values From a &ConsEnv;</title>
<para>
</para>
+ <programlisting>
+ env = Environment()
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Modifying a &ConsEnv;</title>
+
+ <section>
+ <title>Replacing Values in a &ConsEnv;</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Appending to the End of Values in a &ConsEnv;</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Appending to the Beginning of Values in a &ConsEnv;</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ </literallayout>
+
+ </section>
+
</section>
If there is no &Help; text in the &SConstruct; or
&SConscript; files,
&SCons; will revert to displaying its
- standard list and description of available command-line
+ standard list that describes the &SCons; command-line
options.
This list is also always displayed whenever
the <literal>-H</literal> option is used.
=head2 The Build command
-The C<Build> command takes a list of F<Conscript> file names, and arranges
-for them to be included in the build. For example:
-
- Build qw(
- drivers/display/Conscript
- drivers/mouse/Conscript
- parser/Conscript
- utilities/Conscript
- );
-
-This is a simple two-level hierarchy of build scripts: all the subsidiary
-F<Conscript> files are mentioned in the top-level F<Construct> file. Notice
-that not all directories in the tree necessarily have build scripts
-associated with them.
-
-This could also be written as a multi-level script. For example, the
-F<Construct> file might contain this command:
-
- Build qw(
- parser/Conscript
- drivers/Conscript
- utilities/Conscript
- );
-
-and the F<Conscript> file in the F<drivers> directory might contain this:
-
- Build qw(
- display/Conscript
- mouse/Conscript
- );
-
-Experience has shown that the former model is a little easier to understand,
-since the whole construction tree is laid out in front of you, at the
-top-level. Hybrid schemes are also possible. A separately maintained
-component that needs to be incorporated into a build tree, for example,
-might hook into the build tree in one place, but define its own construction
-hierarchy.
-
By default, Cons does not change its working directory to the directory
containing a subsidiary F<Conscript> file it is including. This behavior
can be enabled for a build by specifying, in the top-level F<Construct>
-->
- <para>
+ <para>
+
+ The source code for large software projects
+ rarely stays in a single directory,
+ but is nearly always divided into a
+ hierarchy of directories.
+ Organizing a large software build using &SCons;
+ involves creating a hierarchy of build scripts
+ using the &SConscript; function.
+
+ </para>
+
+ <section>
+ <title>&SConscript; Files</title>
+
+ <para>
+
+ As we've already seen,
+ the build script at the top of the tree is called &SConstruct;.
+ The top-level &SConstruct; file can
+ use the &SConscript; function to
+ include other subsidiary scripts in the build.
+ These subsidiary scripts can, in turn,
+ use the &SConscript; function
+ to include still other scripts in the build.
+ By convention, these subsidiary scripts are usually
+ named &SConscript;.
+ For example, a top-level &SConstruct; file might
+ arrange for four subsidiary scripts to be included
+ in the build as follows:
+
+ </para>
+
+ <programlisting>
+ SConscript(['drivers/display/SConscript',
+ 'drivers/mouse/SConscript',
+ 'parser/SConscript',
+ 'utilities/SConscript'])
+ </programlisting>
+
+ <para>
+
+ In this case, the &SConstruct; file
+ lists all of the &SConscript; files in the build explicitly.
+ (Note, however, that not every directory in the tree
+ necessarily has an &SConscript; file.)
+ Alternatively, the <literal>drivers</literal>
+ subdirectory might contain an intermediate
+ &SConscript; file,
+ in which case the &SConscript; call in
+ the top-level &SConstruct; file
+ would look like:
+
+ </para>
+
+ <programlisting>
+ SConscript(['drivers/SConscript',
+ 'parser/SConscript',
+ 'utilities/SConscript'])
+ </programlisting>
+
+ <para>
+
+ And the subsidiary &SConscript; file in the
+ <literal>drivers</literal> subdirectory
+ would look like:
+
+ </para>
+
+ <programlisting>
+ SConscript(['display/SConscript',
+ 'mouse/SConscript'])
+ </programlisting>
+
+ <para>
+
+ Whether you list all of the &SConscript; files in the
+ top-level &SConstruct; file,
+ or place a subsidiary &SConscript; file in
+ intervening directories,
+ or use some mix of the two schemes,
+ is up to you and the needs of your software.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Path Names Are Relative to the &SConscript; Directory</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ SConscript(['display/SConscript',
+ 'mouse/SConscript'])
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Sharing Environments (and Other Variables) Between &SConscript; Files</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ SConscript(['display/SConscript',
+ 'mouse/SConscript'])
+ </programlisting>
+
+ <section>
+ <title>Exporting Variables</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ SConscript(['display/SConscript',
+ 'mouse/SConscript'])
+ </programlisting>
+
+ </section>
+
+ <section>
+ <title>Importing Variables</title>
- X
+ <para>
- </para>
+ X
- <section>
- <title>&SConscript; Files</title>
+ </para>
- <para>
+ <programlisting>
+ SConscript(['display/SConscript',
+ 'mouse/SConscript'])
+ </programlisting>
- X
+ </section>
- </para>
+ <section>
+ <title>Returning Values</title>
- </section>
+ <para>
- <section>
- <title>X</title>
+ X
- <para>
+ </para>
- X
+ <programlisting>
+ SConscript(['display/SConscript',
+ 'mouse/SConscript'])
+ </programlisting>
- </para>
+ </section>
- </section>
+ </section>
-->
-<!--
-
-=head2 The C<Install> method
-
-The C<Install> method arranges for the specified files to be installed in
-the specified directory. The installation is optimized: the file is not
-copied if it can be linked. If this is not the desired behavior, you will
-need to use a different method to install the file. It is called as follows:
-
- Install $env <directory>, <names>;
-
-Note that, while the files to be installed may be arbitrarily named,
-only the last component of each name is used for the installed target
-name. So, for example, if you arrange to install F<foo/bar> in F<baz>,
-this will create a F<bar> file in the F<baz> directory (not F<foo/bar>).
-
-
-=head2 The C<InstallAs> method
+ <para>
+
+ Once a program is built,
+ it is often appropriate to install it in another
+ directory for public use.
+ You use the &Install; method
+ to arrange for a program, or any other file,
+ to be copied into a destination directory:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Install('/usr/bin', hello)
+ </programlisting>
+
+ <para>
+
+ Note, however, that installing a file is
+ still considered a type of file "build."
+ This is important when you remember that
+ the default behavior of &SCons; is
+ to build files in or below the current directory.
+ If, as in the example above,
+ you are installing files in a directory
+ outside of the top-level &SConstruct; file's directory tree,
+ you must specify that directory
+ (or a higher directory, such as <literal>/</literal>)
+ for it to install anything there:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ % <userinput>scons /usr/bin</userinput>
+ Install file: "hello" as "/usr/bin/hello"
+ </literallayout>
+
+ <para>
+
+ It can, however, be cumbersome to remember
+ (and type) the specific destination directory
+ in which the program (or any other file)
+ should be installed.
+ This is an area where the &Alias;
+ function comes in handy,
+ allowing you, if you wish,
+ to create a pseudo-target named <literal>install</literal>
+ that can expand to the specified destination directory:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.Install('/usr/bin', hello)
+ env.Alias('install', '/usr/bin')
+ </programlisting>
+
+ <para>
+
+ This then yields the more natural
+ ability to install the program
+ in its destination as follows:
+
+ </para>
-The C<InstallAs> method arranges for the specified source file(s) to be
-installed as the specified target file(s). Multiple files should be
-specified as a file list. The installation is optimized: the file is not
-copied if it can be linked. If this is not the desired behavior, you will
-need to use a different method to install the file. It is called as follows:
+ <literallayout>
+ % <userinput>scons install</userinput>
+ Install file: "hello" as "/usr/bin/hello"
+ </literallayout>
+
+ <section>
+ <title>Installing Multiple Files in a Directory</title>
+
+ <para>
+
+ You can install multiple files into a directory
+ simploy by calling the &Install; function multiple times:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ goodbye = env.Program('goodbye.c')
+ env.Install('/usr/bin', hello)
+ env.Install('/usr/bin', goodbye])
+ env.Alias('install', '/usr/bin')
+ </programlisting>
+
+ <para>
+
+ Or, more succinctly, listing the multiple input
+ files in a list
+ (just like you can do with any other builder):
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ goodbye = env.Program('goodbye.c')
+ env.Install('/usr/bin', [hello, goodbye])
+ env.Alias('install', '/usr/bin')
+ </programlisting>
+
+ <para>
+
+ Either of these two examples yields:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons install</userinput>
+ cc -c goodbye.c -o goodbye.o
+ cc -o goodbye goodbye.o
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ Install file: "goodbye" as "/usr/bin/goodbye"
+ Install file: "hello" as "/usr/bin/hello"
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Installing a File Under a Different Name</title>
-C<InstallAs> works in two ways:
+ <para>
+
+ The &Install; method preserves the name
+ of the file when it is copied into the
+ destination directory.
+ If you need to change the name of the file
+ when you copy it, use the &InstallAs; function:
-Single file install:
+ </para>
- InstallAs $env TgtFile, SrcFile;
-
-Multiple file install:
-
- InstallAs $env ['tgt1', 'tgt2'], ['src1', 'src2'];
-
-Or, even as:
-
- @srcs = qw(src1 src2 src3);
- @tgts = qw(tgt1 tgt2 tgt3);
- InstallAs $env [@tgts], [@srcs];
-
-Both the target and the sources lists should be of the same length.
-
--->
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ env.InstallAs('/usr/bin/hello-new', hello)
+ env.Alias('install', '/usr/bin')
+ </programlisting>
- <para>
+ <para>
- X
+ This installs the <literal>hello</literal>
+ program with the name <literal>hello-new</literal>
+ as follows:
- </para>
+ </para>
- <section>
- <title>The &Install; Builder</title>
+ <literallayout>
+ % <userinput>scons install</userinput>
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ Install file: "hello" as "/usr/bin/hello-new"
+ </literallayout>
- <para>
+ </section>
- X
+ <section>
+ <title>Installing Multiple Files Under Different Names</title>
- </para>
+ <para>
- </section>
+ Lastly, if you have multiple files that all
+ need to be installed with different file names,
+ you can either call the &InstallAs; function
+ multiple times, or as a shorthand,
+ you can supply same-length lists
+ for the both the target and source arguments:
- <section>
- <title>The &InstallAs; Method</title>
+ </para>
- <para>
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ goodbye = env.Program('goodbye.c')
+ env.InstallAs(['/usr/bin/hello-new',
+ '/usr/bin/goodbye-new',
+ [hello, goodbye])
+ </programlisting>
+
+ <para>
- X
+ In this case, the &InstallAs; function
+ loops through both lists simultaneously,
+ and copies each source file into its corresponding
+ target file name:
- </para>
+ </para>
+
+ <literallayout>
+ % <userinput>scons install</userinput>
+ cc -c goodbye.c -o goodbye.o
+ cc -o goodbye goodbye.o
+ cc -c hello.c -o hello.o
+ cc -o hello hello.o
+ Install file: "goodbye" as "/usr/bin/goodbye-new"
+ Install file: "hello" as "/usr/bin/hello-new"
+ </literallayout>
- </section>
+ </section>
<!ENTITY help SYSTEM "help.sgml">
<!ENTITY hierarchy SYSTEM "hierarchy.sgml">
<!ENTITY install SYSTEM "install.sgml">
- <!ENTITY library SYSTEM "library.sgml">
<!ENTITY make SYSTEM "make.sgml">
- <!ENTITY more SYSTEM "more.sgml">
- <!ENTITY object SYSTEM "object.sgml">
<!ENTITY precious SYSTEM "precious.sgml">
<!ENTITY preface SYSTEM "preface.sgml">
- <!ENTITY program SYSTEM "program.sgml">
- <!ENTITY reference SYSTEM "reference.sgml">
<!ENTITY repositories SYSTEM "repositories.sgml">
<!ENTITY run SYSTEM "run.sgml">
<!ENTITY scanners SYSTEM "scanners.sgml">
<!ENTITY separate SYSTEM "separate.sgml">
<!ENTITY simple SYSTEM "simple.sgml">
+ <!ENTITY sourcecode SYSTEM "sourcecode.sgml">
<!ENTITY troubleshoot SYSTEM "troubleshoot.sgml">
<!ENTITY variants SYSTEM "variants.sgml">
&depends;
</chapter>
-
-
<chapter id="chap-default">
<title>Default Targets</title>
&default;
&install;
</chapter>
- <chapter id="chap-program">
- <title>The Program Builder</title>
- &program;
- </chapter>
-
- <chapter id="chap-library">
- <title>The Library Builder</title>
- &library;
- </chapter>
-
- <chapter id="chap-more">
- <title>More Things to Do With Builds</title>
- &more;
- </chapter>
-
- <chapter id="chap-command">
- <title>The Command Builder</title>
- &command;
- </chapter>
-
- <chapter id="chap-object">
- <title>The Object Builder</title>
- &object;
- </chapter>
-
<chapter id="chap-precious">
<title>Preventing Removal of Targets</title>
&precious;
&builders;
</chapter>
+ <chapter id="chap-command">
+ <title>Avoiding Having to Write Builders</title>
+ &command;
+ </chapter>
+
<chapter id="chap-actions">
<title>SCons Actions</title>
&actions;
&repositories;
</chapter>
+ <chapter id="chap-sourcecode">
+ <title>Fetching Files From Source Code Management Systems</title>
+ &sourcecode;
+ </chapter>
+
<chapter id="chap-caching">
<title>Caching Built Files</title>
&caching;
</chapter>
- <chapter id="chap-run">
- <title>How to Run &SCons;</title>
- &run;
- </chapter>
-
<chapter id="chap-alias">
<title>Alias Targets</title>
&alias;
</chapter>
+ <chapter id="chap-run">
+ <title>How to Run &SCons;</title>
+ &run;
+ </chapter>
+
<chapter id="chap-troubleshooting">
<title>Troubleshooting</title>
&troubleshoot;
</chapter>
- <appendix id="app-quick">
- <title>Quick Reference</title>
- &reference;
- </appendix>
-
- <appendix id="app-errors">
- <title>Errors Generated by &SCons;</title>
- &errors;
- </appendix>
+ <!--
+ AddPostAction()
+ AddPreAction()
+ Clean()
+ Dir()
+ File()
+ FindFile()
+ GetJobs()
+ SetJobs()
+ SideEffect()
+ ParseConfig()
+ Platform()
+ Tools()
+ -->
<appendix id="app-example">
<title>Complex &SCons; Example</title>
<!--
-=head2 The C<Precious> method
-
-The C<Precious> method asks cons not to delete the specified file or
-list of files before building them again. It is invoked as:
-
- Precious <files>;
-
-This is especially useful for allowing incremental updates to libraries
-or debug information files which are updated rather than rebuilt anew each
-time. Cons will still delete the files when the C<-r> flag is specified.
-
=head2 The C<AfterBuild> method
The C<AfterBuild> method evaluates the specified perl string after
<para>
- X
+ By default, &SCons; removes targets before building them.
+ Sometimes, however, this is not what you want.
+ For example, you may want to update a library incrementally,
+ not by having it deleted and then rebuilt from all
+ of the constituent object files.
+ In such cases, you can use the
+ &Precious; method to prevent
+ &SCons; from removing the target before it is built:
</para>
- <section>
- <title>The &Precious; Method</title>
+ <programlisting>
+ env = Environment(XXX NEED LIBRARY FLAGS
+ LIBFLAGS = '-r')
+ lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ env.Precious(lib)
+ </programlisting>
- <para>
+ <para>
- X
+ XXX:
- </para>
+ </para>
- </section>
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX ANY INPUT HERE?
+ </literallayout>
+
+ <para>
+
+ &SCons; will still delete files marked as &Precious;
+ when the <literal>-c</literal> option is used.
+
+ </para>
-->
- <para>
+ <para>
+
+ Often, a software project will have
+ one or more central repositories,
+ directory trees that contain
+ source code, or derived files, or both.
+ You can eliminate additional unnecessary
+ rebuilds of files by having &SCons;
+ use files from one or more code repositories
+ to build files in your local build tree.
+
+ </para>
+
+ <section>
+ <title>The &Repository; Method</title>
+
+ <!--
+
+ The repository directories specified may contain source files, derived files
+ (objects, libraries and executables), or both. If there is no local file
+ (source or derived) under the directory in which Cons is executed, then the
+ first copy of a same-named file found under a repository directory will be
+ used to build any local derived files.
+
+ -->
+
+ <para>
+
+ It's often useful to allow multiple programmers working
+ on a project to build software from
+ source files and/or derived files that
+ are stored in a centrally-accessible repository,
+ a directory copy of the source code tree.
+ (Note that this is not the sort of repository
+ maintained by a source code management system
+ like BitKeeper, CVS, or Subversion.
+ For information about using &SCons;
+ with these systems, see the section,
+ "Fetching Files From Source Code Management Systems,"
+ below.)
+ You use the &Repository; method
+ to tell &SCons; to search one or more
+ central code repositories (in order)
+ for any source files and derived files
+ that are not present in the local build tree:
- Often, a software project will have
- one or more central repositories,
- directory trees that contain
- source code, or derived files, or both.
- You can eliminate additional unnecessary
- rebuilds of files by having &SCons;
- use files from one or more code repositories
- to build files in your local build tree.
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Program('hello.c')
+ Repository('/usr/repository1', '/usr/repository2')
+ </programlisting>
+
+ <para>
+
+ Multiple calls to the &Repository; method
+ will simply add repositories to the global list
+ that &SCons; maintains,
+ with the exception that &SCons; will automatically eliminate
+ the current directory and any non-existent
+ directories from the list.
- </para>
+ </para>
+
+ </section>
+
+ <section>
+ <title>Finding source files in repositories</title>
+
+ <para>
+
+ The above example
+ specifies that &SCons;
+ will first search for files under
+ the <filename>/usr/repository1</filename> tree
+ and next under the <filename>/usr/repository2</filename> tree.
+ &SCons; expects that any files it searches
+ for will be found in the same position
+ relative to the top-level directory XXX
+ In the above example, if the &hello_c; file is not
+ found in the local build tree,
+ &SCons; will search first for
+ a <filename>/usr/repository1/hello.c</filename> file
+ and then for a <filename>/usr/repository1/hello.c</filename> file
+ to use in its place.
+
+ </para>
+
+ <para>
- <section>
- <title>The &Repository; Method</title>
+ So given the &SConstruct; file above,
+ if the &hello_c; file exists in the local
+ build directory,
+ &SCons; will rebuild the &hello; program
+ as normal:
+
+ </para>
-<!--
-
-The repository directories specified may contain source files, derived files
-(objects, libraries and executables), or both. If there is no local file
-(source or derived) under the directory in which Cons is executed, then the
-first copy of a same-named file found under a repository directory will be
-used to build any local derived files.
-
--->
-
- <para>
-
- The &Repository; method
- tells &SCons; to search one or more
- central code repositories (in order)
- for any source files and derived files
- that are not present in the local build tree:
-
- </para>
-
- <programlisting>
- env = Environment()
- env.Program('hello.c')
- Repository('/usr/repository1', '/usr/repository2')
- </programlisting>
-
- <para>
-
- (Note that multiple calls to the &Repository; method
- will simply add repositories to the global list
- that &SCons; maintains,
- with the exception that &SCons; will automatically eliminate
- the current directory and any non-existent
- directories from the list.)
-
- </para>
-
- </section>
-
- <section>
- <title>Finding source files in repositories</title>
-
- <para>
-
- The above example
- specifies that &SCons;
- will first search for files under
- the <filename>/usr/repository1</filename> tree
- and next under the <filename>/usr/repository2</filename> tree.
- &SCons; expects that any files it searches
- for will be found in the same position
- relative to the top-level directory XXX
- In the above example, if the &hello_c; file is not
- found in the local build tree,
- &SCons; will search first for
- a <filename>/usr/repository1/hello.c</filename> file
- and then for a <filename>/usr/repository1/hello.c</filename> file
- to use in its place.
-
- </para>
-
- <para>
-
- So given the &SConstruct; file above,
- if the &hello_c; file exists in the local
- build directory,
- &SCons; will rebuild the &hello; program
- as normal:
-
- </para>
-
- <literallayout>
- % <userinput>scons</userinput>
- gcc -c hello.c -o hello.o
- gcc -o hello hello.o
- </literallayout>
-
- <para>
-
- If, however, there is no local &hello_c; file,
- but one exists in <filename>/usr/repository1</filename>,
- &SCons; will recompile the &hello; program
- from the source file it finds in the repository:
-
- </para>
-
- <literallayout>
- % <userinput>scons</userinput>
- gcc -c /usr/repository1/hello.c -o hello.o
- gcc -o hello hello.o
- </literallayout>
-
- <para>
-
- And similarly, if there is no local &hello_c; file
- and no <filename>/usr/repository1/hello.c</filename>,
- but one exists in <filename>/usr/repository2</filename>:
-
- </para>
-
- <literallayout>
- % <userinput>scons</userinput>
- gcc -c /usr/repository2/hello.c -o hello.o
- gcc -o hello hello.o
- </literallayout>
-
- <para>
+ <literallayout>
+ % <userinput>scons</userinput>
+ gcc -c hello.c -o hello.o
+ gcc -o hello hello.o
+ </literallayout>
+
+ <para>
- </para>
+ If, however, there is no local &hello_c; file,
+ but one exists in <filename>/usr/repository1</filename>,
+ &SCons; will recompile the &hello; program
+ from the source file it finds in the repository:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ gcc -c /usr/repository1/hello.c -o hello.o
+ gcc -o hello hello.o
+ </literallayout>
+
+ <para>
+
+ And similarly, if there is no local &hello_c; file
+ and no <filename>/usr/repository1/hello.c</filename>,
+ but one exists in <filename>/usr/repository2</filename>:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ gcc -c /usr/repository2/hello.c -o hello.o
+ gcc -o hello hello.o
+ </literallayout>
+
+ <para>
+
+ </para>
- </section>
+ </section>
- <section>
- <title>Finding the &SConstruct; file in repositories</title>
+ <section>
+ <title>Finding the &SConstruct; file in repositories</title>
- <para>
+ <para>
- &SCons; will also search in repositories
- for the &SConstruct; file and any specified &SConscript; files.
- This poses a problem, though: how can &SCons; search a
- repository tree for an &SConstruct; file
- if the &SConstruct; file itself contains the information
- 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>:
+ &SCons; will also search in repositories
+ for the &SConstruct; file and any specified &SConscript; files.
+ This poses a problem, though: how can &SCons; search a
+ repository tree for an &SConstruct; file
+ if the &SConstruct; file itself contains the information
+ 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>:
- </para>
+ </para>
- <literallayout>
- % <userinput>scons -Y /usr/repository1 -Y /usr/repository2</userinput>
- </literallayout>
+ <literallayout>
+ % <userinput>scons -Y /usr/repository1 -Y /usr/repository2</userinput>
+ </literallayout>
- <para>
+ <para>
- When looking for source or derived files,
- &SCons; will first search the repositories
- specified on the command line,
- and then search the repositories
- specified in the &SConstruct; or &SConscript; files.
+ When looking for source or derived files,
+ &SCons; will first search the repositories
+ specified on the command line,
+ and then search the repositories
+ specified in the &SConstruct; or &SConscript; files.
- </para>
+ </para>
- </section>
+ </section>
- <section>
- <title>Finding derived files in repositories</title>
+ <section>
+ <title>Finding derived files in repositories</title>
- <para>
+ <para>
- If a repository contains not only source files,
- but also derived files (such as object files,
- libraries, or executables), &SCons; will perform
- its normal MD5 signature calculation to
- decide if a derived file in a repository is up-to-date,
- or the derived file must be rebuilt in the local build directory.
- For the &SCons; signature calculation to work correctly,
- a repository tree must contain the &sconsign; files
- that &SCons; uses to keep track of signature information.
+ If a repository contains not only source files,
+ but also derived files (such as object files,
+ libraries, or executables), &SCons; will perform
+ its normal MD5 signature calculation to
+ decide if a derived file in a repository is up-to-date,
+ or the derived file must be rebuilt in the local build directory.
+ For the &SCons; signature calculation to work correctly,
+ a repository tree must contain the &sconsign; files
+ that &SCons; uses to keep track of signature information.
- </para>
+ </para>
- <para>
+ <para>
- Usually, this would be done by a build integrator
- who would run &SCons; in the repository
- to create all of its derived files and &sconsign; files,
- or who would &SCons; in a separate build directory
- and copying the resulting tree to the desired repository:
+ Usually, this would be done by a build integrator
+ who would run &SCons; in the repository
+ to create all of its derived files and &sconsign; files,
+ or who would &SCons; in a separate build directory
+ and copying the resulting tree to the desired repository:
- </para>
+ </para>
- <literallayout>
- % <userinput>cd /usr/repository1</userinput>
- % <userinput>scons</userinput>
- gcc -c hello.c -o hello.o
- gcc -o hello hello.o
- </literallayout>
+ <literallayout>
+ % <userinput>cd /usr/repository1</userinput>
+ % <userinput>scons</userinput>
+ gcc -c hello.c -o hello.o
+ gcc -o hello hello.o
+ </literallayout>
- <para>
-
- (Note that this is safe even if the &SConstruct; file
- lists <filename>/usr/repository1</filename> as a repository,
- because &SCons; will remove the current build directory
- from its repository list for that invocation.)
+ <para>
+
+ (Note that this is safe even if the &SConstruct; file
+ lists <filename>/usr/repository1</filename> as a repository,
+ because &SCons; will remove the current build directory
+ from its repository list for that invocation.)
- </para>
+ </para>
- <para>
+ <para>
- Now, with the repository populated,
- we only need to create the one local source file
- we're interested in working with at the moment,
- and use the <literal>-Y</literal> option to
- tell &SCons; to fetch any other files it needs
- from the repository:
+ Now, with the repository populated,
+ we only need to create the one local source file
+ we're interested in working with at the moment,
+ and use the <literal>-Y</literal> option to
+ tell &SCons; to fetch any other files it needs
+ from the repository:
- </para>
+ </para>
- <literallayout>
- % <userinput>cd $HOME/build</userinput>
- % <userinput>edit hello.c</userinput>
- % <userinput>scons -Y /usr/repository1</userinput>
- gcc -c hello.c -o hello.o
- gcc -o hello hello.o
- XXXXXXX
- </literallayout>
+ <literallayout>
+ % <userinput>cd $HOME/build</userinput>
+ % <userinput>edit hello.c</userinput>
+ % <userinput>scons -Y /usr/repository1</userinput>
+ gcc -c hello.c -o hello.o
+ gcc -o hello hello.o
+ XXXXXXX
+ </literallayout>
- <para>
+ <para>
- Notice that &SCons; realizes that it does not need to
- rebuild a local XXX.o file,
- but instead uses the already-compiled XXX.o file
- from the repository.
+ Notice that &SCons; realizes that it does not need to
+ rebuild a local XXX.o file,
+ but instead uses the already-compiled XXX.o file
+ from the repository.
- </para>
+ </para>
- </section>
+ </section>
- <section>
- <title>Guaranteeing local copies of files</title>
+ <section>
+ <title>Guaranteeing local copies of files</title>
- <para>
+ <para>
- If the repository tree contains the complete results of a build,
- and we try to build from the repository
- without any files in our local tree,
- something moderately surprising happens:
+ If the repository tree contains the complete results of a build,
+ and we try to build from the repository
+ without any files in our local tree,
+ something moderately surprising happens:
- </para>
+ </para>
- <literallayout>
- % <userinput>mkdir $HOME/build2</userinput>
- % <userinput>cd $HOME/build2</userinput>
- % <userinput>scons -Y /usr/all/repository hello</userinput>
- scons: `hello' is up-to-date.
- </literallayout>
+ <literallayout>
+ % <userinput>mkdir $HOME/build2</userinput>
+ % <userinput>cd $HOME/build2</userinput>
+ % <userinput>scons -Y /usr/all/repository hello</userinput>
+ scons: `hello' is up-to-date.
+ </literallayout>
- <para>
+ <para>
- Why does &SCons; say that the &hello; program
- is up-to-date when there is no &hello; program
- in the local build directory?
- Because the repository (not the local directory)
- contains the up-to-date &hello; program,
- and &SCons; correctly determines that nothing
- needs to be done to rebuild that
- up-to-date copy of the file.
+ Why does &SCons; say that the &hello; program
+ is up-to-date when there is no &hello; program
+ in the local build directory?
+ Because the repository (not the local directory)
+ contains the up-to-date &hello; program,
+ and &SCons; correctly determines that nothing
+ needs to be done to rebuild that
+ up-to-date copy of the file.
- </para>
-
- <para>
+ </para>
+
+ <para>
- There are, however, many times when you want to ensure that a
- local copy of a file always exists.
- A packaging or testing script, for example,
- may assume that certain generated files exist locally.
- To tell &SCons; to make a copy of any up-to-date repository
- file in the local build directory,
- use the &Local; function:
+ There are, however, many times when you want to ensure that a
+ local copy of a file always exists.
+ A packaging or testing script, for example,
+ may assume that certain generated files exist locally.
+ To tell &SCons; to make a copy of any up-to-date repository
+ file in the local build directory,
+ use the &Local; function:
- </para>
+ </para>
- <programlisting>
- env = Environment()
- hello = env.Program('hello.c')
- Local(hello)
- </programlisting>
+ <programlisting>
+ env = Environment()
+ hello = env.Program('hello.c')
+ Local(hello)
+ </programlisting>
- <para>
+ <para>
- If we then run the same command,
- &SCons; will make a local copy of the program
- from the repository copy,
- and tell you that it is doing so:
+ If we then run the same command,
+ &SCons; will make a local copy of the program
+ from the repository copy,
+ and tell you that it is doing so:
- </para>
+ </para>
- <literallayout>
- % cons -R /usr/all/repository hello
- Local copy of hello from /usr/all/repository/hello
- scons: `hello' is up-to-date.
- XXXXXX DO WE REALLY REPORT up-to-date, TOO?
- </literallayout>
+ <literallayout>
+ % scons -Y /usr/all/repository hello
+ Local copy of hello from /usr/all/repository/hello
+ scons: `hello' is up-to-date.
+ XXXXXX DO WE REALLY REPORT up-to-date, TOO?
+ </literallayout>
- <para>
+ <para>
- (Notice that, because the act of making the local copy
- is not considered a "build" of the &hello; file,
- &SCons; still reports that it is up-to-date.)
- XXXXXX DO WE REALLY REPORT up-to-date, TOO?
+ (Notice that, because the act of making the local copy
+ is not considered a "build" of the &hello; file,
+ &SCons; still reports that it is up-to-date.)
+ XXXXXX DO WE REALLY REPORT up-to-date, TOO?
- </para>
+ </para>
- </section>
+ </section>
<para>
- X
+ 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.
</para>
<section>
- <title>X</title>
+ <title>The &BuildDir; Function</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ BuildDir('build', 'src')
+ env = Environment()
+ env.Program('build/hello.c')
+ </programlisting>
+
+ <para>
+
+ X
+
+ </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>
+
+ </section>
+
+ <section>
+ <title>Avoiding Duplicate Source Files in the Build Directory</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ BuildDir('build', 'src', duplicate=0)
+ env = Environment()
+ env.Program('build/hello.c')
+ </programlisting>
+
+ <para>
+
+ X
+
+ </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>
+
+ <para>
+
+ X
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Why &SCons; Duplicates Source Files by Default</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environmnet()
+ </programlisting>
+
+ <para>
+
+ X
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ cc -c build/hello.c -o build/hello.o
+ cc -o build/hello build/hello.o
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Using &BuildDir; With an &SConscript; File</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Program('hello.c')
+ </programlisting>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ BuildDir('build', 'src')
+ SConscript('build/SConscript')
+ </programlisting>
+
+ <para>
+
+ X
+
+ </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>
+
+ </section>
+
+ <section>
+ <title>Specifying a Build Directory as Part of an &SConscript; Call</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ SConscript('src/SConscript', build_dir='build')
+ </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>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ SConscript('src/SConscript', build_dir='build', duplicate=0)
+ </programlisting>
+
+ <para>
+
+ X
+
+ </para>
+
+ <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>
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 extremely easy to learn,
+ Python is very easy to learn,
and this User's Guide will introduce you step-by-step
to the relatively small amount of Python you'll
- neede to know to be able to use &SCons; effectively.
+ need to know to be able to use &SCons; effectively.
</para>
<para>
- One minor drawback to the use of a Python list
+ One drawback to the use of a Python list
for source files is that
each file name must be enclosed in quotes
(either single quotes or double quotes).
--- /dev/null
+<!--
+
+ 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>
+
+ X
+
+ </para>
+
+ <section>
+ <title>Fetching Source Code From BitKeeper</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.BitKeeper('XXX')
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From CVS</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.CVS('XXX')
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From RCS</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.RCS()
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From SCCS</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.SCCS()
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ </section>
+
+ <section>
+ <title>Fetching Source Code From Subversion</title>
+
+ <para>
+
+ X
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.SourceCode('.', env.Subversion('XXX')
+ env.Program('hello.c')
+ </programlisting>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ XXX
+ </literallayout>
+
+ </section>
</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>