-- Distribute the change to scons-aedist:
- aedist -s -p scons.0.92 {cnum} > scons.0.92.C{cnum}.ae
- pine -attach scons.0.92.C{cnum}.ae scons-aedist@lists.sourceforge.net
- Subject: scons.0.92 - {SUMMARY}
- Body: aegis -l -p scons.0.92 -c {cnum} cd
+ aedist -s -p scons.0.93 {cnum} > scons.0.93.C{cnum}.ae
+ pine -attach scons.0.93.C{cnum}.ae scons-aedist@lists.sourceforge.net
+ Subject: scons.0.93 - {SUMMARY}
+ Body: aegis -l -p scons.0.93 -c {cnum} cd
- rm scons.0.92.C{cnum}.ae
+ rm scons.0.93.C{cnum}.ae
[This will eventually be automated.]
-- Update the aedist baseline on the web site:
- aedist -s -bl -p scons.0.92 > scons.0.92.ae
- scp scons.0.92.ae stevenknight@scons.sourceforge.net:/home/groups/s/sc/scons/htdocs/scons.0.92.ae
- rm scons.0.92.ae
+ aedist -s -bl -p scons.0.93 > scons.0.93.ae
+ scp scons.0.93.ae stevenknight@scons.sourceforge.net:/home/groups/s/sc/scons/htdocs/scons.0.93.ae
+ rm scons.0.93.ae
[This will eventually be automated.]
-- Distribute the change to CVS:
export CVS_RSH=ssh
- ae2cvs -n -aegis -p scons.0.92 -c {cnum} -u ~/SCons/scons
- ae2cvs -X -aegis -p scons.0.92 -c {cnum} -u ~/SCons/scons
+ ae2cvs -n -aegis -p scons.0.93 -c {cnum} -u ~/SCons/scons
+ ae2cvs -X -aegis -p scons.0.93 -c {cnum} -u ~/SCons/scons
If you need the "ae2cvs" Perl script, you can find a copy
checked in to the bin/subdirectory.
ae_p scons.0
- aede {92}
+ aede {93}
- aerpass {92}
+ aerpass {93}
- aeib {92}
+ aeib {93}
aeb
START THE NEW BRANCH FOR RELEASE
- aenbr -p scons.0 {93}
+ aenbr -p scons.0 {94}
- aenc -p scons.0.{93}
+ aenc -p scons.0.{94}
Call it something like,
"Initialize the new branch for release."
Cause = internal_enhancement.
Exempt it from all tests (*_exempt = true).
- ae_p scons.0.{93}
+ ae_p scons.0.{94}
aedb 100
<your email>
cd incoming
bin
- put scons-0.{93}-1.noarch.rpm
- put scons-0.{93}-1.src.rpm
- put scons-0.{93}.tar.gz
- put scons-0.{93}.win32.exe
- put scons-0.{93}.zip
- put scons-local-0.{93}.tar.gz
- put scons-local-0.{93}.zip
- put scons-src-0.{93}.tar.gz
- put scons-src-0.{93}.zip
- put scons_0.{93}-1_all.deb
+ put scons-0.{94}-1.noarch.rpm
+ put scons-0.{94}-1.src.rpm
+ put scons-0.{94}.tar.gz
+ put scons-0.{94}.win32.exe
+ put scons-0.{94}.zip
+ put scons-local-0.{94}.tar.gz
+ put scons-local-0.{94}.zip
+ put scons-src-0.{94}.tar.gz
+ put scons-src-0.{94}.zip
+ put scons_0.{94}-1_all.deb
Create the new release at the SourceForge project page:
=> Add Release
- New release name: 0.{93}
+ New release name: 0.{94}
Cut-and-paste or upload the RELEASE.txt file.
Edit the file info:
- scons-0.{93}-1.noarch.rpm Any .rpm
- scons-0.{93}-1.src.rpm Any Source .rpm
- scons-0.{93}.tar.gz Any .gz
- scons-0.{93}.win32.exe i386 .exe (32-bit Windows)
- scons-0.{93}.zip Any .zip
- scons_0.{93}-1_all.deb Any .deb
+ scons-0.{94}-1.noarch.rpm Any .rpm
+ scons-0.{94}-1.src.rpm Any Source .rpm
+ scons-0.{94}.tar.gz Any .gz
+ scons-0.{94}.win32.exe i386 .exe (32-bit Windows)
+ scons-0.{94}.zip Any .zip
+ scons_0.{94}-1_all.deb Any .deb
Click "Update/Refresh" for each file; this must be done
one at a time.
=> Add Release
- New release name: 0.{93}
+ New release name: 0.{94}
Cut-and-paste or upload the RELEASE.txt file.
Edit the file info:
- scons-local-0.{93}.tar.gz Any .gz
- scons-local-0.{93}.zip Any .zip
+ scons-local-0.{94}.tar.gz Any .gz
+ scons-local-0.{94}.zip Any .zip
Click "Update/Refresh" for each file; this must be done
one at a time.
=> Add Release
- New release name: 0.{93}
+ New release name: 0.{94}
Cut-and-paste or upload the RELEASE.txt file.
Edit the file info:
- scons-src-0.{93}.tar.gz Any .gz
- scons-src-0.{93}.zip Any .zip
+ scons-src-0.{94}.tar.gz Any .gz
+ scons-src-0.{94}.zip Any .zip
Click "Update/Refresh" for each file; this must be done
one at a time.
Release Notice section.
- Hide release {0.90} at the SourceForge download page:
+ Hide release 0.{92} at the SourceForge download page:
Go to the Admin page
=> Edit Releases
- Release Name: {0.90}
+ Release Name: 0.{92}
=> Edit This Release
=> Edit Releases
- Release Name: {0.90}
+ Release Name: 0.{92}
=> Edit This Release
=> Edit Releases
- Release Name: {0.90}
+ Release Name: 0.{92}
=> Edit This Release
- In the Bugs Tracker, add a Group for the new release {0.92}
+ In the Bugs Tracker, add a Group for the new release 0.{92}
nctl = filter(lambda x: x[0] != '#', nbtl)
ncsl = filter(lambda x: x[0] != '#', nbsl)
+def ratio(over, under):
+ return "%.2f" % (float(len(over)) / float(len(under)))
+
+rfiles = ratio(tests, sources)
+rlines = ratio(tlines, slines)
+rnonblank = ratio(nbtl, nbsl)
+rnoncomment = ratio(nctl, ncsl)
+
fmt = "%-8s %12s %12s %12s %12s"
print fmt % ('', 'files', 'lines', 'non-blank', 'non-comment')
print fmt % ('tests:', len(tests), len(tlines), len(nbtl), len(nctl))
print fmt % ('sources:', len(sources), len(slines), len(nbsl), len(ncsl))
+print fmt % ('ratio:', rfiles, rlines, rnonblank, rnoncomment)
orig_env.Install(build, s)
else:
orig_env.SCons_revision(os.path.join(build, s), s)
+ Local(os.path.join(build, s))
#
# For each document, build the document itself in HTML, Postscript,
else:
orig_env.SCons_revision(os.path.join(build, doc, s),
os.path.join(doc, s))
+ Local(os.path.join(build, doc, s))
main = os.path.join(build, doc, 'main.sgml')
out = 'main.out'
</para>
<scons_output example="ex1" os="posix">
- <command>scons install</command>
+ <command>scons -Q install</command>
</scons_output>
<para>
</para>
<scons_output example="ex2" os="posix">
- <command>scons install-bin</command>
- <command>scons install-lib</command>
- <command>scons -c __ROOT__/</command>
- <command>scons install</command>
+ <command>scons -Q install-bin</command>
+ <command>scons -Q install-lib</command>
+ <command>scons -Q -c __ROOT__/</command>
+ <command>scons -Q install</command>
</scons_output>
</para>
<literallayout>
- % <userinput>scons install</userinput>
+ % <userinput>scons -Q install</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
Install file: "hello" as "/usr/bin/hello"
</literallayout>
<programlisting>
env = Environment()
- p = env.Program('hello.c')
- l = env.Library('hello.c')
+ p = env.Program('foo.c')
+ l = env.Library('bar.c')
env.Install('/usr/bin', p)
env.Install('/usr/lib', l)
ib = env.Alias('install-bin', '/usr/bin')
</para>
<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"
+ % <userinput>scons -Q install-bin</userinput>
+ cc -c -o foo.o foo.c
+ cc -o foo foo.o
+ Install file: "foo" as "/usr/bin/foo"
+ % <userinput>scons -Q install-lib</userinput>
+ cc -c -o bar.o bar.c
+ ar r libbar.a bar.o
+ ranlib libbar.a
+ Install file: "libbar.a" as "/usr/lib/libbar.a"
+ % <userinput>scons -Q -c /</userinput>
+ 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>
+ cc -c -o foo.o foo.c
+ cc -o foo foo.o
+ Install file: "foo" as "/usr/bin/foo"
+ cc -c -o bar.o bar.c
+ ar r libbar.a bar.o
+ ranlib libbar.a
+ Install file: "libbar.a" as "/usr/lib/libbar.a"
</literallayout>
This section will describe all of the different
types of files that you can build with &SCons;,
and the built-in &Builder; objects used to build them.
+ By default, all of the &Builder; objects in this section
+ can be built either with or without an explicit
+ construction environment.
</para>
</para>
<programlisting>
- env = Environment()
- env.Program('prog', 'file1.o')
+ Program('prog', 'file1.o')
</programlisting>
<para>
If you omit the ⌖,
the base of the first input
file name specified
- because the base of the target
+ becomes the base of the target
program created.
For example:
</para>
<programlisting>
- env = Environment()
- env.Program(['hello.c', 'goodbye.c'])
+ Program(['hello.c', 'goodbye.c'])
</programlisting>
<para>
</para>
+ <para>
+
+ Two construction variables control what libraries
+ will be linked with the resulting program.
+ The &LIBS; variable is a list of the names of
+ libraries that will be linked into any programs,
+ and the &LIBPATH; variables is a list of
+ directories that will be searched for
+ the specified libraries.
+ &SCons; will construct the right command-line
+ options for the running system.
+ For example:
+
+ </para>
+
+ <scons_example name="libs">
+ <file name="SConstruct" printme="1">
+ env = Environment(LIBS = ['foo1', 'foo2'],
+ LIBPATH = ['/usr/dir1', 'dir2'])
+ env.Program(['hello.c', 'goodbye.c'])
+ </file>
+ <file name="hello.c">
+ int hello() { printf("Hello, world!\n"); }
+ </file>
+ <file name="goodbye.c">
+ int goodbye() { printf("Goodbye, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ Will execute as follows on a POSIX system:
+
+ </para>
+
+ <scons_output example="libs" os="posix">
+ <command>scons -Q</command>
+ </scons_output>
+
+ <para>
+
+ And execute as follows on a Windows system:
+
+ </para>
+
+ <scons_output example="libs" os="win32">
+ <command>scons -Q</command>
+ </scons_output>
+
+ <para>
+
+ The &LIBS; construction variable
+ is turned into command line options
+ by appending the &LIBLINKPREFIX; and &LIBLINKSUFFIX;
+ construction variables to the beginning and end,
+ respectively, of each specified library.
+
+ </para>
+
+ <para>
+
+ The &LIBPATH; construction variable
+ is turned into command line options
+ by appending the &LIBDIRPREFIX; and &LIBDIRSUFFIX;
+ construction variables to the beginning and end,
+ respectively, of each specified library.
+
+ </para>
+
+ <para>
+
+ Other relevant construction variables
+ include those used by the &Object;
+ builders to affect how the
+ source files specified as input to the &Program;
+ builders are turned into object files;
+ see the next section.
+
+ </para>
+
+ <para>
+
+ The command line used to control how a program is linked
+ is specified by the &LINKCOM; construction variable.
+ By default, it uses the
+ &LINK; construction variable
+ and the &LINKFLAGS; construction variable.
+
+ </para>
+
</section>
<section>
<para>
&SCons; provides separate Builder objects
- to create both static and shared object files.
+ to create static and shared object files.
+ The distinction becomes especially important when
+ archiving object files into different types of libraries.
</para>
<para>
- XXX
+ The &StaticObject; Builder
+ is used to build an object file
+ suitable for static linking into a program,
+ or for inclusion in a static library.
+ The &source; argument is a single source-code file,
+ and the ⌖ argument is the
+ name of the static object file to be created.
+ For example:
</para>
<programlisting>
- XXX
+ StaticObject('file', 'file.c')
</programlisting>
+ <para>
+
+ Will create the &file_o;
+ object file on a POSIX system,
+ the &file_obj; executable on a Windows system.
+
+ </para>
+
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ $OBJPREFIX
+ and
+ $OBJSUFFIX
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(OBJPREFIX='my', OBJSUFFIX='.xxx')
+ env.StaticObject('file', 'file.c')
+ </programlisting>
+
+ <para>
+
+ Will create an object file named
+ <filename>myfile.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <para>
+
+ If you omit the ⌖,
+ the base of the first input
+ file name specified
+ beomces the base of the name
+ of the static object file to be created.
+ For example:
+
+ </para>
+
<literallayout>
- XXX
+ StaticObject('file.c')
</literallayout>
+ <para>
+
+ Will create the &file_o;
+ executable on a POSIX system,
+ the &file_obj; executable on a Windows system.
+
+ </para>
+
</section>
<section>
<para>
- XXX
+ The &SharedObject; Builder
+ is used to build an object file
+ suitable for shared linking into a program,
+ or for inclusion in a shared library.
+ The &source; argument is a single source-code file,
+ and the ⌖ argument is the
+ name of the shared object file to be created.
+ For example:
</para>
<programlisting>
- XXX
+ SharedObject('file', 'file.c')
</programlisting>
- <literallayout>
- XXX
- </literallayout>
+ <para>
- </section>
+ Will create the &file_o;
+ object file on a POSIX system,
+ the &file_obj; executable on a Windows system.
- <section>
- <title>The &Object; Builder</title>
+ </para>
<para>
- XXX
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ $SHOBJPREFIX
+ and
+ $SHOBJSUFFIX
+ construction variables
+ will be appended appropriately.
+ For example:
</para>
<programlisting>
- XXX
+ env = Environment(SHOBJPREFIX='my', SHOBJSUFFIX='.xxx')
+ env.SharedObject('file', 'file.c')
</programlisting>
<para>
- Creates a static object file.
+ Will create an object file named
+ <filename>myfile.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <para>
+
+ If you omit the ⌖,
+ the base of the first input
+ file name specified
+ becomes the base of the name
+ of the shared object file to be created.
+ For example:
+
+ </para>
+
+ <literallayout>
+ SharedObject('file.c')
+ </literallayout>
+
+ <para>
+
+ Will create the &file_o;
+ executable on a POSIX system,
+ the &file_obj; executable on a Windows system.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &Object; Builder</title>
+
+ <para>
+
+ The &Object; Builder is a synonym for &StaticObject;
+ and is completely equivalent.
</para>
<para>
&SCons; provides separate Builder objects
- to create both static and shared libraries.
+ to create static and shared libraries.
</para>
<para>
- XXX
+ The &StaticLibrary; Builder
+ is used to create a library
+ suitable for static linking into a program.
+ The &source; argument is one or more
+ source-code files or object files,
+ and the ⌖ argument is the
+ name of the static library to be created.
+ For example:
</para>
<programlisting>
- XXX
+ StaticLibrary('foo', ['file1.c', 'file2.c'])
</programlisting>
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ $LIBPREFIX
+ and
+ $LIBSUFFIX
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(LIBPREFIX='my', LIBSUFFIX='.xxx')
+ env.StaticLibrary('lib', ['file1.o', 'file2.o'])
+ </programlisting>
+
+ <para>
+
+ Will create an object file named
+ <filename>mylib.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <programlisting>
+ StaticLibrary('foo', ['file1.c', 'file2.c'])
+ </programlisting>
+
+ <para>
+
+ If you omit the ⌖,
+ the base of the first input
+ file name specified
+ becomes the base of the name of the static object file to be created.
+ For example:
+
+ </para>
+
<literallayout>
- XXX
+ StaticLibrary(['file.c', 'another.c'])
</literallayout>
+ <para>
+
+ Will create the &libfile_a;
+ library on a POSIX system,
+ the &file_lib; library on a Windows system.
+
+ </para>
+
</section>
<section>
<para>
- XXX
+ The &SharedLibrary; Builder
+ is used to create a shared library
+ suitable for linking with a program.
+ The &source; argument is one or more
+ source-code files or object files,
+ and the ⌖ argument is the
+ name of the shared library to be created.
+ For example:
</para>
- </section>
+ <programlisting>
+ SharedLibrary('foo', ['file1.c', 'file2.c'])
+ </programlisting>
- <section>
- <title>The &Library; Builder</title>
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ $SHLIBPREFIX
+ and
+ $SHLIBSUFFIX
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(SHLIBPREFIX='my', SHLIBSUFFIX='.xxx')
+ env.SharedLibrary('shared', ['file1.o', 'file2.o'])
+ </programlisting>
<para>
- XXX
+ Will create an object file named
+ <filename>myshared.xxx</filename>
+ regardless of the system on which it is run.
</para>
<programlisting>
- XXX
+ SharedLibrary('foo', ['file1.c', 'file2.c'])
</programlisting>
+ <para>
+
+ If you omit the ⌖,
+ the base of the first input
+ file name specified
+ becomes the base of the name of the shared library to be created.
+ For example:
+
+ </para>
+
<literallayout>
- XXX
+ SharedLibrary(['file.c', 'another.c'])
</literallayout>
<para>
- Creates a static library file.
+ Will create the &libfile_so;
+ library on a POSIX system,
+ the &file_dll; library on a Windows system.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &Library; Builder</title>
+
+ <para>
+
+ The &Library; Builder is a synonym for &StaticLibrary;
+ and is completely equivalent.
</para>
&SCons; supports two Builder objects
that know how to build source files
from other input files.
+ These are typically invoked "internally"
+ to turn files that need preprocessing into other source files.
</para>
</scons_example>
<scons_output example="ex1" os="posix">
- <command>scons .</command>
+ <command>scons -Q .</command>
</scons_output>
<para>
</scons_example>
<scons_output example="ex2" os="posix">
- <command>scons .</command>
+ <command>scons -Q .</command>
</scons_output>
<para>
</scons_example>
<scons_output example="ex3" os="posix">
- <command>scons .</command>
+ <command>scons -Q .</command>
</scons_output>
</section>
</para>
<scons_output example="ex4" os="posix">
- <command>scons .</command>
+ <command>scons -Q .</command>
</scons_output>
<para>
</para>
<literallayout>
- % <userinput>scons .</userinput>
+ % <userinput>scons -Q .</userinput>
zip /home/my/project/zip.out file1 file2
</literallayout>
This section will describe all of the different
types of files that you can build with &SCons;,
and the built-in &Builder; objects used to build them.
+ By default, all of the &Builder; objects in this section
+ can be built either with or without an explicit
+ construction environment.
</para>
</para>
<programlisting>
- env = Environment()
- env.Program('prog', 'file1.o')
+ Program('prog', 'file1.o')
</programlisting>
<para>
If you omit the ⌖,
the base of the first input
file name specified
- because the base of the target
+ becomes the base of the target
program created.
For example:
</para>
<programlisting>
- env = Environment()
- env.Program(['hello.c', 'goodbye.c'])
+ Program(['hello.c', 'goodbye.c'])
</programlisting>
<para>
</para>
+ <para>
+
+ Two construction variables control what libraries
+ will be linked with the resulting program.
+ The &LIBS; variable is a list of the names of
+ libraries that will be linked into any programs,
+ and the &LIBPATH; variables is a list of
+ directories that will be searched for
+ the specified libraries.
+ &SCons; will construct the right command-line
+ options for the running system.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(LIBS = ['foo1', 'foo2'],
+ LIBPATH = ['/usr/dir1', 'dir2'])
+ env.Program(['hello.c', 'goodbye.c'])
+ </programlisting>
+
+ <para>
+
+ Will execute as follows on a POSIX system:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons -Q</userinput>
+ cc -c -o goodbye.o goodbye.c
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o goodbye.o -L/usr/dir1 -Ldir2 -lfoo1 -lfoo2
+ </literallayout>
+
+ <para>
+
+ And execute as follows on a Windows system:
+
+ </para>
+
+ <literallayout>
+ C:\><userinput>scons -Q</userinput>
+ cl /nologo /c goodbye.c /Fogoodbye.obj
+ cl /nologo /c hello.c /Fohello.obj
+ link /nologo /OUT:hello.exe /LIBPATH:\usr\dir1 /LIBPATH:dir2 foo1.lib foo2.lib hello.obj goodbye.obj
+ </literallayout>
+
+ <para>
+
+ The &LIBS; construction variable
+ is turned into command line options
+ by appending the &LIBLINKPREFIX; and &LIBLINKSUFFIX;
+ construction variables to the beginning and end,
+ respectively, of each specified library.
+
+ </para>
+
+ <para>
+
+ The &LIBPATH; construction variable
+ is turned into command line options
+ by appending the &LIBDIRPREFIX; and &LIBDIRSUFFIX;
+ construction variables to the beginning and end,
+ respectively, of each specified library.
+
+ </para>
+
+ <para>
+
+ Other relevant construction variables
+ include those used by the &Object;
+ builders to affect how the
+ source files specified as input to the &Program;
+ builders are turned into object files;
+ see the next section.
+
+ </para>
+
+ <para>
+
+ The command line used to control how a program is linked
+ is specified by the &LINKCOM; construction variable.
+ By default, it uses the
+ &LINK; construction variable
+ and the &LINKFLAGS; construction variable.
+
+ </para>
+
</section>
<section>
<para>
&SCons; provides separate Builder objects
- to create both static and shared object files.
+ to create static and shared object files.
+ The distinction becomes especially important when
+ archiving object files into different types of libraries.
</para>
<para>
- XXX
+ The &StaticObject; Builder
+ is used to build an object file
+ suitable for static linking into a program,
+ or for inclusion in a static library.
+ The &source; argument is a single source-code file,
+ and the ⌖ argument is the
+ name of the static object file to be created.
+ For example:
</para>
<programlisting>
- XXX
+ StaticObject('file', 'file.c')
</programlisting>
+ <para>
+
+ Will create the &file_o;
+ object file on a POSIX system,
+ the &file_obj; executable on a Windows system.
+
+ </para>
+
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ $OBJPREFIX
+ and
+ $OBJSUFFIX
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(OBJPREFIX='my', OBJSUFFIX='.xxx')
+ env.StaticObject('file', 'file.c')
+ </programlisting>
+
+ <para>
+
+ Will create an object file named
+ <filename>myfile.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <para>
+
+ If you omit the ⌖,
+ the base of the first input
+ file name specified
+ beomces the base of the name
+ of the static object file to be created.
+ For example:
+
+ </para>
+
<literallayout>
- XXX
+ StaticObject('file.c')
</literallayout>
+ <para>
+
+ Will create the &file_o;
+ executable on a POSIX system,
+ the &file_obj; executable on a Windows system.
+
+ </para>
+
</section>
<section>
<para>
- XXX
+ The &SharedObject; Builder
+ is used to build an object file
+ suitable for shared linking into a program,
+ or for inclusion in a shared library.
+ The &source; argument is a single source-code file,
+ and the ⌖ argument is the
+ name of the shared object file to be created.
+ For example:
</para>
<programlisting>
- XXX
+ SharedObject('file', 'file.c')
</programlisting>
- <literallayout>
- XXX
- </literallayout>
+ <para>
- </section>
+ Will create the &file_o;
+ object file on a POSIX system,
+ the &file_obj; executable on a Windows system.
- <section>
- <title>The &Object; Builder</title>
+ </para>
<para>
- XXX
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ $SHOBJPREFIX
+ and
+ $SHOBJSUFFIX
+ construction variables
+ will be appended appropriately.
+ For example:
</para>
<programlisting>
- XXX
+ env = Environment(SHOBJPREFIX='my', SHOBJSUFFIX='.xxx')
+ env.SharedObject('file', 'file.c')
</programlisting>
<para>
- Creates a static object file.
+ Will create an object file named
+ <filename>myfile.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <para>
+
+ If you omit the ⌖,
+ the base of the first input
+ file name specified
+ becomes the base of the name
+ of the shared object file to be created.
+ For example:
+
+ </para>
+
+ <literallayout>
+ SharedObject('file.c')
+ </literallayout>
+
+ <para>
+
+ Will create the &file_o;
+ executable on a POSIX system,
+ the &file_obj; executable on a Windows system.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &Object; Builder</title>
+
+ <para>
+
+ The &Object; Builder is a synonym for &StaticObject;
+ and is completely equivalent.
</para>
<para>
&SCons; provides separate Builder objects
- to create both static and shared libraries.
+ to create static and shared libraries.
</para>
<para>
- XXX
+ The &StaticLibrary; Builder
+ is used to create a library
+ suitable for static linking into a program.
+ The &source; argument is one or more
+ source-code files or object files,
+ and the ⌖ argument is the
+ name of the static library to be created.
+ For example:
</para>
<programlisting>
- XXX
+ StaticLibrary('foo', ['file1.c', 'file2.c'])
+ </programlisting>
+
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ $LIBPREFIX
+ and
+ $LIBSUFFIX
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(LIBPREFIX='my', LIBSUFFIX='.xxx')
+ env.StaticLibrary('lib', ['file1.o', 'file2.o'])
+ </programlisting>
+
+ <para>
+
+ Will create an object file named
+ <filename>mylib.xxx</filename>
+ regardless of the system on which it is run.
+
+ </para>
+
+ <programlisting>
+ StaticLibrary('foo', ['file1.c', 'file2.c'])
</programlisting>
+ <para>
+
+ If you omit the ⌖,
+ the base of the first input
+ file name specified
+ becomes the base of the name of the static object file to be created.
+ For example:
+
+ </para>
+
<literallayout>
- XXX
+ StaticLibrary(['file.c', 'another.c'])
</literallayout>
+ <para>
+
+ Will create the &libfile_a;
+ library on a POSIX system,
+ the &file_lib; library on a Windows system.
+
+ </para>
+
</section>
<section>
<para>
- XXX
+ The &SharedLibrary; Builder
+ is used to create a shared library
+ suitable for linking with a program.
+ The &source; argument is one or more
+ source-code files or object files,
+ and the ⌖ argument is the
+ name of the shared library to be created.
+ For example:
</para>
- </section>
+ <programlisting>
+ SharedLibrary('foo', ['file1.c', 'file2.c'])
+ </programlisting>
- <section>
- <title>The &Library; Builder</title>
+ <para>
+
+ The target file's prefix and suffix may be omitted,
+ and the values from the
+ $SHLIBPREFIX
+ and
+ $SHLIBSUFFIX
+ construction variables
+ will be appended appropriately.
+ For example:
+
+ </para>
+
+ <programlisting>
+ env = Environment(SHLIBPREFIX='my', SHLIBSUFFIX='.xxx')
+ env.SharedLibrary('shared', ['file1.o', 'file2.o'])
+ </programlisting>
<para>
- XXX
+ Will create an object file named
+ <filename>myshared.xxx</filename>
+ regardless of the system on which it is run.
</para>
<programlisting>
- XXX
+ SharedLibrary('foo', ['file1.c', 'file2.c'])
</programlisting>
+ <para>
+
+ If you omit the ⌖,
+ the base of the first input
+ file name specified
+ becomes the base of the name of the shared library to be created.
+ For example:
+
+ </para>
+
<literallayout>
- XXX
+ SharedLibrary(['file.c', 'another.c'])
</literallayout>
<para>
- Creates a static library file.
+ Will create the &libfile_so;
+ library on a POSIX system,
+ the &file_dll; library on a Windows system.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>The &Library; Builder</title>
+
+ <para>
+
+ The &Library; Builder is a synonym for &StaticLibrary;
+ and is completely equivalent.
</para>
&SCons; supports two Builder objects
that know how to build source files
from other input files.
+ These are typically invoked "internally"
+ to turn files that need preprocessing into other source files.
</para>
</programlisting>
<literallayout>
- % <userinput>scons .</userinput>
+ % <userinput>scons -Q .</userinput>
tar -c -f out1.tar file1 file2
tar -c -f out2.tar directory
</literallayout>
</programlisting>
<literallayout>
- % <userinput>scons .</userinput>
+ % <userinput>scons -Q .</userinput>
tar -c -z -f out.tar.gz directory
</literallayout>
</programlisting>
<literallayout>
- % <userinput>scons .</userinput>
+ % <userinput>scons -Q .</userinput>
tar -c -z -f out.tgz directory
</literallayout>
</para>
<literallayout>
- % <userinput>scons .</userinput>
+ % <userinput>scons -Q .</userinput>
zip("out.zip", ["file1", "file2"])
</literallayout>
</para>
<literallayout>
- % <userinput>scons .</userinput>
+ % <userinput>scons -Q .</userinput>
zip /home/my/project/zip.out file1 file2
</literallayout>
</scons_example>
<scons_output example="ex1">
- <command>scons .</command>
+ <command>scons -Q</command>
</scons_output>
<para>
</scons_example>
<scons_output example="ex2">
- <command>scons .</command>
+ <command>scons -Q</command>
</scons_output>
<programlisting>
env = Environment()
- env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $TARGET > $SOURCE")
+ env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $SOURCE > $TARGET")
</programlisting>
<literallayout>
- % <userinput>scons .</userinput>
- sed 's/x/y' < foo.in > foo.out
+ % <userinput>scons -Q</userinput>
+ sed 's/x/y/' < foo.in > foo.out
</literallayout>
<para>
<programlisting>
env = Environment()
- def build(target, source, env)
- XXX
+ def build(target, source, env):
+ # Whatever it takes to build
return None
env.Command('foo.out', 'foo.in', build)
</programlisting>
<literallayout>
- % <userinput>scons .</userinput>
+ % <userinput>scons -Q</userinput>
build("foo.out", "foo.in")
</literallayout>
</para>
<scons_output example="ex1">
- <command>scons</command>
- <command>scons -c</command>
- <command>scons</command>
+ <command>scons -Q</command>
+ <command>scons -Q -c</command>
+ <command>scons -Q</command>
</scons_output>
</section>
</para>
<scons_output example="ex1">
- <command>scons</command>
- <command>scons -c</command>
- <command>scons --cache-show</command>
+ <command>scons -Q</command>
+ <command>scons -Q -c</command>
+ <command>scons -Q --cache-show</command>
</scons_output>
<para>
</para>
<scons_output example="ex1">
- <command>scons</command>
- <command>scons -c</command>
- <command>scons</command>
- <command>scons -c</command>
- <command>scons --cache-disable</command>
+ <command>scons -Q</command>
+ <command>scons -Q -c</command>
+ <command>scons -Q</command>
+ <command>scons -Q -c</command>
+ <command>scons -Q --cache-disable</command>
</scons_output>
</section>
</para>
<scons_output example="ex1">
- <command>scons --cache-disable</command>
- <command>scons -c</command>
- <command>scons --cache-disable</command>
- <command>scons --cache-force</command>
- <command>scons -c</command>
- <command>scons</command>
+ <command>scons -Q --cache-disable</command>
+ <command>scons -Q -c</command>
+ <command>scons -Q --cache-disable</command>
+ <command>scons -Q --cache-force</command>
+ <command>scons -Q -c</command>
+ <command>scons -Q</command>
</scons_output>
<para>
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- % <userinput>scons -c</userinput>
+ % <userinput>scons -Q -c</userinput>
Removed hello.o
Removed hello
- % <userinput>scons</userinput>
+ % <userinput>scons -Q</userinput>
Retrieved `hello.o' from cache
Retrieved `hello' from cache
- %
</literallayout>
</section>
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- % <userinput>scons -c</userinput>
+ % <userinput>scons -Q -c</userinput>
Removed hello.o
Removed hello
- % <userinput>scons --cache-show</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q --cache-show</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- %
</literallayout>
<para>
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- % <userinput>scons -c</userinput>
+ % <userinput>scons -Q -c</userinput>
Removed hello.o
Removed hello
- % <userinput>scons</userinput>
+ % <userinput>scons -Q</userinput>
Retrieved `hello.o' from cache
Retrieved `hello' from cache
- % <userinput>scons -c</userinput>
+ % <userinput>scons -Q -c</userinput>
Removed hello.o
Removed hello
- % <userinput>scons --cache-disable</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q --cache-disable</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- %
</literallayout>
</section>
</para>
<literallayout>
- % <userinput>scons --cache-disable</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q --cache-disable</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- % <userinput>scons -c</userinput>
+ % <userinput>scons -Q -c</userinput>
Removed hello.o
Removed hello
- % <userinput>scons --cache-disable</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q --cache-disable</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- % <userinput>scons --cache-force</userinput>
- % <userinput>scons -c</userinput>
+ % <userinput>scons -Q --cache-force</userinput>
+ scons: `.' is up to date.
+ % <userinput>scons -Q -c</userinput>
Removed hello.o
Removed hello
- % <userinput>scons</userinput>
+ % <userinput>scons -Q</userinput>
Retrieved `hello.o' from cache
Retrieved `hello' from cache
- %
</literallayout>
<para>
</para>
<scons_output example="ex1">
- <command>scons</command>
- <command>scons</command>
- <command>scons goodbye</command>
+ <command>scons -Q</command>
+ <command>scons -Q</command>
+ <command>scons -Q goodbye</command>
</scons_output>
<para>
</para>
<scons_output example="ex1">
- <command>scons .</command>
+ <command>scons -Q .</command>
</scons_output>
<para>
</para>
<scons_output example="ex2">
- <command>scons</command>
- <command>scons .</command>
+ <command>scons -Q</command>
+ <command>scons -Q .</command>
</scons_output>
<para>
</para>
<scons_output example="ex3">
- <command>scons</command>
- <command>scons .</command>
+ <command>scons -Q</command>
+ <command>scons -Q .</command>
</scons_output>
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- % <userinput>scons</userinput>
- % <userinput>scons goodbye</userinput>
- cc -c goodbye.c -o goodbye.o
+ % <userinput>scons -Q</userinput>
+ scons: `hello' is up to date.
+ % <userinput>scons -Q goodbye</userinput>
+ cc -c -o goodbye.o goodbye.c
cc -o goodbye goodbye.o
- %
</literallayout>
<para>
</para>
<literallayout>
- % <userinput>scons .</userinput>
- cc -c goodbye.c -o goodbye.o
+ % <userinput>scons -Q .</userinput>
+ cc -c -o goodbye.o goodbye.c
cc -o goodbye goodbye.o
- cc -c hello.c -o hello.o
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- %
</literallayout>
<para>
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c prog1.c -o prog1.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o prog1.o prog1.c
cc -o prog1 prog1.o
- cc -c prog3.c -o prog3.o
+ cc -c -o prog3.o prog3.c
cc -o prog3 prog3.o
- % <userinput>scons .</userinput>
- cc -c prog2.c -o prog2.o
+ % <userinput>scons -Q .</userinput>
+ cc -c -o prog2.o prog2.c
cc -o prog2 prog2.o
- %
</literallayout>
<para>
</para>
<literallayout>
- % <userinput>scons</userinput>
+ % <userinput>scons -Q</userinput>
scons: *** No targets specified and no Default() targets found. Stop.
- % <userinput>scons .</userinput>
- cc -c prog1.c -o prog1.o
+ % <userinput>scons -Q .</userinput>
+ cc -c -o prog1.o prog1.c
cc -o prog1 prog1.o
- cc -c prog2.c -o prog2.o
+ cc -c -o prog2.o prog2.c
cc -o prog2 prog2.o
- %
</literallayout>
<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;,
+ A &consenv; is created by the &Environment; method.
+ When you initialize a &consenv;,
you can set the values of the
environment's &consvars;
to control how a program is built.
</para>
<scons_example name="ex1">
- <file name="SConstruct">
+ <file name="SConstruct" printme="1">
env = Environment(CC = 'gcc',
CCFLAGS = '-O2')
</para>
<scons_output example="ex1">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<section>
<para>
- So far,
- all of our examples have
- created a single &consenv; named
- <literal>env</literal>.
- <literal>env</literal>, however,
- is simply a Python variable name,
- and you can use any other variable name that you like.
- For example:
-
- </para>
-
- <sconstruct>
- my_env = Environment(CC = 'gcc',
- CCFLAGS = '-O2')
-
- my_env.Program('foo.c')
- </sconstruct>
-
- <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:
+ The real advantage of construction environments
+ become apparent when you realize
+ that you can create as many different construction
+ environments as you need,
+ each tailored to a different way to build
+ some piece of software or other file.
+ If, for example, we need to build
+ one program with the <literal>-O2</literal> flag
+ and another with the <literal>-g</literal> (debug) flag,
+ we would do this like so:
</para>
<scons_example name="ex2">
- <file name="SConstruct">
+ <file name="SConstruct" printme="1">
opt = Environment(CCFLAGS = '-O2')
dbg = Environment(CCFLAGS = '-g')
</scons_example>
<scons_output example="ex2">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
</para>
<scons_example name="ex3">
- <file name="SConstruct">
+ <file name="SConstruct" printme="1">
opt = Environment(CCFLAGS = '-O2')
dbg = Environment(CCFLAGS = '-g')
</para>
<scons_output example="ex3">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
<literal>-O2</literal>
and one with a &CCFLAGS; value of
<literal>-g</literal>.
+ &SCons; can't just decide that one of them
+ should take precedence over the other,
+ so it generates the error.
To avoid this problem,
we must explicitly specify
that each environment compile
</programlisting>
<scons_example name="ex4">
- <file name="SConstruct">
+ <file name="SConstruct" printme="1">
opt = Environment(CCFLAGS = '-O2')
dbg = Environment(CCFLAGS = '-g')
Notice that each call to the &Object; builder
returns a value,
an internal &SCons; object that
- represents the file that will be built.
+ represents the object file that will be built.
We then use that object
as input to the &Program; builder.
This avoids having to specify explicitly
</para>
<scons_output example="ex4">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
</section>
that sets &CC; to &gcc;,
and then creating two copies,
one which sets &CCFLAGS; for optimization
- and the other with sets &CCFLAGS; for debugging:
+ and the other which sets &CCFLAGS; for debugging:
</para>
opt = env.Copy(CCFLAGS = '-O2')
dbg = env.Copy(CCFLAGS = '-g')
- e = opt.Object('foo', 'foo.c')
+ env.Program('foo', 'foo.c')
o = opt.Object('foo-opt', 'foo.c')
opt.Program(o)
</para>
<scons_output example="ex5">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
</section>
</para>
<scons_output example="ex6">
- <command>scons</command>
- CC is: cc
+ <command>scons -Q</command>
</scons_output>
<para>
<file name="SConstruct" printme="1">
env = Environment(FOO = 'foo', BAR = 'bar')
dict = env.Dictionary()
- for key, value in dict.items():
- print "key = %s, value = %s % (key, value)
+ for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']:
+ print "key = %s, value = %s" % (key, dict[key])
</file>
</scons_Example>
<para>
This &SConstruct; file
- will print the dictionary items for us as follows:
+ will print the specified dictionary items for us on POSIX
+ systems as follows:
+
+ </para>
+
+ <scons_output example="ex6b" os="posix">
+ <command>scons -Q</command>
+ </scons_output>
+
+ <para>
+
+ And on Win32:
</para>
- <scons_output example="ex6b">
- % <userinput>scons</userinput>
- key = FOO, value = foo
- key = BAR, value = bar
+ <scons_output example="ex6b" os="win32">
+ <command>scons -Q</command>
</scons_output>
</section>
</para>
<scons_output example="ex7">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
</section>
</scons_example>
<scons_output example="ex8">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
</section>
</scons_example>
<scons_output example="ex9">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
</section>
<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;,
+ A &consenv; is created by the &Environment; method.
+ When you initialize a &consenv;,
you can set the values of the
environment's &consvars;
to control how a program is built.
</para>
- <programlisting>
+ <programlisting>
env = Environment(CC = 'gcc',
CCFLAGS = '-O2')
env.Program('foo.c')
- </programlisting>
+ </programlisting>
<para>
</para>
<literallayout>
- % <userinput>scons</userinput>
- gcc -c -O2 foo.c -o foo.o
+ % <userinput>scons -Q</userinput>
+ gcc -O2 -c -o foo.o foo.c
gcc -o foo foo.o
</literallayout>
<para>
- So far,
- all of our examples have
- created a single &consenv; named
- <literal>env</literal>.
- <literal>env</literal>, however,
- is simply a Python variable name,
- and you can use any other variable name that you like.
- For example:
-
- </para>
-
- <programlisting>
- my_env = Environment(CC = 'gcc',
- CCFLAGS = '-O2')
-
- my_env.Program('foo.c')
- </programlisting>
-
- <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:
+ The real advantage of construction environments
+ become apparent when you realize
+ that you can create as many different construction
+ environments as you need,
+ each tailored to a different way to build
+ some piece of software or other file.
+ If, for example, we need to build
+ one program with the <literal>-O2</literal> flag
+ and another with the <literal>-g</literal> (debug) flag,
+ we would do this like so:
</para>
</programlisting>
<literallayout>
- % <userinput>scons</userinput>
- cc -c -O2 bar.c -o bar.o
+ % <userinput>scons -Q</userinput>
+ cc -g -c -o bar.o bar.c
cc -o bar bar.o
- cc -c -g foo.c -o foo.o
+ cc -O2 -c -o foo.o foo.c
cc -o foo foo.o
</literallayout>
</para>
<literallayout>
- % <userinput>scons</userinput>
- scons: *** Two different environments were specified for the same target: foo.o
+ % <userinput>scons -Q</userinput>
+
+ scons: *** Two different environments were specified for the same target: foo.o
File "SConstruct", line 6, in ?
</literallayout>
<literal>-O2</literal>
and one with a &CCFLAGS; value of
<literal>-g</literal>.
+ &SCons; can't just decide that one of them
+ should take precedence over the other,
+ so it generates the error.
To avoid this problem,
we must explicitly specify
that each environment compile
</para>
+ <programlisting>
+ </programlisting>
+
<programlisting>
opt = Environment(CCFLAGS = '-O2')
dbg = Environment(CCFLAGS = '-g')
Notice that each call to the &Object; builder
returns a value,
an internal &SCons; object that
- represents the file that will be built.
+ represents the object file that will be built.
We then use that object
as input to the &Program; builder.
This avoids having to specify explicitly
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c -g foo.c -o foo-dbg.o
+ % <userinput>scons -Q</userinput>
+ cc -g -c -o foo-dbg.o foo.c
cc -o foo-dbg foo-dbg.o
- cc -c -O2 foo.c -o foo-opt.o
+ cc -O2 -c -o foo-opt.o foo.c
cc -o foo-opt foo-opt.o
</literallayout>
that sets &CC; to &gcc;,
and then creating two copies,
one which sets &CCFLAGS; for optimization
- and the other with sets &CCFLAGS; for debugging:
+ and the other which sets &CCFLAGS; for debugging:
</para>
opt = env.Copy(CCFLAGS = '-O2')
dbg = env.Copy(CCFLAGS = '-g')
- e = opt.Object('foo', 'foo.c')
+ env.Program('foo', 'foo.c')
o = opt.Object('foo-opt', 'foo.c')
opt.Program(o)
</para>
<literallayout>
- % <userinput>scons</userinput>
- gcc -c foo.c -o foo.o
+ % <userinput>scons -Q</userinput>
+ gcc -c -o foo.o foo.c
gcc -o foo foo.o
- gcc -c -g foo.c -o foo-dbg.o
+ gcc -g -c -o foo-dbg.o foo.c
gcc -o foo-dbg foo-dbg.o
- gcc -c -O2 foo.c -o foo-opt.o
+ gcc -O2 -c -o foo-opt.o foo.c
gcc -o foo-opt foo-opt.o
</literallayout>
</para>
<literallayout>
- % <userinput>scons</userinput>
+ % <userinput>scons -Q</userinput>
CC is: cc
+ scons: `.' is up to date.
</literallayout>
<para>
<programlisting>
env = Environment(FOO = 'foo', BAR = 'bar')
dict = env.Dictionary()
- for key, value in dict.items():
- print "key = %s, value = %s % (key, value)
+ for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']:
+ print "key = %s, value = %s" % (key, dict[key])
</programlisting>
<para>
This &SConstruct; file
- will print the dictionary items for us as follows:
+ will print the specified dictionary items for us on POSIX
+ systems as follows:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons -Q</userinput>
+ key = OBJSUFFIX, value = .o
+ key = LIBSUFFIX, value = .a
+ key = PROGSUFFIX, value =
+ scons: `.' is up to date.
+ </literallayout>
+
+ <para>
+
+ And on Win32:
</para>
<literallayout>
- % <userinput>scons</userinput>
- key = FOO, value = foo
- key = BAR, value = bar
+ C:\><userinput>scons -Q</userinput>
+ key = OBJSUFFIX, value = .obj
+ key = LIBSUFFIX, value = .lib
+ key = PROGSUFFIX, value = .exe
+ scons: `.' is up to date.
</literallayout>
</section>
</para>
<programlisting>
- env = Environment(CCFLAGS = '-DDEFINE1)
+ env = Environment(CCFLAGS = '-DDEFINE1')
env.Program('foo.c')
env.Replace(CCFLAGS = '-DDEFINE2')
env.Program('bar.c')
</para>
<literallayout>
- % <userinput>scons</userinput>
- gcc -DDEFINE2 -c bar.c -o bar.o
- gcc -o bar bar.o
- gcc -DDEFINE2 -c foo.c -o foo.o
- gcc -o foo foo.o
+ % <userinput>scons -Q</userinput>
+ cc -DDEFINE2 -c -o bar.o bar.c
+ cc -o bar bar.o
+ cc -DDEFINE1 -c -o foo.o foo.c
+ cc -o foo foo.o
</literallayout>
</section>
</programlisting>
<literallayout>
- % <userinput>scons</userinput>
- gcc -DMY_VALUE -DLAST -c foo.c -o foo.o
- gcc -o foo foo.o
+ % <userinput>scons -Q</userinput>
+ cc -DMY_VALUE -DLAST -c -o foo.o foo.c
+ cc -o foo foo.o
</literallayout>
</section>
</programlisting>
<literallayout>
- % <userinput>scons</userinput>
- gcc -DFIRST -DMY_VALUE -c foo.c -o foo.o
- gcc -o foo foo.o
+ % <userinput>scons -Q</userinput>
+ cc -DFIRST -DMY_VALUE -c -o foo.o foo.c
+ cc -o foo foo.o
</literallayout>
</section>
It's often very useful to be able to give
users some help that describes the
specific targets, build options, etc.,
- that can be used for the build.
+ that can be used for your build.
&SCons; provides the &Help; function
to allow you to specify this help text:
</para>
<scons_example name="ex1">
- <file name="SConstruct">
+ <file name="SConstruct" printme="1">
Help("""
Type: 'scons program' to build the production program,
'scons debug' to build the debug version.
It's often very useful to be able to give
users some help that describes the
specific targets, build options, etc.,
- that can be used for the build.
+ that can be used for your build.
&SCons; provides the &Help; function
to allow you to specify this help text:
<literallayout>
% <userinput>scons -h</userinput>
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+
Type: 'scons program' to build the production program,
'scons debug' to build the debug version.
+
+ Use scons -H for help about command-line options.
</literallayout>
<para>
</para>
<scons_output example="ex1">
- <command>scons</command>
- <command>scons __ROOT__/usr/bin</command>
+ <command>scons -Q</command>
+ <command>scons -Q __ROOT__/usr/bin</command>
</scons_output>
<para>
</para>
- <scons_output example="ex1">
- <command>scons</command>
- <command>scons install</command>
+ <scons_output example="ex2">
+ <command>scons -Q</command>
+ <command>scons -Q install</command>
</scons_output>
<section>
<file name="hello.c">
int main() { printf("Hello, world!\n"); }
</file>
+ <file name="goodbye.c">
+ int main() { printf("Goodbye, world!\n"); }
+ </file>
</scons_example>
<para>
</para>
<scons_output example="ex3">
- <command>scons install</command>
+ <command>scons -Q install</command>
</scons_output>
</section>
</para>
<scons_output example="ex4">
- <command>scons install</command>
+ <command>scons -Q install</command>
</scons_output>
</section>
env.InstallAs(['__ROOT__/usr/bin/hello-new',
'__ROOT__/usr/bin/goodbye-new'],
[hello, goodbye])
+ env.Alias('install', '__ROOT__/usr/bin')
</file>
<file name="hello.c">
int main() { printf("Hello, world!\n"); }
</file>
+ <file name="goodbye.c">
+ int main() { printf("Goodbye, world!\n"); }
+ </file>
</scons_example>
<para>
</para>
<scons_output example="ex5">
- <command>scons install</command>
+ <command>scons -Q install</command>
</scons_output>
</section>
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- % <userinput>scons /usr/bin</userinput>
+ % <userinput>scons -Q /usr/bin</userinput>
Install file: "hello" as "/usr/bin/hello"
</literallayout>
</para>
<literallayout>
- % <userinput>scons install</userinput>
+ % <userinput>scons -Q</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q install</userinput>
Install file: "hello" as "/usr/bin/hello"
</literallayout>
hello = env.Program('hello.c')
goodbye = env.Program('goodbye.c')
env.Install('/usr/bin', hello)
- env.Install('/usr/bin', goodbye])
+ env.Install('/usr/bin', goodbye)
env.Alias('install', '/usr/bin')
</programlisting>
</para>
<literallayout>
- % <userinput>scons install</userinput>
- cc -c goodbye.c -o goodbye.o
+ % <userinput>scons -Q install</userinput>
+ cc -c -o goodbye.o goodbye.c
cc -o goodbye goodbye.o
- cc -c hello.c -o hello.o
- cc -o hello hello.o
Install file: "goodbye" as "/usr/bin/goodbye"
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
Install file: "hello" as "/usr/bin/hello"
</literallayout>
</para>
<literallayout>
- % <userinput>scons install</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q install</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
Install file: "hello" as "/usr/bin/hello-new"
</literallayout>
hello = env.Program('hello.c')
goodbye = env.Program('goodbye.c')
env.InstallAs(['/usr/bin/hello-new',
- '/usr/bin/goodbye-new',
+ '/usr/bin/goodbye-new'],
[hello, goodbye])
+ env.Alias('install', '/usr/bin')
</programlisting>
<para>
</para>
<literallayout>
- % <userinput>scons install</userinput>
- cc -c goodbye.c -o goodbye.o
+ % <userinput>scons -Q install</userinput>
+ cc -c -o goodbye.o goodbye.c
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"
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
Install file: "hello" as "/usr/bin/hello-new"
</literallayout>
<scons_example name="ex1" printme="1">
<file name="SConstruct" printme="1">
- env = Environment()
- env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ Library('foo', ['f1.c', 'f2.c', 'f3.c'])
</file>
<file name="hello.c">
int main() { printf("Hello, world!\n"); }
</para>
- <scons_output example="ex1">
- <command>scons</command>
+ <scons_output example="ex1" os="posix">
+ <command>scons -Q</command>
</scons_output>
<para>
</para>
- <scons_output example="ex1">
- <command>scons</command>
+ <scons_output example="ex1" os="win32">
+ <command>scons -Q</command>
</scons_output>
<para>
and by specifying the directory in which
the library will be found in the
&LIBPATH; construction variable:
+ env = Environment(LIBS = 'foo', LIBPATH = '.')
</para>
<scons_example name="ex2">
- <file name="SConstruct">
- env = Environment(LIBS = 'foo', LIBPATH = '.')
- env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
- env.Program('prog.c')
+ <file name="SConstruct" printme="1">
+ Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ Program('prog.c', LIBS='foo', LIBPATH='.')
</file>
<file name="f1.c">
int main() { printf("Hello, world!\n"); }
</para>
- <scons_output example="ex2">
- <command>scons</command>
+ <scons_output example="ex2" os="posix">
+ <command>scons -Q</command>
</scons_output>
<para>
</para>
<scons_output example="ex2" os="win32">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
<scons_example name="ex3">
<file name="SConstruct" printme="1">
- env = Environment(LIBS = 'm',
+ Program('prog.c', LIBS = 'm',
LIBPATH = ['/usr/lib', '/usr/local/lib'])
- env.Program('prog.c')
</file>
<file name="prog.c">
int main() { printf("prog.c\n"); }
</para>
- <scons_output example="ex3">
- <command>scons</command>
+ <scons_output example="ex3" os="posix">
+ <command>scons -Q</command>
</scons_output>
<para>
</para>
<scons_output example="ex3" os="win32">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
</para>
<programlisting>
- env = Environment()
- env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ Library('foo', ['f1.c', 'f2.c', 'f3.c'])
</programlisting>
<para>
&SCons; uses the appropriate library prefix and suffix for your system.
So on POSIX or Linux systems,
the above example would build as follows
- (although &ranlib may not be called on all systems):
+ (although &ranlib; may not be called on all systems):
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c f1.c -o f1.o
- cc -c f2.c -o f2.o
- cc -c f3.c -o f3.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o f1.o f1.c
+ cc -c -o f2.o f2.c
+ cc -c -o f3.o f3.c
ar r libfoo.a f1.o f2.o f3.o
ranlib libfoo.a
</literallayout>
</para>
<literallayout>
- C:\><userinput>scons</userinput>
- cl /Fof1.obj f1.c
- cl /Fof2.obj f2.c
- cl /Fof3.obj f3.c
+ C:\><userinput>scons -Q</userinput>
+ cl /nologo /c f1.c /Fof1.obj
+ cl /nologo /c f2.c /Fof2.obj
+ cl /nologo /c f3.c /Fof3.obj
lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj
</literallayout>
and by specifying the directory in which
the library will be found in the
&LIBPATH; construction variable:
+ env = Environment(LIBS = 'foo', LIBPATH = '.')
</para>
<programlisting>
- env = Environment(LIBS = 'foo', LIBPATH = '.')
- env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
- env.Program('prog.c')
+ Library('foo', ['f1.c', 'f2.c', 'f3.c'])
+ Program('prog.c', LIBS='foo', LIBPATH='.')
</programlisting>
<para>
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c f1.c -o f1.o
- cc -c f2.c -o f2.o
- cc -c f3.c -o f3.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o f1.o f1.c
+ cc -c -o f2.o f2.c
+ cc -c -o f3.o f3.c
ar r libfoo.a f1.o f2.o f3.o
ranlib libfoo.a
- cc -c prog.c -o prog.o
- cc -o prog -L. -lfoo prog.o
+ cc -c -o prog.o prog.c
+ cc -o prog prog.o -L. -lfoo
</literallayout>
<para>
</para>
<literallayout>
- C:\><userinput>scons</userinput>
- cl /Fof1.obj f1.c
- cl /Fof2.obj f2.c
- cl /Fof3.obj f3.c
+ C:\><userinput>scons -Q</userinput>
+ cl /nologo /c f1.c /Fof1.obj
+ cl /nologo /c f2.c /Fof2.obj
+ cl /nologo /c f3.c /Fof3.obj
lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj
- cl /Foprog.obj prog.c
- link /OUT:prog.exe /LIBPATH:. foo.lib prog.obj
+ cl /nologo /c prog.c /Foprog.obj
+ link /nologo /OUT:prog.exe /LIBPATH:. foo.lib prog.obj
</literallayout>
<para>
</para>
<programlisting>
- env = Environment(LIBS = 'm',
+ Program('prog.c', LIBS = 'm',
LIBPATH = ['/usr/lib', '/usr/local/lib'])
- env.Program('prog.c')
</programlisting>
<para>
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c prog.c -o prog.o
- cc -o prog -L/usr/lib -L/usr/local/lib -lm prog.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o prog.o prog.c
+ cc -o prog prog.o -L/usr/lib -L/usr/local/lib -lm
</literallayout>
<para>
</para>
<literallayout>
- C:\><userinput>scons</userinput>
- cl /Foprog.obj prog.c
- link /nologo /OUT:program.exe /LIBPATH:\usr\lib;\usr\local\lib m.lib prog.obj
+ C:\><userinput>scons -Q</userinput>
+ cl /nologo /c prog.c /Foprog.obj
+ link /nologo /OUT:prog.exe /LIBPATH:\usr\lib /LIBPATH:\usr\local\lib m.lib prog.obj
</literallayout>
<para>
<scons_example name="ex1">
<file name="SConstruct" printme="1">
- env = Environment(XXX NEED LIBRARY FLAGS
- LIBFLAGS = '-r')
+ env = Environment()
lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
env.Precious(lib)
</file>
<para>
- XXX:
+ Although the output doesn't look any different,
+ &SCons; does not, in fact,
+ delete the target library before rebuilding it:
</para>
<scons_output example="ex1">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
- &SCons; will still delete files marked as &Precious;
+ &SCons; will, however, still delete files marked as &Precious;
when the <literal>-c</literal> option is used.
</para>
</para>
<programlisting>
- env = Environment(XXX NEED LIBRARY FLAGS
- LIBFLAGS = '-r')
+ env = Environment()
lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
env.Precious(lib)
</programlisting>
<para>
- XXX:
+ Although the output doesn't look any different,
+ &SCons; does not, in fact,
+ delete the target library before rebuilding it:
</para>
<literallayout>
- % <userinput>scons</userinput>
- XXX ANY INPUT HERE?
+ % <userinput>scons -Q</userinput>
+ cc -c -o f1.o f1.c
+ cc -c -o f2.o f2.c
+ cc -c -o f3.o f3.c
+ ar r libfoo.a f1.o f2.o f3.o
+ ranlib libfoo.a
</literallayout>
<para>
- &SCons; will still delete files marked as &Precious;
+ &SCons; will, however, still delete files marked as &Precious;
when the <literal>-c</literal> option is used.
</para>
</para>
+ <section>
+ <title>Command-Line Options</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Getting at Command-Line Arguments</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
<section>
<title>Selective Builds</title>
<para>
- XXX
+ Users may find themselves supplying
+ the same command-line options every time
+ they run &SCons;.
+ For example, a user might find that it saves time
+ to always specify a value of <literal>-j 2</literal>
+ to run the builds in parallel.
+
+ </para>
+
+ <scons_example name="SCONSFLAGS">
+ <file name="SConstruct">
+ def b(target, source, env):
+ pass
+ def s(target, source, env):
+ return " ..."
+ a = Action(b, strfunction = s)
+ env = Environment(BUILDERS = {'A' : a})
+ env.A('foo.out', 'foo.in')
+ </file>
+ <file name="foo.in">
+ foo.in
+ </file>
+ </scons_example>
+
+ <scons_output example="SCONSFLAGS">
+ <command>scons</command>
+ <command>export SCONSFLAGS="-Q"</command>
+ <command>scons</command>
+ </scons_output>
+
+ <para>
</para>
</para>
+ <section>
+ <title>Command-Line Options</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Getting at Command-Line Arguments</title>
+
+ <para>
+
+ XXX
+
+ </para>
+
+ </section>
+
<section>
<title>Selective Builds</title>
<para>
- XXX
+ Users may find themselves supplying
+ the same command-line options every time
+ they run &SCons;.
+ For example, a user might find that it saves time
+ to always specify a value of <literal>-j 2</literal>
+ to run the builds in parallel.
+
+ </para>
+
+
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ scons: `.' is up to date.
+ scons: done building targets.
+ % <userinput>export SCONSFLAGS="-Q"</userinput>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ scons: `.' is up to date.
+ scons: done building targets.
+ </literallayout>
+
+ <para>
</para>
<scons_example name="ex1">
<file name="SConstruct" printme="1">
- env = Environment()
- env.Program('hello.c')
+ Program('hello.c')
</file>
<file name="hello.c">
int main() { printf("Hello, world!\n"); }
</para>
<programlisting>
- env = Environment() # Create an environment.
# Arrange to build the "hello" program.
- env.Program('hello.c')
+ Program('hello.c') # "hello.c" is the source file.
</programlisting>
<para>
</section>
+ <section>
+ <title>Making the Output Less Verbose</title>
+
+ <para>
+
+ You've already seen how &SCons; prints
+ some messages about what it's doing,
+ surrounding the actual commands used to build the software:
+
+ </para>
+
+ <scons_output example="ex1" os="win32">
+ <command>scons</command>
+ </scons_output>
+
+ <para>
+
+ These messages emphasize the
+ order in which &SCons; does its work:
+ the configuration files
+ (generically referred to as &SConscript; files)
+ are read and executed first,
+ and only then are the target files built.
+ Among other benefits, these messages help to distinguish between
+ errors that occur while the configuration files are read,
+ and errors that occur while targets are being built.
+
+ </para>
+
+ <para>
+
+ The drawback, of course, is that these messages clutter the output.
+ Fortunately, they're easily disabled by using
+ the &Q; option when invoking &SCons;:
+
+ </para>
+
+ <scons_output example="ex1" os="win32">
+ <command>scons -Q</command>
+ </scons_output>
+
+ <para>
+
+ Because we want this User's Guide to focus
+ on what &SCons; is actually doing,
+ we're going use the &Q; option
+ to remove these messages from the
+ output of all the remaining examples in this Guide.
+
+ </para>
+
+ </section>
+
<section>
<title>Compiling Multiple Source Files</title>
<scons_example name="ex2">
<file name="SConstruct" printme="1">
- env = Environment()
- env.Program(['prog.c', 'file1.c', 'file2.c'])
+ Program(['prog.c', 'file1.c', 'file2.c'])
</file>
<file name="prog.c">
int main() { printf("prog.c\n"); }
</para>
<scons_output example="ex2">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
<scons_example name="ex3">
<file name="SConstruct" printme="1">
- env = Environment()
- env.Program('program', ['main.c', 'file1.c', 'file2.c'])
+ Program('program', ['main.c', 'file1.c', 'file2.c'])
</file>
<file name="main.c">
int main() { printf("prog.c\n"); }
</para>
<scons_output example="ex3" os="posix">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
</para>
<scons_output example="ex3" os="win32">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
</section>
</para>
<programlisting>
- env = Environment()
- env.Program('program', Split('main.c file1.c file2.'))
+ Program('program', Split('main.c file1.c file2.'))
</programlisting>
<para>
+ (If you're already familiar with Python,
+ you'll have realized that this is similar to the
+ <function>split()</function> method
+ in the Python standard <function>string</function> module.
+ Unlike the <function>string.split()</function> method,
+ however, the &Split; function
+ does not require a string as input
+ and will wrap up a single non-string object in a list,
+ or return its argument untouched if it's already a list.
+ This comes in handy as a way to make sure
+ arbitrary values can be passed to &SCons; functions
+ without having to check the type of the variable by hand.)
+
+ </para>
+
+ <para>
+
Putting the call to the &Split; function
- inside the <function>env.Program</function> call
+ inside the <function>Program</function> call
can also be a little unwieldy.
A more readable alternative is to
assign the output from the &Split; call
to a variable name,
and then use the variable when calling the
- <function>env.Program</function> function:
+ <function>Program</function> function:
</para>
<programlisting>
- env = Environment()
list = Split('main.c file1.c file2.')
- env.Program('program', list)
+ Program('program', list)
</programlisting>
<para>
</para>
<programlisting>
- env = Environment()
list = Split('main.c
file1.c
file2.c')
- env.Program('program', list)
+ Program('program', list)
</programlisting>
</section>
</para>
<programlisting>
- env = Environment()
list = Split('main.c file1.c file2.')
- env.Program(target = 'program', source = list)
+ Program(target = 'program', source = list)
+ </programlisting>
+
+ <para>
+
+ Because the keywords explicitly identify
+ what each argument is,
+ you can actually reverse the order if you prefer:
+
+ </para>
+
+ <programlisting>
+ list = Split('main.c file1.c file2.')
+ Program(source = list, target = 'program')
</programlisting>
<para>
Whether or not you choose to use keyword arguments
- to identify the target and source files
- is purely a personal choice;
- &SCons; functions the same either way.
+ to identify the target and source files,
+ and the order in which you specify them
+ when using keywords,
+ are purely personal choices;
+ &SCons; functions the same regardless.
</para>
In order to compile multiple programs
within the same &SConstruct; file,
- simply call the <function>env.Program</function> method
+ simply call the <function>Program</function> method
multiple times,
once for each program you need to build:
<scons_example name="ex4">
<file name="SConstruct" printme="1">
- env = Environment()
- env.Program('foo.c')
- env.Program('bar', ['bar1.c', 'bar2.c'])
+ Program('foo.c')
+ Program('bar', ['bar1.c', 'bar2.c'])
</file>
<file name="foo.c">
int main() { printf("foo.c\n"); }
</para>
<scons_output example="ex4">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
<scons_example name="ex5">
<file name="SConstruct" printme="1">
- env = Environment()
- env.Program(Split('foo.c common1.c common2.c'))
- env.Program('bar', Split('bar1.c bar2.c common1.c common2.c'))
+ Program(Split('foo.c common1.c common2.c'))
+ Program('bar', Split('bar1.c bar2.c common1.c common2.c'))
</file>
<file name="foo.c">
int main() { printf("foo.c\n"); }
&SCons; recognizes that the object files for
the &common1_c; and &common2_c; source files
each only need to be built once,
- even though the files are listed multiple times:
+ even though the resulting object files are
+ each linked in to both of the resulting executable programs:
</para>
<scons_output example="ex5">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
common = ['common1.c', 'common2.c']
foo_files = ['foo.c'] + common
bar_files = ['bar1.c', 'bar2.c'] + common
- env = Environment()
- env.Program('foo', foo_files)
- env.Program('bar', bar_files)
+ Program('foo', foo_files)
+ Program('bar', bar_files)
</programlisting>
<para>
</para>
<programlisting>
- env = Environment()
- env.Program('hello.c')
+ Program('hello.c')
</programlisting>
<para>
<literallayout>
% <userinput>scons</userinput>
- cc -c hello.c -o hello.o
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cc -c -o hello.o hello.c
cc -o hello hello.o
+ scons: done building targets.
</literallayout>
<para>
<literallayout>
C:\><userinput>scons</userinput>
- cl /Fohello.obj hello.c
- link /Fohello.exe hello.obj
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cl /nologo /c hello.c /Fohello.obj
+ link /nologo /OUT:hello.exe hello.obj
+ scons: done building targets.
</literallayout>
<para>
</para>
<programlisting>
- env = Environment() # Create an environment.
# Arrange to build the "hello" program.
- env.Program('hello.c')
+ Program('hello.c') # "hello.c" is the source file.
</programlisting>
<para>
</section>
+ <section>
+ <title>Making the Output Less Verbose</title>
+
+ <para>
+
+ You've already seen how &SCons; prints
+ some messages about what it's doing,
+ surrounding the actual commands used to build the software:
+
+ </para>
+
+ <literallayout>
+ C:\><userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cl /nologo /c hello.c /Fohello.obj
+ link /nologo /OUT:hello.exe hello.obj
+ scons: done building targets.
+ </literallayout>
+
+ <para>
+
+ These messages emphasize the
+ order in which &SCons; does its work:
+ the configuration files
+ (generically referred to as &SConscript; files)
+ are read and executed first,
+ and only then are the target files built.
+ Among other benefits, these messages help to distinguish between
+ errors that occur while the configuration files are read,
+ and errors that occur while targets are being built.
+
+ </para>
+
+ <para>
+
+ The drawback, of course, is that these messages clutter the output.
+ Fortunately, they're easily disabled by using
+ the &Q; option when invoking &SCons;:
+
+ </para>
+
+ <literallayout>
+ C:\><userinput>scons -Q</userinput>
+ cl /nologo /c hello.c /Fohello.obj
+ link /nologo /OUT:hello.exe hello.obj
+ </literallayout>
+
+ <para>
+
+ Because we want this User's Guide to focus
+ on what &SCons; is actually doing,
+ we're going use the &Q; option
+ to remove these messages from the
+ output of all the remaining examples in this Guide.
+
+ </para>
+
+ </section>
+
<section>
<title>Compiling Multiple Source Files</title>
</para>
<programlisting>
- env = Environment()
- env.Program(['prog.c', 'file1.c', 'file2.'])
+ Program(['prog.c', 'file1.c', 'file2.c'])
</programlisting>
<para>
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c file1.c -o file1.o
- cc -c file2.c -o file2.o
- cc -c prog.c -o prog.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o file1.o file1.c
+ cc -c -o file2.o file2.c
+ cc -c -o prog.o prog.c
cc -o prog prog.o file1.o file2.o
</literallayout>
</para>
<programlisting>
- env = Environment()
- env.Program('program', ['main.c', 'file1.c', 'file2.'])
+ Program('program', ['main.c', 'file1.c', 'file2.c'])
</programlisting>
<para>
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c file1.c -o file1.o
- cc -c file2.c -o file2.o
- cc -c main.c -o main.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o file1.o file1.c
+ cc -c -o file2.o file2.c
+ cc -c -o main.o main.c
cc -o program main.o file1.o file2.o
</literallayout>
</para>
<literallayout>
- C:\><userinput>scons</userinput>
- cl /Fofile1.obj file1.c
- cl /Fofile2.obj file2.c
- cl /Fomain.obj main.c
- link /Foprogram.exe main.obj file1.obj file2.obj
+ C:\><userinput>scons -Q</userinput>
+ cl /nologo /c file1.c /Fofile1.obj
+ cl /nologo /c file2.c /Fofile2.obj
+ cl /nologo /c main.c /Fomain.obj
+ link /nologo /OUT:program.exe main.obj file1.obj file2.obj
</literallayout>
</section>
</para>
<programlisting>
- env = Environment()
- env.Program('program', Split('main.c file1.c file2.'))
+ Program('program', Split('main.c file1.c file2.'))
</programlisting>
<para>
+ (If you're already familiar with Python,
+ you'll have realized that this is similar to the
+ <function>split()</function> method
+ in the Python standard <function>string</function> module.
+ Unlike the <function>string.split()</function> method,
+ however, the &Split; function
+ does not require a string as input
+ and will wrap up a single non-string object in a list,
+ or return its argument untouched if it's already a list.
+ This comes in handy as a way to make sure
+ arbitrary values can be passed to &SCons; functions
+ without having to check the type of the variable by hand.)
+
+ </para>
+
+ <para>
+
Putting the call to the &Split; function
- inside the <function>env.Program</function> call
+ inside the <function>Program</function> call
can also be a little unwieldy.
A more readable alternative is to
assign the output from the &Split; call
to a variable name,
and then use the variable when calling the
- <function>env.Program</function> function:
+ <function>Program</function> function:
</para>
<programlisting>
- env = Environment()
list = Split('main.c file1.c file2.')
- env.Program('program', list)
+ Program('program', list)
</programlisting>
<para>
</para>
<programlisting>
- env = Environment()
list = Split('main.c
file1.c
file2.c')
- env.Program('program', list)
+ Program('program', list)
</programlisting>
</section>
</para>
<programlisting>
- env = Environment()
list = Split('main.c file1.c file2.')
- env.Program(target = 'program', source = list)
+ Program(target = 'program', source = list)
+ </programlisting>
+
+ <para>
+
+ Because the keywords explicitly identify
+ what each argument is,
+ you can actually reverse the order if you prefer:
+
+ </para>
+
+ <programlisting>
+ list = Split('main.c file1.c file2.')
+ Program(source = list, target = 'program')
</programlisting>
<para>
Whether or not you choose to use keyword arguments
- to identify the target and source files
- is purely a personal choice;
- &SCons; functions the same either way.
+ to identify the target and source files,
+ and the order in which you specify them
+ when using keywords,
+ are purely personal choices;
+ &SCons; functions the same regardless.
</para>
In order to compile multiple programs
within the same &SConstruct; file,
- simply call the <function>env.Program</function> method
+ simply call the <function>Program</function> method
multiple times,
once for each program you need to build:
</para>
<programlisting>
- env = Environment()
- env.Program('foo.c')
- env.Program('bar', ['bar1.c', 'bar2.c'])
+ Program('foo.c')
+ Program('bar', ['bar1.c', 'bar2.c'])
</programlisting>
<para>
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c bar1.c -o bar1.o
- cc -c bar2.c -o bar2.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o bar1.o bar1.c
+ cc -c -o bar2.o bar2.c
cc -o bar bar1.o bar2.o
- cc -c foo.c -o foo.o
+ cc -c -o foo.o foo.c
cc -o foo foo.o
</literallayout>
</para>
<programlisting>
- env = Environment()
- env.Program(Split('foo.c common1.c common2.c'))
- env.Program('bar', Split('bar1.c bar2.c common1.c common2.c'))
+ Program(Split('foo.c common1.c common2.c'))
+ Program('bar', Split('bar1.c bar2.c common1.c common2.c'))
</programlisting>
<para>
&SCons; recognizes that the object files for
the &common1_c; and &common2_c; source files
each only need to be built once,
- even though the files are listed multiple times:
+ even though the resulting object files are
+ each linked in to both of the resulting executable programs:
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c bar1.c -o bar1.o
- cc -c bar2.c -o bar2.o
- cc -c common1.c -o common1.o
- cc -c common2.c -o common2.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o bar1.o bar1.c
+ cc -c -o bar2.o bar2.c
+ cc -c -o common1.o common1.c
+ cc -c -o common2.o common2.c
cc -o bar bar1.o bar2.o common1.o common2.o
- cc -c foo.c -o foo.o
+ cc -c -o foo.o foo.c
cc -o foo foo.o common1.o common2.o
</literallayout>
common = ['common1.c', 'common2.c']
foo_files = ['foo.c'] + common
bar_files = ['bar1.c', 'bar2.c'] + common
- env = Environment()
- env.Program('foo', foo_files)
- env.Program('bar', bar_files)
+ Program('foo', foo_files)
+ Program('bar', bar_files)
</programlisting>
<para>
import shutil
import stat
import string
+import cStringIO
import SCons.Action
import SCons.Errors
self._cwd = dir
if change_os_dir:
os.chdir(dir.abspath)
- except:
+ except OSError:
self._cwd = curr
raise
message = "building associated BuildDir targets: %s" % string.join(map(str, targets))
return targets, message
+class DummyExecutor:
+ """Dummy executor class returned by Dir nodes to bamboozle SCons
+ into thinking we are an actual derived node, where our sources are
+ our directory entries."""
+ def get_raw_contents(self):
+ return ''
+ def get_contents(self):
+ return ''
+ def get_timestamp(self):
+ return 0
+
class Dir(Base):
"""A class for directories in a file system.
"""
self.abspath_ = self.abspath + os.sep
self.repositories = []
self.srcdir = None
+ self.source_scanner = None
self.entries = {}
self.entries['.'] = self
self.entries['..'] = self.dir
self.cwd = self
self.builder = 1
+ self.searched = 0
self._sconsign = None
self.build_dirs = []
self.all_children(scan))
def all_children(self, scan=1):
+ # Before we traverse our children, make sure we have created Nodes
+ # for any files that this directory contains. We need to do this
+ # so any change in a file in this directory will cause it to
+ # be out of date.
+ if not self.searched:
+ try:
+ for filename in os.listdir(self.abspath):
+ if filename != '.sconsign':
+ self.Entry(filename)
+ except OSError:
+ # Directory does not exist. No big deal
+ pass
+ self.searched = 1
keys = filter(lambda k: k != '.' and k != '..', self.entries.keys())
kids = map(lambda x, s=self: s.entries[x], keys)
def c(one, two):
"""A directory does not get scanned."""
return None
- def calc_signature(self, calc):
- """A directory has no signature."""
- return None
-
def set_bsig(self, bsig):
"""A directory has no signature."""
bsig = None
csig = None
def get_contents(self):
- """Return a fixed "contents" value of a directory."""
- return ''
-
+ """Return aggregate contents of all our children."""
+ contents = cStringIO.StringIO()
+ for kid in self.children(None):
+ contents.write(kid.get_contents())
+ return contents.getvalue()
+
def prepare(self):
pass
return self.srcdir
return Base.srcnode(self)
+ def get_executor(self, create=1):
+ """Fetch the action executor for this node. Create one if
+ there isn't already one, and requested to do so."""
+ try:
+ executor = self.executor
+ except AttributeError:
+ executor = DummyExecutor()
+ self.executor = executor
+ return executor
+
+ def get_timestamp(self):
+ """Return the latest timestamp from among our children"""
+ stamp = 0
+ for kid in self.children(None):
+ if kid.get_timestamp() > stamp:
+ stamp = kid.get_timestamp()
+ return stamp
+
class File(Base):
"""A class for files in a file system.
"""
def rfile(self):
try:
return self._rfile
- except:
+ except AttributeError:
self._rfile = self
if not self.exists():
n = self.fs.Rsearch(self.path, clazz=File,
assert f.get('foo') == (3, 1, 2)
assert f.get_implicit('foo') == ['bar']
+class SConsignFileTestCase(unittest.TestCase):
+
+ def runTest(self):
+ test = TestCmd.TestCmd(workdir = '')
+ file = test.workpath('sconsign_file')
+
+ assert SCons.Sig.SConsign_db is None, SCons.Sig.SConsign_db
+
+ SCons.Sig.SConsignFile(file)
+
+ assert not SCons.Sig.SConsign_db is None, SCons.Sig.SConsign_db
+
+ class Fake_DBM:
+ def open(self, name, mode):
+ self.name = name
+ self.mode = mode
+ return self
+
+ fake_dbm = Fake_DBM()
+
+ SCons.Sig.SConsignFile(file, fake_dbm)
+
+ assert not SCons.Sig.SConsign_db is None, SCons.Sig.SConsign_db
+ assert not hasattr(fake_dbm, 'name'), fake_dbm
+ assert not hasattr(fake_dbm, 'mode'), fake_dbm
+
+ SCons.Sig.SConsign_db = None
+
+ SCons.Sig.SConsignFile(file, fake_dbm)
+
+ assert not SCons.Sig.SConsign_db is None, SCons.Sig.SConsign_db
+ assert fake_dbm.name == file, fake_dbm.name
+ assert fake_dbm.mode == "c", fake_dbm.mode
+
+
def suite():
suite = unittest.TestSuite()
suite.addTest(_SConsignTestCase())
suite.addTest(SConsignDBTestCase())
suite.addTest(SConsignDirFileTestCase())
+ suite.addTest(SConsignFileTestCase())
return suite
if __name__ == "__main__":
SConsign_db = None
-# 1 means use build signature for derived source files
-# 0 means use content signature for derived source files
-build_signature = 1
-
def write():
global sig_files
for sig_file in sig_files:
"""
try:
return self.entries[filename]
- except:
+ except (KeyError, AttributeError):
return SConsignEntry()
def set_entry(self, filename, entry):
if type(self.entries) is not type({}):
self.entries = {}
raise TypeError
+ except KeyboardInterrupt:
+ raise
except:
SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
"Ignoring corrupt sconsign entry : %s"%self.dir.path)
if self.dirty:
global SConsign_db
SConsign_db[self.dir.path] = cPickle.dumps(self.entries, 1)
- SConsign_db.sync()
+ try:
+ SConsign_db.sync()
+ except AttributeError:
+ # Not all anydbm modules have sync() methods.
+ pass
class SConsignDir(_SConsign):
def __init__(self, fp=None, module=None):
try:
fp = open(self.sconsign, 'rb')
- except:
+ except IOError:
fp = None
try:
SConsignDir.__init__(self, fp, module)
+ except KeyboardInterrupt:
+ raise
except:
SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
"Ignoring corrupt .sconsign file: %s"%self.sconsign)
try:
file = open(temp, 'wb')
fname = temp
- except:
+ except IOError:
try:
file = open(self.sconsign, 'wb')
fname = self.sconsign
- except:
+ except IOError:
return
cPickle.dump(self.entries, file, 1)
file.close()
mode = os.stat(self.sconsign)[0]
os.chmod(self.sconsign, 0666)
os.unlink(self.sconsign)
- except:
+ except OSError:
pass
try:
os.rename(fname, self.sconsign)
- except:
+ except OSError:
open(self.sconsign, 'wb').write(open(fname, 'rb').read())
os.chmod(self.sconsign, mode)
try:
os.unlink(temp)
- except:
+ except OSError:
pass
SConsignForDirectory = SConsignDirFile
-def SConsignFile(name):
+def SConsignFile(name, dbm_module=None):
"""
Arrange for all signatures to be stored in a global .sconsign.dbm
file.
"""
global SConsign_db
if SConsign_db is None:
- import anydbm
- SConsign_db = anydbm.open(name, "c")
+ if dbm_module is None:
+ import anydbm
+ dbm_module = anydbm
+ SConsign_db = dbm_module.open(name, "c")
global SConsignForDirectory
SConsignForDirectory = SConsignDB
# sys.prefix is (likely) C:\Python*;
# check only C:\Python*.
prefs.append(sys.prefix)
+ prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages'))
else:
# On other (POSIX) platforms, things are more complicated due to
# the variety of path names and library locations. Try to be smart
# check only /foo/lib/scons*.
prefs.append(sys.prefix)
- prefs = map(lambda x: os.path.join(x, 'lib'), prefs)
+ temp = map(lambda x: os.path.join(x, 'lib'), prefs)
+ temp.extend(map(lambda x: os.path.join(x,
+ 'lib',
+ 'python' + sys.version[:3],
+ 'site-packages'),
+ prefs))
+ prefs = temp
# Look first for 'scons-__version__' in all of our preference libs,
# then for 'scons'.
#
test.write(['work2', 'SConstruct'], """
-SConsignFile('my_sconsign')
+e = Environment(XXX = 'scons')
+e.SConsignFile('my_${XXX}ign')
B = Builder(action = "%s ../build.py $TARGETS $SOURCES")
env = Environment(BUILDERS = { 'B' : B })
env.B(target = 'f5.out', source = 'f5.in')
#!/usr/bin/env python
#
-# Copyright (c) 2001, 2002, 2003 Steven Knight
+# __COPYRIGHT__
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-__revision__ = "/home/scons/scons/branch.0/baseline/test/sconsign.py 0.90.D001 2003/06/25 15:32:24 knight"
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os.path
import string