<screen>
% <userinput>scons -Q /</userinput>
- \e[?1034hcc -o hello.o -c hello.c
+ cc -o hello.o -c hello.c
cc -o hello hello.o
Install file: "hello" as "/usr/bin/hello"
Install file: "hello" as "install/bin/hello"
<screen>
% <userinput>scons -Q</userinput>
- \e[?1034hcc -o test_stuff.o -c test_stuff.c
+ cc -o test_stuff.o -c test_stuff.c
cc -o tests/test_stuff test_stuff.o
</screen>
<screen>
C:\><userinput>scons -Q</userinput>
- IndexError: list index out of range:
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Script\Main.py", line 1294:
- _exec_main(parser, values)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Script\Main.py", line 1259:
- _main(parser)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Script\Main.py", line 929:
- SCons.Script._SConscript._SConscript(fs, script)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Script\SConscript.py", line 179:
- exec sys.stdin in call_stack[-1].globals
- File "<stdin>", line 219:
- None
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Script\SConscript.py", line 614:
- env = self.factory()
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Script\SConscript.py", line 594:
- default_env = SCons.Defaults.DefaultEnvironment()
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Defaults.py", line 91:
- _default_env = apply(SCons.Environment.Environment, args, kw)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Environment.py", line 1004:
- apply_tools(self, tools, toolpath)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Environment.py", line 106:
- env.Tool(tool)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Environment.py", line 1703:
- tool(self)
- File "<stdin>", line 67:
- None
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Tool\msvc.py", line 239:
- mssdk.generate(env)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Tool\mssdk.py", line 41:
- mssdk_setup_env(env)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Tool\MSCommon\sdk.py", line 298:
- mssdk = get_default_sdk()
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Tool\MSCommon\sdk.py", line 262:
- return InstalledSDKList[0]
- \e[?1034h
+ rc /fores.res res.rc
+ cl /Fotest_stuff.obj /c test_stuff.c /nologo
+ link /nologo /OUT:tests\test_stuff.exe test_stuff.obj res.res
</screen>
<para>
<screen>
% <userinput>scons -Q install</userinput>
- \e[?1034hcc -o hello.o -c hello.c
+ cc -o hello.o -c hello.c
cc -o hello hello.o
Install file: "hello" as "/usr/bin/hello"
</screen>
<screen>
% <userinput>scons -Q install-bin</userinput>
- \e[?1034hcc -o foo.o -c foo.c
+ cc -o foo.o -c foo.c
cc -o foo foo.o
Install file: "foo" as "/usr/bin/foo"
% <userinput>scons -Q install-lib</userinput>
- \e[?1034hcc -o bar.o -c bar.c
+ cc -o bar.o -c bar.c
ar rc libbar.a bar.o
ranlib libbar.a
Install file: "libbar.a" as "/usr/lib/libbar.a"
% <userinput>scons -Q -c /</userinput>
- \e[?1034hRemoved foo.o
+ Removed foo.o
Removed foo
Removed /usr/bin/foo
Removed bar.o
Removed libbar.a
Removed /usr/lib/libbar.a
% <userinput>scons -Q install</userinput>
- \e[?1034hcc -o foo.o -c foo.c
+ cc -o foo.o -c foo.c
cc -o foo foo.o
Install file: "foo" as "/usr/bin/foo"
cc -o bar.o -c bar.c
<screen>
% <userinput>scons -Q</userinput>
- \e[?1034hcc -o goodbye.o -c goodbye.c
+ cc -o goodbye.o -c goodbye.c
cc -o hello.o -c hello.c
cc -o hello hello.o goodbye.o -L/usr/dir1 -Ldir2 -lfoo1 -lfoo2
</screen>
<screen>
C:\><userinput>scons -Q</userinput>
- IndexError: list index out of range:
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Script\Main.py", line 1294:
- _exec_main(parser, values)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Script\Main.py", line 1259:
- _main(parser)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Script\Main.py", line 929:
- SCons.Script._SConscript._SConscript(fs, script)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Script\SConscript.py", line 179:
- exec sys.stdin in call_stack[-1].globals
- File "<stdin>", line 219:
- None
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Script\SConscript.py", line 614:
- env = self.factory()
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Script\SConscript.py", line 594:
- default_env = SCons.Defaults.DefaultEnvironment()
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Defaults.py", line 91:
- _default_env = apply(SCons.Environment.Environment, args, kw)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Environment.py", line 1004:
- apply_tools(self, tools, toolpath)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Environment.py", line 106:
- env.Tool(tool)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Environment.py", line 1703:
- tool(self)
- File "<stdin>", line 67:
- None
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Tool\msvc.py", line 239:
- mssdk.generate(env)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Tool\mssdk.py", line 41:
- mssdk_setup_env(env)
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Tool\MSCommon\sdk.py", line 298:
- mssdk = get_default_sdk()
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Tool\MSCommon\sdk.py", line 262:
- return InstalledSDKList[0]
- \e[?1034h
+ cl /Fogoodbye.obj /c goodbye.c /nologo
+ cl /Fohello.obj /c hello.c /nologo
+ link /nologo /OUT:hello.exe /LIBPATH:\usr\dir1 /LIBPATH:dir2 foo1.lib foo2.lib hello.obj goodbye.obj
</screen>
<para>
<screen>
% <userinput>scons -Q .</userinput>
- \e[?1034htar -c -f out1.tar file1 file2
+ tar -c -f out1.tar file1 file2
tar -c -f out2.tar directory
</screen>
<screen>
% <userinput>scons -Q .</userinput>
+ tar -c -z -f out.tar.gz directory
+ </screen>
+
+ <para>
+
+ you may also wish to set the value of the
+ &cv-link-TARSUFFIX; construction variable
+ to your desired suffix for compress &tar; archives,
+ so that &SCons; can append it to the target file name
+ without your having to specify it explicitly:
+
+ </para>
+
+ <programlisting>
+ env = Environment(TARFLAGS = '-c -z',
+ TARSUFFIX = '.tgz')
+ env.Tar('out', 'directory')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q .</userinput>
+ tar -c -z -f out.tgz directory
+ </screen>
+
+ </section>
+
+ <section>
+ <title>The &Zip; Builder</title>
+
+ <para>
+
+ The &b-link-Zip; Builder object creates archives of files
+ and/or directory trees in the ZIP file format.
+ Python versions 1.6 or later
+ contain an internal &zipfile; module
+ that &SCons; will use.
+ In this case, given the following
+ &SConstruct; file:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Zip('out', ['file1', 'file2'])
+ </programlisting>
+
+ <para>
+
+ Your output will reflect the fact
+ that an internal Python function
+ is being used to create the output ZIP archive:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q .</userinput>
+ zip(["out.zip"], ["file1", "file2"])
+ </screen>
+
+ <para>
+
+ If you're using Python version 1.5.2 to run &SCons;,
+ then &SCons; will try to use an external
+ &zip; program as follows:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q .</userinput>
+ zip /home/my/project/zip.out file1 file2
+ </screen>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Java</title>
+
+ <para>
+
+ &SCons; provides Builder objects
+ for creating various types of Java output files.
+
+ </para>
+
+ <section>
+ <title>Building Class Files: the &Java; Builder</title>
+
+ <para>
+
+ The &b-link-Java; builder takes one or more input
+ <filename>.java</filename> files
+ and turns them into one or more
+ <filename>.class</filename> files
+ Unlike most builders, however,
+ the &Java; builder takes
+ target and source <emphasis>directories</emphasis>,
+ not files, as input.
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Java(target = 'classes', source = 'src')
+ </programlisting>
+
+ <para>
+
+ The &Java; builder will then
+ search the specified source directory
+ tree for all <filename>.java</filename> files,
+ and pass any out-of-date
+
+ </para>
+
+ <screen>
+ XXX Java() screen
+ </screen>
+
+ </section>
+
+ <section>
+ <title>The &Jar; Builder</title>
+
+ <para>
+
+ XXX The &Jar; builder object
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ env.Java(target = 'classes', source = 'src')
+ env.Jar(target = '', source = 'classes')
+ </programlisting>
+
+ <screen>
+ XXX Jar() screen
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Building C header and stub files: the &JavaH; Builder</title>
+
+ <para>
+
+ XXX JavaH() para
+
+ </para>
+
+ <programlisting>
+ XXX JavaH() programlisting
+ </programlisting>
+
+ <screen>
+ XXX JavaH() screen
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Building RMI stub and skeleton class files: the &RMIC; Builder</title>
+
+ <para>
+
+ XXX RMIC() para
+
+ </para>
+
+ <programlisting>
+ XXX RMIC() programlisting
+ </programlisting>
+
+ <screen>
+ XXX RMIC() screen
+ </screen>
+
+ </section>
+
+ </section>
<screen>
% <userinput>scons -Q</userinput>
+ sed 's/x/y/' < foo.in > foo.out
+ </screen>
+
+ <para>
+
+ This is often more convenient than
+ creating a &Builder; object
+ and adding it to the &cv-link-BUILDERS; variable
+ of a &consenv;
+
+ </para>
+
+ <para>
+
+ Note that the action you specify to the
+ &Command; &Builder; can be any legal &SCons; &Action;,
+ such as a Python function:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ def build(target, source, env):
+ # Whatever it takes to build
+ return None
+ env.Command('foo.out', 'foo.in', build)
+ </programlisting>
+
+ <para>
+
+ Which executes as follows:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ build(["foo.out"], ["foo.in"])
+ </screen>
+
+ <para>
+
+ Note that &cv-link-SOURCE; and &cv-link-TARGET; are expanded
+ in the source and target as well as of SCons 1.1,
+ so you can write:
+
+ </para>
+
+ <programlisting>
+ env.Command('${SOURCE.basename}.out', 'foo.in', build)
+ </programlisting>
+
+
+ <para>
+
+ which does the same thing as the previous example, but allows you
+ to avoid repeating yourself.
+
+ </para>
+
+<!--
+
+ __COPYRIGHT__
+
+ 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 Adding new methods
+
+For slightly more demanding changes, you may wish to add new methods to the
+C<cons> package. Here's an example of a very simple extension,
+C<InstallScript>, which installs a tcl script in a requested location, but
+edits the script first to reflect a platform-dependent path that needs to be
+installed in the script:
+
+ # cons::InstallScript - Create a platform dependent version of a shell
+ # script by replacing string ``#!your-path-here'' with platform specific
+ # path $BIN_DIR.
+
+ sub cons::InstallScript {
+ my ($env, $dst, $src) = @_;
+ Command $env $dst, $src, qq(
+ sed s+your-path-here+$BIN_DIR+ %< > %>
+ chmod oug+x %>
+ );
+ }
+
+Notice that this method is defined directly in the C<cons> package (by
+prefixing the name with C<cons::>). A change made in this manner will be
+globally visible to all environments, and could be called as in the
+following example:
+
+ InstallScript $env "$BIN/foo", "foo.tcl";
+
+For a small improvement in generality, the C<BINDIR> variable could be
+passed in as an argument or taken from the construction environment-,-as
+C<%BINDIR>.
+
+
+=head2 Overriding methods
+
+Instead of adding the method to the C<cons> name space, you could define a
+new package which inherits existing methods from the C<cons> package and
+overrides or adds others. This can be done using Perl's inheritance
+mechanisms.
+
+The following example defines a new package C<cons::switch> which
+overrides the standard C<Library> method. The overridden method builds
+linked library modules, rather than library archives. A new
+constructor is provided. Environments created with this constructor
+will have the new library method; others won't.
+
+ package cons::switch;
+ BEGIN {@ISA = 'cons'}
+
+ sub new {
+ shift;
+ bless new cons(@_);
+ }
+
+ sub Library {
+ my($env) = shift;
+ my($lib) = shift;
+ my(@objs) = Objects $env @_;
+ Command $env $lib, @objs, q(
+ %LD -r %LDFLAGS %< -o %>
+ );
+ }
+
+This functionality could be invoked as in the following example:
+
+ $env = new cons::switch(@overrides);
+ ...
+ Library $env 'lib.o', 'foo.c', 'bar.c';
+
+-->
+
+ <para>
+
+ Although &SCons; provides many useful methods
+ for building common software products:
+ programs, libraries, documents.
+ you frequently want to be
+ able to build some other type of file
+ not supported directly by &SCons;.
+ Fortunately, &SCons; makes it very easy
+ to define your own &Builder; objects
+ for any custom file types you want to build.
+ (In fact, the &SCons; interfaces for creating
+ &Builder; objects are flexible enough and easy enough to use
+ that all of the the &SCons; built-in &Builder; objects
+ are created the mechanisms described in this section.)
+
+ </para>
+
+ <section>
+ <title>Writing 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 < $SOURCE > $TARGET')
+ </programlisting>
+
+ <para>
+
+ All the above line does is create a free-standing
+ &Builder; object.
+ The next section will show us how to actually use it.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Attaching a Builder to a &ConsEnv;</title>
+
+ <para>
+
+ A &Builder; object isn't useful
+ until it's attached to a &consenv;
+ so that we can call it to arrange
+ for files to be built.
+ This is done through the &cv-link-BUILDERS;
+ &consvar; in an environment.
+ The &cv-BUILDERS; variable is a Python dictionary
+ that maps the names by which you want to call
+ various &Builder; objects to the objects themselves.
+ For example, if we want to call the
+ &Builder; we just defined by the name
+ <function>Foo</function>,
+ our &SConstruct; file might look like:
+
+ </para>
+
+
+
+ <programlisting>
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ </programlisting>
+
+ <para>
+
+ With the &Builder; attached to our &consenv;
+ with the name <function>Foo</function>,
+ we can now actually call it like so:
+
+ </para>
+
+ <programlisting>
+ env.Foo('file.foo', 'file.input')
+ </programlisting>
+
+ <para>
+
+ Then when we run &SCons; it looks like:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ foobuild < file.input > file.foo
+ </screen>
+
+ <para>
+
+ Note, however, that the default &cv-BUILDERS;
+ variable in a &consenv;
+ comes with a default set of &Builder; objects
+ already defined:
+ &b-link-Program;, &b-link-Library;, etc.
+ And when we explicitly set the &cv-BUILDERS; variable
+ when we create the &consenv;,
+ the default &Builder;s are no longer part of
+ the environment:
+
+ </para>
+
+ <!--
+ The ToolSurrogate stuff that's used to capture output initializes
+ SCons.Defaults.ConstructionEnvironment with its own list of TOOLS.
+ In this next example, we want to show the user that when they
+ set the BUILDERS explicitly, the call to env.Program() generates
+ an AttributeError. This won't happen with all of the default
+ ToolSurrogates in the default construction environment. To make the
+ AttributeError show up, we have to overwite the default construction
+ environment's TOOLS variable so Program() builder doesn't show up.
+
+ We do this by executing a slightly different SConstruct file than the
+ one we print in the guide, with two extra statements at the front
+ that overwrite the TOOLS variable as described. Note that we have
+ to jam those statements on to the first line to keep the line number
+ in the generated error consistent with what the user will see in the
+ User's Guide.
+ -->
+ <programlisting>
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ AttributeError: SConsEnvironment instance has no attribute 'Program':
+ File "/home/my/project/SConstruct", line 4:
+ env.Program('hello.c')
+ </screen>
+
+ <para>
+
+ To be able to use both our own defined &Builder; objects
+ and the default &Builder; objects in the same &consenv;,
+ you can either add to the &cv-BUILDERS; variable
+ using the &Append; function:
+
+ </para>
+
+
+
+ <programlisting>
+ env = Environment()
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ 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 &cv-BUILDERS; dictionary:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ 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 &b-link-Program; &Builder;:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ foobuild < file.input > file.foo
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ </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 < $SOURCE > $TARGET',
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file1')
+ env.Foo('file2')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ foobuild < file1.input > file1.foo
+ foobuild < file2.input > file2.foo
+ </screen>
+
+ <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>
+
+ <section>
+ <title>Builders That Execute Python Functions</title>
+
+ <para>
+
+ 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).
+ Such a &buildfunc; definition looks like:
+
+ </para>
+
+ <programlisting>
+ def build_function(target, source, env):
+ # Code to build "target" from "source"
+ return None
+ </programlisting>
+
+ <para>
+
+ The arguments of a &buildfunc; are:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>target</term>
+
+ <listitem>
+ <para>
+
+ A list of Node objects representing
+ the target or targets to be
+ built by this builder function.
+ The file names of these target(s)
+ may be extracted using the Python &str; function.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>source</term>
+
+ <listitem>
+ <para>
+
+ A list of Node objects representing
+ the sources to be
+ used by this builder function to build the targets.
+ The file names of these source(s)
+ may be extracted using the Python &str; function.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>env</term>
+
+ <listitem>
+ <para>
+
+ The &consenv; used for building the target(s).
+ The builder function may use any of the
+ environment's construction variables
+ in any way to affect how it builds the targets.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ The builder function must
+ return a <literal>0</literal> or <literal>None</literal> value
+ if the target(s) are built successfully.
+ The builder function
+ may raise an exception
+ or return any non-zero value
+ to indicate that the build is unsuccessful,
+
+ </para>
+
+ <para>
+
+ 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):
+ # Code to build "target" from "source"
+ 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>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ build_function(["file.foo"], ["file.input"])
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Builders That Create Actions Using a &Generator;</title>
+
+ <para>
+
+ &SCons; Builder objects can create an action "on the fly"
+ by using a function called a &generator;.
+ This provides a great deal of flexibility to
+ construct just the right list of commands
+ to build your target.
+ A &generator; looks like:
+
+ </para>
+
+ <programlisting>
+ def generate_actions(source, target, env, for_signature):
+ return 'foobuild < %s > %s' % (target[0], source[0])
+ </programlisting>
+
+ <para>
+
+ The arguments of a &generator; are:
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>source</term>
+
+ <listitem>
+ <para>
+
+ A list of Node objects representing
+ the sources to be built
+ by the command or other action
+ generated by this function.
+ The file names of these source(s)
+ may be extracted using the Python &str; function.
+
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term>target</term>
+
+ <listitem>
+ <para>
+
+ A list of Node objects representing
+ the target or targets to be built
+ by the command or other action
+ generated by this function.
+ The file names of these target(s)
+ may be extracted using the Python &str; function.
+
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term>env</term>
+
+ <listitem>
+ <para>
+
+ The &consenv; used for building the target(s).
+ The generator may use any of the
+ environment's construction variables
+ in any way to determine what command
+ or other action to return.
+
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ <varlistentry>
+ <term>for_signature</term>
+
+ <listitem>
+ <para>
+
+ A flag that specifies whether the
+ generator is being called to contribute to a build signature,
+ as opposed to actually executing the command.
+
+ <!-- XXX NEED MORE HERE, describe generators use in signatures -->
+
+ </para>
+ </listitem>
+
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ The &generator; must return a
+ command string or other action that will be used to
+ build the specified target(s) from the specified source(s).
+
+ </para>
+
+ <para>
+
+ Once you've defined a &generator;,
+ you create a &Builder; to use it
+ by specifying the generator keyword argument
+ instead of <literal>action</literal>.
+
+ </para>
+
+
+
+ <programlisting>
+ def generate_actions(source, target, env, for_signature):
+ return 'foobuild < %s > %s' % (source[0], target[0])
+ bld = Builder(generator = generate_actions,
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file')
+ </programlisting>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ foobuild < file.input > file.foo
+ </screen>
+
+ <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 or Source Lists Using an &Emitter;</title>
+
+ <para>
+
+ &SCons; supports the ability for a Builder to modify the
+ lists of target(s) from the specified source(s).
+ You do this by defining an &emitter; function
+ that takes as its arguments
+ the list of the targets passed to the builder,
+ the list of the sources passed to the builder,
+ and the construction environment.
+ The emitter function should return the modified
+ lists of targets that should be built
+ and sources from which the targets will be built.
+
+ </para>
+
+ <para>
+
+ For example, suppose you want to define a Builder
+ that always calls a <filename>foobuild</filename> program,
+ and you want to automatically add
+ a new target file named
+ <filename>new_target</filename>
+ and a new source file named
+ <filename>new_source</filename>
+ whenever it's called.
+ The &SConstruct; file might look like this:
+
+ </para>
+
+
+
+ <programlisting>
+ def modify_targets(target, source, env):
+ target.append('new_target')
+ source.append('new_source')
+ return target, source
+ bld = Builder(action = 'foobuild $TARGETS - $SOURCES',
+ suffix = '.foo',
+ src_suffix = '.input',
+ emitter = modify_targets)
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file')
+ </programlisting>
+
+ <para>
+
+ And would yield the following output:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ foobuild file.foo new_target - file.input new_source
+ </screen>
+
+ <para>
+
+ One very flexible thing that you can do is
+ use a construction variable to specify
+ different emitter functions for different
+ construction variable.
+ To do this, specify a string
+ containing a construction variable
+ expansion as the emitter when you call
+ the &Builder; function,
+ and set that construction variable to
+ the desired emitter function
+ in different construction environments:
+
+ </para>
+
+ <programlisting>
+ bld = Builder(action = 'my_command $SOURCES > $TARGET',
+ suffix = '.foo',
+ src_suffix = '.input',
+ emitter = '$MY_EMITTER')
+ def modify1(target, source, env):
+ return target, source + ['modify1.in']
+ def modify2(target, source, env):
+ return target, source + ['modify2.in']
+ env1 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify1)
+ env2 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify2)
+ env1.Foo('file1')
+ env2.Foo('file2')
+ import os
+ env1['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd()
+ env2['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd()
+
+
+ </programlisting>
+
+ <programlisting>
+ bld = Builder(action = 'my_command $SOURCES > $TARGET',
+ suffix = '.foo',
+ src_suffix = '.input',
+ emitter = '$MY_EMITTER')
+ def modify1(target, source, env):
+ return target, source + ['modify1.in']
+ def modify2(target, source, env):
+ return target, source + ['modify2.in']
+ env1 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify1)
+ env2 = Environment(BUILDERS = {'Foo' : bld},
+ MY_EMITTER = modify2)
+ env1.Foo('file1')
+ env2.Foo('file2')
+
+ </programlisting>
+
+ <para>
+
+ In this example, the <filename>modify1.in</filename>
+ and <filename>modify2.in</filename> files
+ get added to the source lists
+ of the different commands:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ my_command file1.input modify1.in > file1.foo
+ my_command file2.input modify2.in > file2.foo
+ </screen>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>target_factor=, source_factory=</title>
+
+ </section>
+
+ <section>
+ <title>target_scanner=, source_scanner=</title>
+
+ </section>
+
+ <section>
+ <title>multi=</title>
+
+ </section>
+
+ <section>
+ <title>single_source=</title>
+
+ </section>
+
+ <section>
+ <title>src_builder=</title>
+
+ </section>
+
+ <section>
+ <title>ensure_suffix=</title>
+
+ </section>
+
+ -->
+
+ <section>
+ <title>Where To Put Your Custom Builders and Tools</title>
+
+ <para>
+
+ The <filename>site_scons</filename> directory gives you a place to
+ put Python modules you can import into your &SConscript; files
+ (<filename>site_scons</filename>),
+ add-on tools that can integrate into &SCons;
+ (<filename>site_scons/site_tools</filename>),
+ and a <filename>site_scons/site_init.py</filename> file that
+ gets read before any &SConstruct; or &SConscript; file,
+ allowing you to change &SCons;'s default behavior.
+
+ </para>
+
+ <para>
+
+ If you get a tool from somewhere (the &SCons; wiki or a third party,
+ for instance) and you'd like to use it in your project, the
+ <filename>site_scons</filename> dir is the simplest place to put it.
+ Tools come in two flavors; either a Python function that operates on
+ an &Environment; or a Python file containing two functions,
+ <function>exists()</function> and <function>generate()</function>.
+
+ </para>
+
+ <para>
+
+ A single-function Tool can just be included in your
+ <filename>site_scons/site_init.py</filename> file where it will be
+ parsed and made available for use. For instance, you could have a
+ <filename>site_scons/site_init.py</filename> file like this:
+
+ </para>
+
+ <programlisting>
+ def TOOL_ADD_HEADER(env):
+ """A Tool to add a header from $HEADER to the source file"""
+ add_header = Builder(action=['echo "$HEADER" > $TARGET',
+ 'cat $SOURCE >> $TARGET'])
+ env.Append(BUILDERS = {'AddHeader' : add_header})
+ env['HEADER'] = '' # set default value
+ </programlisting>
+
+ <para>
+
+ and a &SConstruct; like this:
+
+ </para>
+
+ <programlisting>
+ # Use TOOL_ADD_HEADER from site_scons/site_init.py
+ env=Environment(tools=['default', TOOL_ADD_HEADER], HEADER="=====")
+ env.AddHeader('tgt', 'src')
+ </programlisting>
+
+ <para>
+
+ The <function>TOOL_ADD_HEADER</function> tool method will be
+ called to add the <function>AddHeader</function> tool to the
+ environment.
+
+ </para>
+
+ <!--
+ <scons_output example="site1" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+ -->
+
+ <para>
+ Similarly, a more full-fledged tool with
+ <function>exists()</function> and <function>generate()</function>
+ methods can be installed in
+ <filename>site_scons/site_tools/toolname.py</filename>. Since
+ <filename>site_scons/site_tools</filename> is automatically added
+ to the head of the tool search path, any tool found there will be
+ available to all environments. Furthermore, a tool found there
+ will override a built-in tool of the same name, so if you need to
+ change the behavior of a built-in tool, site_scons gives you the
+ hook you need.
+ </para>
+
+ <para>
+ Many people have a library of utility Python functions they'd like
+ to include in &SConscript;s; just put that module in
+ <filename>site_scons/my_utils.py</filename> or any valid Python module name of your
+ choice. For instance you can do something like this in
+ <filename>site_scons/my_utils.py</filename> to add
+ <function>build_id</function> and <function>MakeWorkDir</function>
+ functions:
+ </para>
+
+ <programlisting>
+ from SCons.Script import * # for Execute and Mkdir
+ def build_id():
+ """Return a build ID (stub version)"""
+ return "100"
+ def MakeWorkDir(workdir):
+ """Create the specified dir immediately"""
+ Execute(Mkdir(workdir))
+ </programlisting>
+
+ <para>
+
+ And then in your &SConscript; or any sub-&SConscript; anywhere in
+ your build, you can import <filename>my_utils</filename> and use it:
+
+ </para>
+
+ <programlisting>
+ import my_utils
+ print "build_id=" + my_utils.build_id()
+ my_utils.MakeWorkDir('/tmp/work')
+ </programlisting>
+
+ <para>
+ Note that although you can put this library in
+ <filename>site_scons/site_init.py</filename>,
+ it is no better there than <filename>site_scons/my_utils.py</filename>
+ since you still have to import that module into your &SConscript;.
+ Also note that in order to refer to objects in the SCons namespace
+ such as &Environment; or &Mkdir; or &Execute; in any file other
+ than a &SConstruct; or &SConscript; you always need to do
+ </para>
+ <programlisting>
+ from SCons.Script import *
+ </programlisting>
+
+ <para>
+ This is true in modules in <filename>site_scons</filename> such as
+ <filename>site_scons/site_init.py</filename> as well.
+ </para>
+
+ <para>
+
+ If you have a machine-wide site dir you'd like to use instead of
+ <filename>./site_scons</filename>, use the
+ <literal>--site-dir</literal> option to point to your dir.
+ <filename>site_init.py</filename> and
+ <filename>site_tools</filename> will be located under that dir.
+ To avoid using a <filename>site_scons</filename> dir at all, even
+ if it exists, use the <literal>--no-site-dir</literal> option.
+
+ </para>
+
+ </section>
+
+
+ <!--
+
+ <section>
+ <title>Builders That Use Other Builders</title>
+
+ <para>
+
+ XXX para
+
+ </para>
+
+ <scons_example name="ex8">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ #env.SourceCode('.', env.BitKeeper('my_command'))
+ env.Program('hello.c')
+ </file>
+ <file name="hello.c">
+ hello.c
+ </file>
+ </scons_example>
+
+ <scons_output example="ex8">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ -->
+<!--
+
+ __COPYRIGHT__
+
+ 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 refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
+
+<refentry id="Command">
+
+<refmeta>
+<refentrytitle>Command</refentrytitle>
+</refmeta>
+
+<methodsynopsis>
+ <methodname>env.Command</methodname>
+ <methodparam>foo</methodparam>
+ <methodparam>bar</methodparam>
+</methodsynopsis>
+
+</refentry>
+-->
+
+<para>
+
+This appendix contains descriptions of all of the
+Builders that are <emphasis>potentially</emphasis>
+available "out of the box" in this version of SCons.
+
+</para>
+
+<variablelist>
+
+&builders-gen;
+
+</variablelist>
+<!--
+
+ __COPYRIGHT__
+
+ 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>
+
+ 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.
+
+ </para>
+
+ <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.
+ <footnote>
+ <para>
+ Actually, the MD5 signature is used as the name of the file
+ in the shared cache directory in which the contents are stored.
+ </para>
+ </footnote>
+ 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>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons -Q</userinput>
+ Retrieved `hello.o' from cache
+ Retrieved `hello' from cache
+ </screen>
+
+ <para>
+
+ Note that the &CacheDir; feature still calculates
+ MD5 build sigantures for the shared cache file names
+ even if you configure &SCons; to use timestamps
+ to decide if files are up to date.
+ (See the <xref linkend="chap-depends"></xref>
+ chapter for information about the &Decider; function.)
+ Consequently, using &CacheDir; may reduce or eliminate any
+ potential performance improvements
+ from using timestamps for up-to-date decisions.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Keeping Build Output Consistent</title>
+
+ <para>
+
+ One potential drawback to using a shared cache
+ is that the output printed by &SCons;
+ 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>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons -Q --cache-show</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ <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 Using the Shared Cache for Specific Files</title>
+
+ <para>
+
+ You may want to disable caching for certain
+ specific files in your configuration.
+ For example, if you only want to put
+ executable files in a central cache,
+ but not the intermediate object files,
+ you can use the &NoCache;
+ function to specify that the
+ object files should not be cached:
+
+ </para>
+
+ <programlisting>
+ env = Environment()
+ obj = env.Object('hello.c')
+ env.Program('hello.c')
+ CacheDir('cache')
+ NoCache('hello.o')
+ </programlisting>
+
+ <para>
+
+ Then when you run &scons; after cleaning
+ the built targets,
+ it will recompile the object file locally
+ (since it doesn't exist in the shared cache directory),
+ but still realize that the shared cache directory
+ contains an up-to-date executable program
+ that can be retrieved instead of re-linking:
+
+ </para>
+
+ <!--
+
+ <scons_output example="ex1">
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>scons -Q -c</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ Retrieved `hello' from cache
+ </screen>
+
+ </section>
+
+ <section>
+ <title>Disabling the 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>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons -Q</userinput>
+ Retrieved `hello.o' from cache
+ Retrieved `hello' from cache
+ % <userinput>scons -Q -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons -Q --cache-disable</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ </screen>
+
+ </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>
+
+ 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 already exist in your local tree
+ from having been built by a previous invocation:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q --cache-disable</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q -c</userinput>
+ Removed hello.o
+ Removed hello
+ % <userinput>scons -Q --cache-disable</userinput>
+ cc -o hello.o -c hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q --cache-force</userinput>
+ scons: `.' is up to date.
+ % <userinput>scons -Q</userinput>
+ scons: `.' is up to date.
+ </screen>
+
+ <para>
+
+ 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>
+
+ </section>
+
+ <section>
+ <title>Minimizing Cache Contention: the <literal>--random</literal> Option</title>
+
+ <para>
+
+ If you allow multiple builds to update the
+ shared cache directory simultaneously,
+ two builds that occur at the same time
+ can sometimes start "racing"
+ with one another to build the same files
+ in the same order.
+ If, for example,
+ you are linking multiple files into an executable program:
+
+ </para>
+
+ <programlisting>
+ Program('prog',
+ ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c'])
+ </programlisting>
+
+ <para>
+
+ &SCons; will normally build the input object files
+ on which the program depends in their normal, sorted order:
+
+ </para>
+
+ <screen>
+ % <userinput>scons -Q</userinput>
+ cc -o f1.o -c f1.c
+ cc -o f2.o -c f2.c
+ cc -o f3.o -c f3.c
+ cc -o f4.o -c f4.c
+ cc -o f5.o -c f5.c
+ cc -o prog f1.o f2.o f3.o f4.o f5.o
+ </screen>
+
+ <para>
+
+ But if two such builds take place simultaneously,
+ they may each look in the cache at nearly the same
+ time and both decide that <filename>f1.o</filename>
+ must be rebuilt and pushed into the shared cache directory,
+ then both decide that <filename>f2.o</filename>
+ must be rebuilt (and pushed into the shared cache directory),
+ then both decide that <filename>f3.o</filename>
+ must be rebuilt...
+ This won't cause any actual build problems--both
+ builds will succeed,
+ generate correct output files,
+ and populate the cache--but
+ it does represent wasted effort.
+
+ </para>
+
+ <para>
+
+ To alleviate such contention for the cache,
+ you can use the <literal>--random</literal> command-line option
+ to tell &SCons; to build dependencies
+ in a random order:
+
+ </para>
+
+ <!--
+
+ The following <screen> output was generated by this:
+
+ <scons_output example="ex-random">
+ <scons_output_command>scons -Q - -random</scons_output_command>
+ </scons_output>
+
+ We captured it directly here to guarantee a "random" order,
+ guarding against the potential for - -random to happen
+ to return things in the original sorted order.
+
+ -->
+
+ <screen>
+ % <userinput>scons -Q --random</userinput>
+ cc -o f3.o -c f3.c
+ cc -o f1.o -c f1.c
+ cc -o f5.o -c f5.c
+ cc -o f2.o -c f2.c
+ cc -o f4.o -c f4.c
+ cc -o prog f1.o f2.o f3.o f4.o f5.o
+ </screen>
+
+ <para>
+
+ Multiple builds using the <literal>--random</literal> option
+ will usually build their dependencies in different,
+ random orders,
+ which minimizes the chances for a lot of
+ contention for same-named files
+ in the shared cache directory.
+ Multiple simultaneous builds might still race to try to build
+ the same target file on occasion,
+ but long sequences of inefficient contention
+ should be rare.
+
+ </para>
+
+ <para>
+
+ Note, of course,
+ the <literal>--random</literal> option
+ will cause the output that &SCons; prints
+ to be inconsistent from invocation to invocation,
+ which may be an issue when
+ trying to compare output from different build runs.
+
+ </para>
+
+ <para>
+
+ If you want to make sure dependencies will be built
+ in a random order without having to specify
+ the <literal>--random</literal> on very command line,
+ you can use the &SetOption; function to
+ set the <literal>random</literal> option
+ within any &SConscript; file:
+
+ </para>
+
+ <programlisting>
+ Program('prog',
+ ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c'])
+
+ SetOption('random', 1)
+ Program('prog',
+ ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c'])
+ </programlisting>
+
+ </section>
+
+ <!--
+
+ <section>
+ <title>Troubleshooting Shared Caching: the &cache-debug; Option</title>
+
+ <para>
+
+ XXX describe the - - cache-debug option
+ XXX maybe point to the troubleshooting appendix?
+
+ </para>
+
+ </section>
+
+ -->
+
+ <!--
+
+ <section>
+
+ <para>
+
+ XXX describe CacheDir management: monitoring, deleting, etc.
+
+ </para>
+
+ </section>
+
+ -->
<screen>
% <userinput>scons</userinput>
- \e[?1034hscons: Reading SConscript files ...
+ scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
... [build output] ...
scons: done building targets.
% <userinput>export SCONSFLAGS="-Q"</userinput>
% <userinput>scons</userinput>
- \e[?1034h ... [build output] ...
+ ... [build output] ...
</screen>
<para>
<screen>
% <userinput>scons -Q</userinput>
- \e[?1034hrunning with -j 2
+ running with -j 2
scons: `.' is up to date.
</screen>
<screen>
% <userinput>export NUM_CPU="4"</userinput>
% <userinput>scons -Q</userinput>
- \e[?1034hrunning with -j 4
+ running with -j 4
scons: `.' is up to date.
</screen>
<screen>
% <userinput>scons -Q -j 7</userinput>
- \e[?1034hrunning with -j 7
+ running with -j 7
scons: `.' is up to date.
% <userinput>export NUM_CPU="4"</userinput>
% <userinput>scons -Q -j 3</userinput>
- \e[?1034hrunning with -j 3
+ running with -j 3
scons: `.' is up to date.
</screen>
<screen>
% <userinput>scons -Q -n</userinput>
- \e[?1034hInstall file: "foo.in" as "/usr/bin/foo.in"
+ Install file: "foo.in" as "/usr/bin/foo.in"
</screen>
<para>
<screen>
% <userinput>scons -Q -n --prefix=/tmp/install</userinput>
- \e[?1034hInstall file: "foo.in" as "/tmp/install/usr/bin/foo.in"
+ Install file: "foo.in" as "/tmp/install/usr/bin/foo.in"
</screen>
</section>
<screen>
% <userinput>scons -Q debug=0</userinput>
- \e[?1034hcc -o prog.o -c prog.c
+ cc -o prog.o -c prog.c
cc -o prog prog.o
% <userinput>scons -Q debug=0</userinput>
- \e[?1034hscons: `.' is up to date.
+ scons: `.' is up to date.
% <userinput>scons -Q debug=1</userinput>
- \e[?1034hscons: `.' is up to date.
+ cc -o prog.o -c -g prog.c
+ cc -o prog prog.o
% <userinput>scons -Q debug=1</userinput>
- \e[?1034hscons: `.' is up to date.
+ scons: `.' is up to date.
</screen>
<para>
<screen>
% <userinput>scons -Q define=FOO</userinput>
- \e[?1034hcc -o prog.o -c -DFOO prog.c
+ cc -o prog.o -c -DFOO prog.c
% <userinput>scons -Q define=FOO define=BAR</userinput>
- \e[?1034hscons: `.' is up to date.
+ cc -o prog.o -c -DFOO -DBAR prog.c
</screen>
<para>
<screen>
% <userinput>scons -Q RELEASE=1</userinput>
- \e[?1034hcc -o bar.o -c -DRELEASE_BUILD=1 bar.c
+ cc -o bar.o -c -DRELEASE_BUILD=1 bar.c
cc -o foo.o -c -DRELEASE_BUILD=1 foo.c
cc -o foo foo.o bar.o
</screen>
<screen>
% <userinput>scons -Q -h</userinput>
- \e[?1034h
+
RELEASE: Set to 1 to build for release
default: 0
actual: 0
<screen>
% <userinput>scons -Q</userinput>
- \e[?1034hcc -o bar.o -c -DRELEASE_BUILD=1 bar.c
+ cc -o bar.o -c -DRELEASE_BUILD=1 bar.c
cc -o foo.o -c -DRELEASE_BUILD=1 foo.c
cc -o foo foo.o bar.o
</screen>
<screen>
% <userinput>scons -Q</userinput>
- \e[?1034hcc -o bar.o -c -DRELEASE_BUILD=0 bar.c
+ cc -o bar.o -c -DRELEASE_BUILD=0 bar.c
cc -o foo.o -c -DRELEASE_BUILD=0 foo.c
cc -o foo foo.o bar.o
</screen>
<screen>
% <userinput>scons -Q RELEASE=yes foo.o</userinput>
- \e[?1034hcc -o foo.o -c -DRELEASE_BUILD=True foo.c
+ cc -o foo.o -c -DRELEASE_BUILD=True foo.c
</screen>
<screen>
% <userinput>scons -Q RELEASE=t foo.o</userinput>
- \e[?1034hcc -o foo.o -c -DRELEASE_BUILD=True foo.c
+ cc -o foo.o -c -DRELEASE_BUILD=True foo.c
</screen>
<para>
<screen>
% <userinput>scons -Q RELEASE=no foo.o</userinput>
- \e[?1034hcc -o foo.o -c -DRELEASE_BUILD=False foo.c
+ cc -o foo.o -c -DRELEASE_BUILD=False foo.c
</screen>
<screen>
% <userinput>scons -Q RELEASE=f foo.o</userinput>
- \e[?1034hcc -o foo.o -c -DRELEASE_BUILD=False foo.c
+ cc -o foo.o -c -DRELEASE_BUILD=False foo.c
</screen>
<para>
scons: *** Error converting option: RELEASE
Invalid value for boolean option: bad_value
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Variables\__init__.py", line 214, in Update
- \e[?1034h
+ File "/home/my/project/SConstruct", line 4, in <module>
</screen>
</section>
<screen>
% <userinput>scons -Q COLOR=red foo.o</userinput>
- \e[?1034hcc -o foo.o -c -DCOLOR="red" foo.c
+ cc -o foo.o -c -DCOLOR="red" foo.c
% <userinput>scons -Q COLOR=blue foo.o</userinput>
- \e[?1034hscons: `foo.o' is up to date.
+ cc -o foo.o -c -DCOLOR="blue" foo.c
% <userinput>scons -Q COLOR=green foo.o</userinput>
- \e[?1034hscons: `foo.o' is up to date.
+ cc -o foo.o -c -DCOLOR="green" foo.c
</screen>
<para>
% <userinput>scons -Q COLOR=magenta foo.o</userinput>
scons: *** Invalid value for option COLOR: magenta
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Variables\EnumVariable.py", line 51, in _validator
- \e[?1034h
+ File "/home/my/project/SConstruct", line 5, in <module>
</screen>
<para>
<screen>
% <userinput>scons -Q COLOR=navy foo.o</userinput>
- \e[?1034hcc -o foo.o -c -DCOLOR="blue" foo.c
+ cc -o foo.o -c -DCOLOR="blue" foo.c
</screen>
<para>
% <userinput>scons -Q COLOR=Red foo.o</userinput>
scons: *** Invalid value for option COLOR: Red
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Variables\EnumVariable.py", line 51, in _validator
- \e[?1034h
+ File "/home/my/project/SConstruct", line 5, in <module>
% <userinput>scons -Q COLOR=BLUE foo.o</userinput>
scons: *** Invalid value for option COLOR: BLUE
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Variables\EnumVariable.py", line 51, in _validator
- \e[?1034h
+ File "/home/my/project/SConstruct", line 5, in <module>
% <userinput>scons -Q COLOR=nAvY foo.o</userinput>
scons: *** Invalid value for option COLOR: nAvY
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Variables\EnumVariable.py", line 51, in _validator
- \e[?1034h
+ File "/home/my/project/SConstruct", line 5, in <module>
</screen>
<para>
<screen>
% <userinput>scons -Q COLOR=Red foo.o</userinput>
- \e[?1034hcc -o foo.o -c -DCOLOR="Red" foo.c
+ cc -o foo.o -c -DCOLOR="Red" foo.c
% <userinput>scons -Q COLOR=BLUE foo.o</userinput>
- \e[?1034hscons: `foo.o' is up to date.
+ cc -o foo.o -c -DCOLOR="BLUE" foo.c
% <userinput>scons -Q COLOR=nAvY foo.o</userinput>
- \e[?1034hscons: `foo.o' is up to date.
+ cc -o foo.o -c -DCOLOR="blue" foo.c
% <userinput>scons -Q COLOR=green foo.o</userinput>
- \e[?1034hscons: `foo.o' is up to date.
+ cc -o foo.o -c -DCOLOR="green" foo.c
</screen>
<para>
<screen>
% <userinput>scons -Q COLOR=Red foo.o</userinput>
- \e[?1034hcc -o foo.o -c -DCOLOR="red" foo.c
+ cc -o foo.o -c -DCOLOR="red" foo.c
% <userinput>scons -Q COLOR=nAvY foo.o</userinput>
- \e[?1034hscons: `foo.o' is up to date.
+ cc -o foo.o -c -DCOLOR="blue" foo.c
% <userinput>scons -Q COLOR=GREEN foo.o</userinput>
- \e[?1034hscons: `foo.o' is up to date.
+ cc -o foo.o -c -DCOLOR="green" foo.c
</screen>
</section>
<screen>
% <userinput>scons -Q COLORS=red,blue foo.o</userinput>
- \e[?1034hcc -o foo.o -c -DCOLORS="red blue" foo.c
+ cc -o foo.o -c -DCOLORS="red blue" foo.c
% <userinput>scons -Q COLORS=blue,green,red foo.o</userinput>
- \e[?1034hscons: `foo.o' is up to date.
+ cc -o foo.o -c -DCOLORS="blue green red" foo.c
</screen>
<para>
<screen>
% <userinput>scons -Q COLORS=all foo.o</userinput>
- \e[?1034hcc -o foo.o -c -DCOLORS="red green blue" foo.c
+ cc -o foo.o -c -DCOLORS="red green blue" foo.c
% <userinput>scons -Q COLORS=none foo.o</userinput>
- \e[?1034hscons: `foo.o' is up to date.
+ cc -o foo.o -c -DCOLORS="" foo.c
</screen>
<para>
scons: *** Error converting option: COLORS
Invalid value(s) for option: magenta
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Variables\__init__.py", line 214, in Update
- \e[?1034h
+ File "/home/my/project/SConstruct", line 5, in <module>
</screen>
</section>
<screen>
% <userinput>scons -Q foo.o</userinput>
- \e[?1034hcc -o foo.o -c -DCONFIG_FILE="/etc/my_config" foo.c
+ cc -o foo.o -c -DCONFIG_FILE="/etc/my_config" foo.c
% <userinput>scons -Q CONFIG=/usr/local/etc/other_config foo.o</userinput>
- \e[?1034hscons: `foo.o' is up to date.
+ scons: `foo.o' is up to date.
</screen>
<para>
% <userinput>scons -Q CONFIG=/does/not/exist foo.o</userinput>
scons: *** Path for option CONFIG does not exist: /does/not/exist
- File "p:\cyghome\bdeegan\scons\trunk\bootstrap\src\engine\SCons\Variables\PathVariable.py", line 117, in PathExists
- \e[?1034h
+ File "/home/my/project/SConstruct", line 6, in <module>
</screen>
<para>
<screen>
% <userinput>scons -Q foo.o</userinput>
- \e[?1034hcc -o foo.o -c -DPACKAGE="/opt/location" foo.c
+ cc -o foo.o -c -DPACKAGE="/opt/location" foo.c
% <userinput>scons -Q PACKAGE=/usr/local/location foo.o</userinput>
- \e[?1034hscons: `foo.o' is up to date.
+ cc -o foo.o -c -DPACKAGE="/usr/local/location" foo.c
% <userinput>scons -Q PACKAGE=yes foo.o</userinput>
- \e[?1034hscons: `foo.o' is up to date.
+ cc -o foo.o -c -DPACKAGE="True" foo.c
% <userinput>scons -Q PACKAGE=no foo.o</userinput>
- \e[?1034hscons: `foo.o' is up to date.
+ cc -o foo.o -c -DPACKAGE="False" foo.c
</screen>
</section>
<screen>
% <userinput>scons -Q NOT_KNOWN=foo</userinput>
- \e[?1034hUnknown variables: ['NOT_KNOWN']
+ Unknown variables: ['NOT_KNOWN']
</screen>
<para>
<screen>
% <userinput>scons -Q</userinput>
- \e[?1034hcc -o foo.o -c foo.c
+ cc -o foo.o -c foo.c
cc -o foo foo.o
% <userinput>scons -Q bar</userinput>
- \e[?1034hDon't forget to copy `bar' to the archive!
+ Don't forget to copy `bar' to the archive!
cc -o bar.o -c bar.c
cc -o bar bar.o
</screen>
<screen>
% <userinput>scons -Q</userinput>
- \e[?1034hcc -o hello.o -c hello.c
+ cc -o hello.o -c hello.c
cc -o hello hello.o
% <userinput>scons -Q</userinput>
- \e[?1034hscons: `hello' is up to date.
+ scons: `hello' is up to date.
% <userinput>scons -Q goodbye</userinput>
- \e[?1034hcc -o goodbye.o -c goodbye.c
+ cc -o goodbye.o -c goodbye.c
cc -o goodbye goodbye.o
</screen>
<screen>
% <userinput>scons -Q .</userinput>
- \e[?1034hcc -o goodbye.o -c goodbye.c
+ cc -o goodbye.o -c goodbye.c
cc -o goodbye goodbye.o
cc -o hello.o -c hello.c
cc -o hello hello.o
<screen>
% <userinput>scons -Q</userinput>
- \e[?1034hcc -o prog1.o -c prog1.c
+ cc -o prog1.o -c prog1.c
cc -o prog1 prog1.o
cc -o prog3.o -c prog3.c
cc -o prog3 prog3.o
% <userinput>scons -Q .</userinput>
- \e[?1034hcc -o prog2.o -c prog2.c
+ cc -o prog2.o -c prog2.c
cc -o prog2 prog2.o
</screen>
<screen>
% <userinput>scons -Q</userinput>
- \e[?1034hcc -o prog1/foo.o -c prog1/foo.c
+ cc -o prog1/foo.o -c prog1/foo.c
cc -o prog1/main.o -c prog1/main.c
cc -o prog1/main prog1/main.o prog1/foo.o
% <userinput>scons -Q</userinput>
- \e[?1034hscons: `prog1' is up to date.
+ scons: `prog1' is up to date.
% <userinput>scons -Q .</userinput>
- \e[?1034hcc -o prog2/bar.o -c prog2/bar.c
+ cc -o prog2/bar.o -c prog2/bar.c
cc -o prog2/main.o -c prog2/main.c
cc -o prog2/main prog2/main.o prog2/bar.o
</screen>
<screen>
% <userinput>scons -Q</userinput>
scons: *** No targets specified and no Default() targets found. Stop.
- \e[?1034h
% <userinput>scons -Q .</userinput>
- \e[?1034hcc -o prog1.o -c prog1.c
+ cc -o prog1.o -c prog1.c
cc -o prog1 prog1.o
cc -o prog2.o -c prog2.c
cc -o prog2 prog2.o
<screen>
% <userinput>scons</userinput>
- \e[?1034hscons: Reading SConscript files ...
+ scons: Reading SConscript files ...
DEFAULT_TARGETS is ['prog1']
scons: done reading SConscript files.
scons: Building targets ...
<screen>
% <userinput>scons</userinput>
- \e[?1034hscons: Reading SConscript files ...
+ scons: Reading SConscript files ...
DEFAULT_TARGETS is now ['prog1']
DEFAULT_TARGETS is now ['prog1', 'prog2']
scons: done reading SConscript files.
<screen>
% <userinput>scons -Q</userinput>
- \e[?1034hBUILD_TARGETS is ['prog1']
+ BUILD_TARGETS is ['prog1']
cc -o prog1.o -c prog1.c
cc -o prog1 prog1.o
% <userinput>scons -Q prog2</userinput>
- \e[?1034hBUILD_TARGETS is ['prog2']
+ BUILD_TARGETS is ['prog2']
cc -o prog2.o -c prog2.c
cc -o prog2 prog2.o
% <userinput>scons -Q -c .</userinput>
- \e[?1034hBUILD_TARGETS is ['.']
+ BUILD_TARGETS is ['.']
Removed prog1.o
Removed prog1
Removed prog2.o
% <userinput>touch -t 198901010000 hello.c</userinput>
% <userinput>scons -Q hello.o</userinput>
cc -o hello.o -c hello.c
- cc -o hello hello.o
</screen>
<para>
<screen>
C:\><userinput>scons -Q hello.exe</userinput>
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
cl /Fohello.obj /c hello.c /nologo /Iinclude /I\home\project\inc
link /nologo /OUT:hello.exe hello.obj
</screen>
<screen>
% <userinput>scons -Q hello</userinput>
cc -o version.o -c version.c
- cc -o version.o -c version.c
cc -o hello.o -c hello.c
+ cc -o hello version.o hello.o
+ % <userinput>sleep 1</userinput>
+ % <userinput>scons -Q hello</userinput>
+ cc -o version.o -c version.c
scons: `hello' is up to date.
% <userinput>sleep 1</userinput>
% <userinput>edit hello.c</userinput>
[CHANGE THE CONTENTS OF hello.c]
% <userinput>scons -Q hello</userinput>
cc -o version.o -c version.c
- cc -o version.o -c version.c
cc -o hello.o -c hello.c
cc -o hello version.o hello.o
% <userinput>sleep 1</userinput>
<screen>
C:\><userinput>scons -Q</userinput>
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
key = OBJSUFFIX, value = .obj
key = LIBSUFFIX, value = .lib
key = PROGSUFFIX, value = .exe
<screen>
% <userinput>scons -Q</userinput>
- scons: warning: Two different environments were specified for target foo.o,
- but they appear to have the same action: CCCom(target, source, env)
- File "/home/my/project/SConstruct", line 6, in ?
-
- scons: warning: Two different environments were specified for target foo,
- but they appear to have the same action: Cat(target, source, env)
- File "/home/my/project/SConstruct", line 6, in ?
- cc -o foo.o -c -g foo.c
- cc -o foo foo.o
+ scons: *** Two environments with different actions were specified for the same target: foo.o
+ File "/home/my/project/SConstruct", line 6, in <module>
</screen>
<para>
<screen>
C:\><userinput>scons -Q</userinput>
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
cl /Fohello.obj /c hello.c /nologo
link /nologo /OUT:new_hello.exe hello.obj
</screen>
<screen>
C:\><userinput>scons -Q</userinput>
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
cl /Fofile1.obj /c file1.c /nologo
cl /Fofile2.obj /c file2.c /nologo
cl /Foprog.obj /c prog.c /nologo
<screen>
C:\><userinput>scons -Q</userinput>
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
cl /Fof1.obj /c f1.c /nologo
cl /Fof2.obj /c f2.c /nologo
cl /Fof3.obj /c f3.c /nologo
<screen>
C:\><userinput>scons -Q</userinput>
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
cl /Fof1.obj /c f1.c /nologo
cl /Fof2.obj /c f2.c /nologo
cl /Fof3.obj /c f3.c /nologo
<screen>
C:\><userinput>scons -Q</userinput>
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
cl /Fof1.obj /c f1.c /nologo
cl /Fof2.obj /c f2.c /nologo
cl /Fof3.obj /c f3.c /nologo
<screen>
C:\><userinput>scons -Q</userinput>
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
cl /Foprog.obj /c prog.c /nologo
link /nologo /OUT:prog.exe /LIBPATH:\usr\lib /LIBPATH:\usr\local\lib m.lib prog.obj
</screen>
<screen>
C:\><userinput>scons -Q</userinput>
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
cl /Fogoodbye.obj /c goodbye.c -DGOODBYE
cl /Fohello.obj /c hello.c -DHELLO
link /nologo /OUT:hello.exe hello.obj goodbye.obj
<screen>
C:\><userinput>scons -Q</userinput>
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
The object file is: hello.obj
The program file is: hello.exe
cl /Fohello.obj /c hello.c /nologo
<screen>
C:\><userinput>scons -h</userinput>
scons: Reading SConscript files ...
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
scons: done reading SConscript files.
Type: 'scons program' to build the production program.
<screen>
% <userinput>scons -Q</userinput>
- Package x11 was not found in the pkg-config search path.
- Perhaps you should add the directory containing `x11.pc'
- to the PKG_CONFIG_PATH environment variable
- No package 'x11' found
- OSError: 'pkg-config x11 --cflags --libs' exited 1:
- File "/home/my/project/SConstruct", line 3:
- env.ParseConfig("pkg-config x11 --cflags --libs")
- File "bootstrap/src/engine/SCons/Environment.py", line 1474:
- None
- File "bootstrap/src/engine/SCons/Environment.py", line 593:
- None
+ ['/lib/compat', '/usr/X11/include']
+ scons: `.' is up to date.
</screen>
<para>
<screen>
% <userinput>scons -Q</userinput>
- Package x11 was not found in the pkg-config search path.
- Perhaps you should add the directory containing `x11.pc'
- to the PKG_CONFIG_PATH environment variable
- No package 'x11' found
- OSError: 'pkg-config x11 --cflags --libs' exited 1:
- File "/home/my/project/SConstruct", line 2:
- env.ParseConfig("pkg-config x11 --cflags --libs")
- File "bootstrap/src/engine/SCons/Environment.py", line 1474:
- None
- File "bootstrap/src/engine/SCons/Environment.py", line 593:
- None
+ ['/usr/X11/include']
+ scons: `.' is up to date.
</screen>
<screen>
C:\><userinput>scons -Q</userinput>
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
CPPPATH ['/opt/include']
LIBPATH ['/opt/lib']
LIBS ['foo']
<screen>
C:\><userinput>scons</userinput>
scons: Reading SConscript files ...
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
scons: done reading SConscript files.
scons: Building targets ...
cl /Fohello.obj /c hello.c /nologo
<screen>
C:\><userinput>scons</userinput>
scons: Reading SConscript files ...
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
scons: done reading SConscript files.
scons: Building targets ...
cl /Fohello.obj /c hello.c /nologo
<screen>
C:\><userinput>scons</userinput>
scons: Reading SConscript files ...
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
scons: done reading SConscript files.
scons: Building targets ...
cl /Fohello.obj /c hello.c /nologo
scons: done building targets.
C:\><userinput>scons -c</userinput>
scons: Reading SConscript files ...
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed hello.obj
<screen>
C:\><userinput>scons</userinput>
scons: Reading SConscript files ...
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
scons: done reading SConscript files.
scons: Building targets ...
cl /Fohello.obj /c hello.c /nologo
<screen>
C:\><userinput>scons -Q</userinput>
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
cl /Fohello.obj /c hello.c /nologo
link /nologo /OUT:hello.exe hello.obj
</screen>
'DSUFFIXES': ['.d'],
'Dir': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>,
'Dirs': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>,
- 'ENV': {'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'},
+ 'ENV': { 'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'},
'ESCAPE': <function escape at 0x700000>,
'File': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>,
'HOST_ARCH': None,
<screen>
C:\><userinput>scons</userinput>
scons: Reading SConscript files ...
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
{ 'BUILDERS': {'_InternalInstall': <function InstallBuilderWrapper at 0x700000>, 'Object': <SCons.Builder.CompositeBuilder instance at 0x700000>, 'PCH': <SCons.Builder.BuilderBase instance at 0x700000>, 'RES': <SCons.Builder.BuilderBase instance at 0x700000>, 'SharedObject': <SCons.Builder.CompositeBuilder instance at 0x700000>, 'StaticObject': <SCons.Builder.CompositeBuilder instance at 0x700000>, '_InternalInstallAs': <function InstallAsBuilderWrapper at 0x700000>},
'CC': 'cl',
'CCCOM': <SCons.Action.FunctionAction instance at 0x700000>,
'DSUFFIXES': ['.d'],
'Dir': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>,
'Dirs': <SCons.Defaults.Variable_Method_Caller instance at 0x700000>,
- 'ENV': { 'PATH': 'C:/WINDOWS\\System32',
+ 'ENV': { 'PATH': 'C:\\WINDOWS\\System32',
'PATHEXT': '.COM;.EXE;.BAT;.CMD',
'SystemRoot': 'C:\\WINDOWS'},
'ESCAPE': <function escape at 0x700000>,
<screen>
% <userinput>scons</userinput>
scons: Reading SConscript files ...
- {'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'}
+ { 'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'}
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
<screen>
C:\><userinput>scons</userinput>
scons: Reading SConscript files ...
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
- { 'PATH': 'C:/WINDOWS\\System32',
+ { 'PATH': 'C:\\WINDOWS\\System32',
'PATHEXT': '.COM;.EXE;.BAT;.CMD',
'SystemRoot': 'C:\\WINDOWS'}
scons: done reading SConscript files.
File "bootstrap/src/engine/SCons/Job.py", line 197, in start
task.prepare()
File "bootstrap/src/engine/SCons/Script/Main.py", line 167, in prepare
+ return SCons.Taskmaster.OutOfDateTask.prepare(self)
File "bootstrap/src/engine/SCons/Taskmaster.py", line 190, in prepare
+ executor.prepare()
File "bootstrap/src/engine/SCons/Executor.py", line 397, in prepare
+ raise SCons.Errors.StopError, msg % (s, self.batches[0].targets[0])
</screen>
<para>
<screen>
C:\><userinput>scons -Q OS=windows</userinput>
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
-
- scons: warning: No installed VCs
- File "<stdin>", line 67, in __call__
-
- scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
- File "<stdin>", line 67, in __call__
Install file: "build/windows/world/world.h" as "export/windows/include/world.h"
cl /Fobuild\windows\hello\hello.obj /c build\windows\hello\hello.c /nologo /Iexport\windows\include
cl /Fobuild\windows\world\world.obj /c build\windows\world\world.c /nologo /Iexport\windows\include