Python 1.5.2, you may not have distutils installed. If you are running
Python version 1.6 or later, you should be fine.
-NOTE TO RED HAT USERS: All Red Hat Linux versions up to 7.3 still ship
-Python 1.5.2 as the default, so you probably do *not* have distutils
+NOTE TO RED HAT USERS: Red Hat shipped Python 1.5.2 as the default all
+the way up to Red Hat Linux 7.3, so you probably do *not* have distutils
installed, unless you have already done so manually or are running Red
Hat 8.0 or later.
-- (Optional.) Install from a pre-packaged SCons package that
does not require distutils:
- Red Hat Linux scons-0.92-1.noarch.rpm
+ Red Hat Linux scons-0.93-1.noarch.rpm
- Debian GNU/Linux scons_0.92-1_all.deb
+ Debian GNU/Linux scons_0.93-1_all.deb
(or use apt-get)
- Windows scons-0.92.win32.exe
+ Windows scons-0.93.win32.exe
-- (Recommended.) Download the latest distutils package from the
following URL:
Depending on the utilities installed on your system, any or all of the
following packages will be built:
- build/dist/scons-0.92-1.noarch.rpm
- build/dist/scons-0.92-1.src.rpm
- build/dist/scons-0.92.linux-i686.tar.gz
- build/dist/scons-0.92.tar.gz
- build/dist/scons-0.92.win32.exe
- build/dist/scons-0.92.zip
- build/dist/scons-doc-0.92.tar.gz
- build/dist/scons-local-0.92.tar.gz
- build/dist/scons-local-0.92.zip
- build/dist/scons-src-0.92.tar.gz
- build/dist/scons-src-0.92.zip
- build/dist/scons_0.92-1_all.deb
+ build/dist/scons-0.93-1.noarch.rpm
+ build/dist/scons-0.93-1.src.rpm
+ build/dist/scons-0.93.linux-i686.tar.gz
+ build/dist/scons-0.93.tar.gz
+ build/dist/scons-0.93.win32.exe
+ build/dist/scons-0.93.zip
+ build/dist/scons-doc-0.93.tar.gz
+ build/dist/scons-local-0.93.tar.gz
+ build/dist/scons-local-0.93.zip
+ build/dist/scons-src-0.93.tar.gz
+ build/dist/scons-src-0.93.zip
+ build/dist/scons_0.93-1_all.deb
The SConstruct file is supposed to be smart enough to avoid trying to
build packages for which you don't have the proper utilities installed.
import time
project = 'scons'
-default_version = '0.92'
+default_version = '0.93'
copyright = "Copyright (c) %s Steven Knight" % copyright_years
Default('.')
+scons (0.93-1) unstable; urgency=low
+
+ * Fourth beta release.
+
+ -- Steven Knight <knight@baldmt.com> Thu, 23 Oct 2003 07:26:55 -0500
+
+
scons (0.92-1) unstable; urgency=low
* Third beta release.
<!ENTITY implicit-cache "<literal>--implicit-cache</literal>">
<!ENTITY implicit-deps-changed "<literal>--implicit-deps-changed</literal>">
<!ENTITY implicit-deps-unchanged "<literal>--implicit-deps-unchanged</literal>">
+<!ENTITY Q "<literal>-Q</literal>">
<!--
<!ENTITY Export "<function>Export</function>">
<!ENTITY Help "<function>Help</function>">
<!ENTITY Ignore "<function>Ignore</function>">
+<!ENTITY Import "<function>Import</function>">
<!ENTITY Install "<function>Install</function>">
<!ENTITY InstallAs "<function>InstallAs</function>">
<!ENTITY Link "<function>Link</function>">
<!ENTITY Prepend "<function>Prepend</function>">
<!ENTITY Replace "<function>Replace</function>">
<!ENTITY Repository "<function>Repository</function>">
+<!ENTITY Return "<function>Return</function>">
<!ENTITY RuleSet "<function>RuleSet</function>">
<!ENTITY Salt "<function>Salt</function>">
<!ENTITY SetBuildSignatureType "<function>SetBuildSignatureType</function>">
<!ENTITY BUILDERMAP "<varname>BUILDERMAP</varname>">
<!ENTITY BUILDERS "<varname>BUILDERS</varname>">
+<!ENTITY LIBDIRPREFIX "<varname>LIBDIRPREFIX</varname>">
+<!ENTITY LIBDIRSUFFIX "<varname>LIBDIRSUFFIX</varname>">
+<!ENTITY LIBLINKPREFIX "<varname>LIBLINKPREFIX</varname>">
+<!ENTITY LIBLINKSUFFIX "<varname>LIBLINKSUFFIX</varname>">
+<!ENTITY LINK "<varname>LINK</varname>">
+<!ENTITY LINKCOM "<varname>LINKCOM</varname>">
+<!ENTITY LINKFLAGS "<varname>LINKFLAGS</varname>">
<!ENTITY SCANNERMAP "<varname>SCANNERMAP</varname>">
<!ENTITY SCANNERS "<varname>SCANNERS</varname>">
<!ENTITY TARFLAGS "<varname>TARFLAGS</varname>">
-->
+<!ENTITY bar "<application>bar</application>">
<!ENTITY common1_c "<application>common1.c</application>">
<!ENTITY common2_c "<application>common2.c</application>">
<!ENTITY goodbye "<application>goodbye</application>">
+<!ENTITY file_dll "<application>file.dll</application>">
+<!ENTITY file_lib "<application>file.lib</application>">
+<!ENTITY file_o "<application>file.o</application>">
+<!ENTITY file_obj "<application>file.obj</application>">
+<!ENTITY foo "<application>foo</application>">
<!ENTITY hello "<application>hello</application>">
<!ENTITY hello_c "<filename>hello.c</filename>">
<!ENTITY hello_exe "<filename>hello.exe</filename>">
<!ENTITY hello_h "<filename>hello.h</filename>">
<!ENTITY hello_o "<filename>hello.o</filename>">
+<!ENTITY libfile_a "<filename>libfile_a</filename>">
+<!ENTITY libfile_so "<filename>libfile_so</filename>">
<!ENTITY prog "<filename>prog</filename>">
<!ENTITY prog1 "<filename>prog1</filename>">
<!ENTITY prog2 "<filename>prog2</filename>">
<file name="SConstruct">
bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env = Environment(BUILDERS = {'Foo' : bld})
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
env.Foo('file.foo', 'file.input')
</file>
<file name="file.input">
file.input
</file>
+ <file name="foobuild" chmod="0755">
+ cat
+ </file>
</scons_example>
- <programlisting>
+ <sconstruct>
bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env = Environment(BUILDERS = {'Foo' : bld})
- </programlisting>
+ </sconstruct>
<para>
</para>
<scons_output example="ex1">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
</file>
</scons_example>
- <!--
- scons: Reading SConscript files ...
- other errors
- Traceback (most recent call last):
- File "/usr/lib/scons/SCons/Script/__init__.py", line 901, in main
- _main()
- File "/usr/lib/scons/SCons/Script/__init__.py", line 762, in _main
- SCons.Script.SConscript.SConscript(script)
- File "/usr/lib/scons/SCons/Script/SConscript.py", line 207, in SConscript
- exec _file_ in stack[-1].globals
- File "SConstruct", line 4, in ?
- env.Program('hello.c')
- scons: Environment instance has no attribute 'Program'
- -->
-
<scons_output example="ex2">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
<scons_example name="ex3">
<file name="SConstruct">
env = Environment()
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env.Append(BUILDERS = {'Foo' : bld})
env.Foo('file.foo', 'file.input')
<file name="hello.c">
hello.c
</file>
+ <file name="foobuild" chmod="0755">
+ cat
+ </file>
</scons_example>
+ <sconstruct>
+ env = Environment()
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ env.Append(BUILDERS = {'Foo' : bld})
+ env.Foo('file.foo', 'file.input')
+ env.Program('hello.c')
+ </sconstruct>
+
<para>
Or you can explicitly set the appropriately-named
</para>
- <programlisting>
+ <sconstruct>
env = Environment()
bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env['BUILDERS']['Foo'] = bld
env.Foo('file.foo', 'file.input')
env.Program('hello.c')
- </programlisting>
+ </sconstruct>
<para>
</para>
<scons_output example="ex3">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
</section>
</para>
<scons_example name="ex4">
- <file name="SConstruct" printme="1">
- bld = Builder(action = 'foobuild < $TARGET > $SOURCE',
+ <file name="SConstruct">
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET',
suffix = '.foo',
src_suffix = '.input')
env = Environment(BUILDERS = {'Foo' : bld})
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
env.Foo('file1')
env.Foo('file2')
</file>
<file name="file2.input">
file2.input
</file>
+ <file name="foobuild" chmod="0755">
+ cat
+ </file>
</scons_example>
+ <sconstruct>
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET',
+ suffix = '.foo',
+ src_suffix = '.input')
+ env = Environment(BUILDERS = {'Foo' : bld})
+ env.Foo('file1')
+ env.Foo('file2')
+ </sconstruct>
+
<scons_output example="ex4">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
<programlisting>
def build_function(target, source, env):
- # XXX
+ # Code to build "target" from "source"
return None
</programlisting>
<scons_example name="ex5">
<file name="SConstruct" printme="1">
def build_function(target, source, env):
- # XXX
+ # Code to build "target" from "source"
return None
bld = Builder(action = build_function,
suffix = '.foo',
</para>
<scons_output example="ex5">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
</section>
&SCons; Builder objects can create an action "on the fly"
by using a function called a &generator;.
- This provides a great deal of flexibility XXX
+ 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 XXX
+ return 'foobuild < %s > %s' % (target[0], source[0])
</programlisting>
<para>
generator is being called to contribute to a build signature,
as opposed to actually executing the command.
- XXX
+ <!-- XXX NEED MORE HERE -->
</para>
</listitem>
</para>
<scons_example name="ex6">
- <file name="SConstruct" printme="1">
+ <file name="SConstruct">
+ 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})
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
env.Foo('file')
</file>
<file name="file.input">
file.input
</file>
+ <file name="foobuild" chmod="0755">
+ cat
+ </file>
</scons_example>
+ <sconstruct>
+ 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')
+ </sconstruct>
+
<scons_output example="ex6">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
</para>
<scons_example name="ex7">
- <file name="SConstruct" printme="1">
- def modify_targets(XXX):
- return XXX
- bld = Builder(action = 'XXX',
+ <file name="SConstruct">
+ 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})
+ import os
+ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
env.Foo('file')
</file>
<file name="file.input">
file.input
</file>
- </programlisting>
+ <file name="new_source">
+ new_source
+ </file>
+ <file name="foobuild" chmod="0755">
+ cat
+ </file>
+ </scons_example>
+
+ <sconstruct>
+ 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')
+ </sconstruct>
<scons_output example="ex7">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<programlisting>
suffix = '.foo',
src_suffix = '.input',
emitter = 'MY_EMITTER')
- def modify1(XXX):
- return XXX
- def modify2(XXX):
- return XXX
+ def modify1(target, source, env):
+ return target, source
+ def modify2(target, source, env):
+ return target, source
env1 = Environment(BUILDERS = {'Foo' : bld},
MY_EMITTER = modify1)
env2 = Environment(BUILDERS = {'Foo' : bld},
</section>
+ <!--
+
<section>
<title>Builders That Use Other Builders</title>
<scons_example name="ex8">
<file name="SConstruct" printme="1">
env = Environment()
- env.SourceCode('.', env.BitKeeper('XXX'))
+ #env.SourceCode('.', env.BitKeeper('XXX'))
env.Program('hello.c')
</file>
- </programlisting>
+ <file name="hello.c">
+ hello.c
+ </file>
+ </scons_example>
<scons_output example="ex8">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
</section>
+
+ -->
</para>
<programlisting>
- bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
</programlisting>
<para>
</para>
+
+
<programlisting>
- bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env = Environment(BUILDERS = {'Foo' : bld})
</programlisting>
</para>
<literallayout>
- % <userinput>scons</userinput>
+ % <userinput>scons -Q</userinput>
foobuild < file.input > file.foo
</literallayout>
</para>
<programlisting>
- bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env = Environment(BUILDERS = {'Foo' : bld})
env.Foo('file.foo', 'file.input')
env.Program('hello.c')
</programlisting>
<literallayout>
- % <userinput>scons</userinput>
- scons: Reading SConscript files ...
- other errors
- Traceback (most recent call last):
- File "/usr/lib/scons/SCons/Script/__init__.py", line 901, in main
- _main()
- File "/usr/lib/scons/SCons/Script/__init__.py", line 762, in _main
- SCons.Script.SConscript.SConscript(script)
- File "/usr/lib/scons/SCons/Script/SConscript.py", line 207, in SConscript
- exec _file_ in stack[-1].globals
- File "SConstruct", line 4, in ?
- env.Program('hello.c')
- scons: Environment instance has no attribute 'Program'
+ % <userinput>scons -Q</userinput>
+ AttributeError: SConsEnvironment instance has no attribute 'Program':
</literallayout>
<para>
</para>
+
+
<programlisting>
env = Environment()
- bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env.Append(BUILDERS = {'Foo' : bld})
env.Foo('file.foo', 'file.input')
env.Program('hello.c')
<programlisting>
env = Environment()
- bld = Builder(action = 'foobuild < $TARGET > $SOURCE')
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env['BUILDERS']['Foo'] = bld
env.Foo('file.foo', 'file.input')
env.Program('hello.c')
</para>
<literallayout>
- % <userinput>scons</userinput>
+ % <userinput>scons -Q</userinput>
foobuild < file.input > file.foo
- cc -c hello.c -o hello.o
+ cc -c -o hello.o hello.c
cc -o hello hello.o
</literallayout>
</para>
+
+
<programlisting>
- bld = Builder(action = 'foobuild < $TARGET > $SOURCE',
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET',
suffix = '.foo',
src_suffix = '.input')
env = Environment(BUILDERS = {'Foo' : bld})
</programlisting>
<literallayout>
- % <userinput>scons</userinput>
+ % <userinput>scons -Q</userinput>
foobuild < file1.input > file1.foo
foobuild < file2.input > file2.foo
</literallayout>
<programlisting>
def build_function(target, source, env):
- # XXX
+ # Code to build "target" from "source"
return None
</programlisting>
<programlisting>
def build_function(target, source, env):
- # XXX
+ # Code to build "target" from "source"
return None
bld = Builder(action = build_function,
suffix = '.foo',
</para>
<literallayout>
- % <userinput>scons</userinput>
+ % <userinput>scons -Q</userinput>
build_function("file.foo", "file.input")
</literallayout>
&SCons; Builder objects can create an action "on the fly"
by using a function called a &generator;.
- This provides a great deal of flexibility XXX
+ 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 XXX
+ return 'foobuild < %s > %s' % (target[0], source[0])
</programlisting>
<para>
generator is being called to contribute to a build signature,
as opposed to actually executing the command.
- XXX
+ <!-- XXX NEED MORE HERE -->
</para>
</listitem>
</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')
</programlisting>
<literallayout>
- % <userinput>scons</userinput>
- XXX
+ % <userinput>scons -Q</userinput>
+ foobuild < file.input > file.foo
</literallayout>
<para>
</para>
+
+
<programlisting>
- def modify_targets(XXX):
- return XXX
- bld = Builder(action = 'XXX',
+ 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)
</programlisting>
<literallayout>
- % <userinput>scons</userinput>
- XXX
+ % <userinput>scons -Q</userinput>
+ foobuild file.foo new_target - file.input new_source
</literallayout>
<programlisting>
suffix = '.foo',
src_suffix = '.input',
emitter = 'MY_EMITTER')
- def modify1(XXX):
- return XXX
- def modify2(XXX):
- return XXX
+ def modify1(target, source, env):
+ return target, source
+ def modify2(target, source, env):
+ return target, source
env1 = Environment(BUILDERS = {'Foo' : bld},
MY_EMITTER = modify1)
env2 = Environment(BUILDERS = {'Foo' : bld},
</section>
+ <!--
+
<section>
<title>Builders That Use Other Builders</title>
</para>
- <programlisting>
+ <scons_example name="ex8">
+ <file name="SConstruct" printme="1">
env = Environment()
- env.SourceCode('.', env.BitKeeper('XXX')
+ #env.SourceCode('.', env.BitKeeper('XXX'))
env.Program('hello.c')
- </programlisting>
+ </file>
+ <file name="hello.c">
+ hello.c
+ </file>
+ </scons_example>
- <literallayout>
- % <userinput>scons</userinput>
- XXX
- </literallayout>
+ <scons_output example="ex8">
+ <command>scons -Q</command>
+ </scons_output>
</section>
+
+ -->
<scons_example name="ex1">
<file name="SConstruct">
- env = Environment()
- env.Program('hello.c')
+ Program('hello.c')
</file>
<file name="hello.c">
int main() { printf("Hello, world!\n"); }
</scons_example>
<scons_output example="ex1" os="posix">
- <command>scons</command>
- <command>scons</command>
+ <command>scons -Q</command>
+ <command>scons -Q</command>
</scons_output>
<para>
</para>
<scons_output example="ex1" os="posix">
- <command>scons hello</command>
- <command>scons hello</command>
+ <command>scons -Q hello</command>
+ <command>scons -Q hello</command>
</scons_output>
<para>
</para>
<scons_output example="ex1" os="posix">
- <command>scons hello</command>
+ <command>scons -Q hello</command>
<command>touch hello.c</command>
- <command>scons hello</command>
+ <command>scons -Q hello</command>
</scons_output>
<para>
</para>
<scons_output example="ex1" os="posix">
- <command>scons hello</command>
- <command output="[CHANGE THE CONTENTS OF hello.c]">edit hello.c</command>
- <command>scons hello</command>
- </scons>
-
- <!--
-
- <literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- % <userinput>edit hello.c</userinput>
- [CHANGE THE CONTENTS OF hello.c]
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- %
- </literallayout>
-
- -->
+ <command>scons -Q hello</command>
+ <command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</command>
+ <command>scons -Q hello</command>
+ </scons_output>
<para>
</para>
<sconstruct>
- env = Environment()
- env.Program('hello.c')
+ Program('hello.c')
SourceSignatures('MD5')
</sconstruct>
<scons_example name="ex2">
<file name="SConstruct" printme="1">
- env = Environment()
- env.Program('hello.c')
+ Program('hello.c')
SourceSignatures('timestamp')
</file>
<file name="hello.c">
</para>
- <scons_output example="ex1" os="posix">
- <command>scons hello</command>
+ <scons_output example="ex2" os="posix">
+ <command>scons -Q hello</command>
<command>touch hello.c</command>
- <command>scons hello</command>
- </scons>
+ <command>scons -Q hello</command>
+ </scons_output>
</section>
target file is up to date or must be rebuilt.
When a target file depends on another target file,
&SCons; allows you to separately configure
- how the signatures of an "intermediate" target file
- is used when deciding if a dependent target file
+ how the signatures of "intermediate" target files
+ are used when deciding if a dependent target file
must be rebuilt.
</para>
</para>
<scons_output example="ex1" os="posix">
- <command>scons hello</command>
- <command output="[CHANGE THE CONTENTS OF hello.c]">edit hello.c</command>
- <command>scons hello</command>
- </scons>
-
- <!--
-
- <literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- % <userinput>edit hello.c</userinput>
- [CHANGE THE CONTENTS OF hello.c]
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- %
- </literallayout>
-
- -->
+ <command>scons -Q hello</command>
+ <command output=" [CHANGE THE CONTENTS OF hello.c]">edit hello.c</command>
+ <command>scons -Q hello</command>
+ </scons_output>
<para>
</para>
<sconstruct>
- env = Environment()
- env.Program('hello.c')
+ Program('hello.c')
TargetSignatures('build')
</sconstruct>
If so, then any other target files
that depend on such a built-but-not-changed target
file actually need not be rebuilt.
- You can have &SCons;
- realize that a dependent target file
- need not be rebuilt in this situation
+ You can make &SCons;
+ realize that it does not need to rebuild
+ a dependent target file in this situation
using the &TargetSignatures; function as follows:
</para>
<scons_example name="ex3">
<file name="SConstruct" printme="1">
- env = Environment()
- env.Program('hello.c')
+ Program('hello.c')
TargetSignatures('content')
</file>
<file name="hello.c">
</para>
<scons_output example="ex3" os="posix">
- <command>scons hello</command>
- <command output="[CHANGE A COMMENT IN hello.c]">edit hello.c</command>
- <command>scons hello</command>
- </scons>
+ <command>scons -Q hello</command>
+ <command output=" [CHANGE A COMMENT IN hello.c]" edit="STRIP CCCOM line">edit hello.c</command>
+ <command>scons -Q hello</command>
+ </scons_output>
<para>
<scons_example name="ex4">
<file name="SConstruct">
- env = Environment(CPPPATH = '.')
- hello = env.Program('hello.c')
+ Program('hello.c', CPPPATH = '.')
</file>
<file name="hello.c" printme="1">
- #include "hello.h"
- int
- main()
- {
- printf("Hello, %s!\n", string);
- }
+ #include "hello.h"
+ int
+ main()
+ {
+ printf("Hello, %s!\n", string);
+ }
</file>
<file name="hello.h">
- #define string "world"
+ #define string "world"
</file>
</scons_example>
<para>
- The &CPPPATH; assignment in the &Environment; call
+ The &CPPPATH; value
tells &SCons; to look in the current directory
(<literal>'.'</literal>)
for any files included by C source files
</para>
<scons_output example="ex4" os="posix">
- <command>scons hello</command>
- <command>scons hello</command>
- <command output="[CHANGE THE CONTENTS IN hello.h]">edit hello.h</command>
- <command>scons hello</command>
- </scons>
+ <command>scons -Q hello</command>
+ <command>scons -Q hello</command>
+ <command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</command>
+ <command>scons -Q hello</command>
+ </scons_output>
<para>
</para>
- <programlisting>
- </programlisting>
-
<scons_example name="ex5">
- <file name="SConstruct">
- env = Environment(CPPPATH = ['include', '/home/project/inc'])
- hello = env.Program('hello.c')
+ <file name="SConstruct" printme="1">
+ Program('hello.c', CPPPATH = ['include', '/home/project/inc'])
</file>
<file name="hello.c">
int main() { printf("Hello, world!\n"); }
</para>
- <scons_output example="ex4" os="posix">
- <command>scons hello</command>
+ <scons_output example="ex5" os="posix">
+ <command>scons -Q hello</command>
</scons_output>
<para>
</para>
- <scons_output example="ex4" os="win32">
- <command>scons hello</command>
+ <scons_output example="ex5" os="win32">
+ <command>scons -Q hello.exe</command>
</scons_output>
</section>
the implicit dependencies
that its scanners find,
for use by later builds.
- You do this either by specifying the
+ You can do this by specifying the
&implicit-cache; option on the command line:
</para>
- <scons_output example="ex1" os="win32">
- <command>scons --implicit-cache hello</command>
- <command>scons hello</command>
+ <scons_output example="ex1">
+ <command>scons -Q --implicit-cache hello</command>
+ <command>scons -Q hello</command>
</scons_output>
<para>
- Or by setting the &implicit_cache; option
+ If you don't want to specify &implicit-cache;
+ on the command line each time,
+ you can make it the default behavior for your build
+ by setting the &implicit_cache; option
in an &SConscript; file:
</para>
SetOption('implicit_cache', 1)
</sconstruct>
- <para>
+ <!--
- &SCons; does not cache implicit dependencies like this by default
- because XXX
+ <para>
+ XXX
+
</para>
<para>
-
- XXX
+ &SCons; does not cache implicit dependencies like this by default
+ because XXX
+
</para>
+ -->
+
<section>
<title>The &implicit-deps-changed; Option</title>
<para>
- XXX
+ When using cached implicit dependencies,
+ sometimes you want to "start fresh"
+ and have &SCons; re-scan the files
+ for which it previously cached the dependencies.
+ For example,
+ if you have recently installed a new version of
+ external code that you use for compilation,
+ the external header files will have changed
+ and the previously-cached implicit dependencies
+ will be out of date.
+ You can update them by
+ running &SCons; with the &implicit-deps-changed; option:
+
+ </para>
+
+ <scons_output example="ex1">
+ <command>scons -Q --implicit-deps-changed hello</command>
+ <command>scons -Q hello</command>
+ </scons_output>
+
+ <para>
+
+ In this case, &SCons; will re-scan all of the implicit dependencies
+ and cache updated copies of the information.
</para>
<para>
- XXX
+ By default when caching dependencies,
+ &SCons; notices when a file has been modified
+ and re-scans the file for any updated
+ implicit dependency information.
+ Sometimes, however, you may want
+ to force &SCons; to use the cached implicit dependencies,
+ even if the source files changed.
+ This can speed up a build for example,
+ when you have changed your source files
+ but know that you haven't changed
+ any <literal>#include</literal> lines.
+ In this case,
+ you can use the &implicit-deps-unchanged; option:
+
+ </para>
+
+ <scons_output example="ex1">
+ <command>scons -Q --implicit-deps-unchanged hello</command>
+ <command>scons -Q hello</command>
+ </scons_output>
+
+ <para>
+
+ In this case,
+ &SCons; will assume that the cached implicit
+ dependencies are correct and
+ will not bother to re-scan changed files.
+ For typical builds after small,
+ incremental changes to source files,
+ the savings may not be very big,
+ but sometimes every bit of
+ improved performance counts.
</para>
</para>
- <programlisting>
- env = Environment()
- hello = env.Program('hello.c')
- env.Ignore(hello, 'hello.h')
- </programlisting>
+ <scons_example name="ignore">
+ <file name="SConstruct" printme="1">
+ hello = Program('hello.c')
+ Ignore(hello, 'hello.h')
+ </file>
+ <file name="hello.c">
+ #include "hello.h"
+ int main() { printf("Hello, %s!\n", string); }
+ </file>
+ <file name="hello.h">
+ #define string "world"
+ </file>
+ </scons_example>
<!-- XXX mention that you can use arrays for target and source? -->
+ <!--
+ <scons_output example="ignore">
+ <command>scons -Q hello</command>
+ <command>scons -Q hello</command>
+ <command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</command>
+ <command>scons -Q hello</command>
+ XXX THIS EXAMPLE SHOULD BE UP-TO-DATE! XXX
+ </scons_output>
+ -->
+
<literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- % <userinput>scons hello</userinput>
- scons: `hello' is up to date.
- % <userinput>edit hello.h</userinput>
- [CHANGE THE CONTENTS OF hello.h]
- % <userinput>scons hello</userinput>
- scons: `hello' is up to date.
+ % <userinput>scons -Q hello</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ % <userinput>edit hello.h</userinput>
+ [CHANGE THE CONTENTS OF hello.h]
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
</literallayout>
<para>
On the other hand,
sometimes a file depends on another file
- that has no &SCons; scanner will detect.
+ that is not detected by an &SCons; scanner.
For this situation,
&SCons; allows you to specific explicitly that one file
depends on another file,
<!-- XXX mention that you can use arrays for target and source? -->
<literallayout>
- % <userinput>scons hello</userinput>
+ % <userinput>scons -Q hello</userinput>
cc -c hello.c -o hello.o
cc -o hello hello.o
- % <userinput>scons hello</userinput>
+ % <userinput>scons -Q hello</userinput>
scons: `hello' is up to date.
% <userinput>edit other_file</userinput>
[CHANGE THE CONTENTS OF other_file]
- % <userinput>scons hello</userinput>
+ % <userinput>scons -Q hello</userinput>
cc -c hello.c -o hello.o
cc -o hello hello.o
</literallayout>
</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 -Q</userinput>
+ scons: `.' is up to date.
</literallayout>
<para>
</para>
<literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q hello</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- % <userinput>scons hello</userinput>
+ % <userinput>scons -Q hello</userinput>
scons: `hello' is up to date.
- %
</literallayout>
<para>
</para>
<literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q hello</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
% <userinput>touch hello.c</userinput>
- % <userinput>scons hello</userinput>
+ % <userinput>scons -Q hello</userinput>
scons: `hello' is up to date.
- %
</literallayout>
<para>
</para>
<literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q hello</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
% <userinput>edit hello.c</userinput>
[CHANGE THE CONTENTS OF hello.c]
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q hello</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- %
</literallayout>
<para>
</para>
<programlisting>
- env = Environment()
- env.Program('hello.c')
+ Program('hello.c')
SourceSignatures('MD5')
</programlisting>
</para>
<programlisting>
- env = Environment()
- env.Program('hello.c')
+ Program('hello.c')
SourceSignatures('timestamp')
</programlisting>
</para>
<literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q hello</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
% <userinput>touch hello.c</userinput>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q hello</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- %
</literallayout>
</section>
target file is up to date or must be rebuilt.
When a target file depends on another target file,
&SCons; allows you to separately configure
- how the signatures of an "intermediate" target file
- is used when deciding if a dependent target file
+ how the signatures of "intermediate" target files
+ are used when deciding if a dependent target file
must be rebuilt.
</para>
</para>
<literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q hello</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
% <userinput>edit hello.c</userinput>
- [CHANGE THE CONTENTS OF hello.c]
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
+ [CHANGE THE CONTENTS OF hello.c]
+ % <userinput>scons -Q hello</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- %
</literallayout>
<para>
</para>
<programlisting>
- env = Environment()
- env.Program('hello.c')
+ Program('hello.c')
TargetSignatures('build')
</programlisting>
If so, then any other target files
that depend on such a built-but-not-changed target
file actually need not be rebuilt.
- You can have &SCons;
- realize that a dependent target file
- need not be rebuilt in this situation
+ You can make &SCons;
+ realize that it does not need to rebuild
+ a dependent target file in this situation
using the &TargetSignatures; function as follows:
</para>
<programlisting>
- env = Environment()
- env.Program('hello.c')
+ Program('hello.c')
TargetSignatures('content')
</programlisting>
</para>
<literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q hello</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
% <userinput>edit hello.c</userinput>
[CHANGE A COMMENT IN hello.c]
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- %
+ % <userinput>scons -Q hello</userinput>
+ cc -c -o hello.o hello.c
+ scons: `hello' is up to date.
</literallayout>
<para>
</para>
+
<programlisting>
#define string "world"
- </programlisting>
+ </programlisting>
<para>
</para>
+
<programlisting>
- env = Environment(CPPPATH = '.')
- hello = env.Program('hello.c')
- </programlisting>
+ Program('hello.c', CPPPATH = '.')
+ </programlisting>
<para>
- The &CPPPATH; assignment in the &Environment; call
+ The &CPPPATH; value
tells &SCons; to look in the current directory
(<literal>'.'</literal>)
for any files included by C source files
</para>
<literallayout>
- % <userinput>scons hello</userinput>
- cc -I. -c hello.c -o hello.o
+ % <userinput>scons -Q hello</userinput>
+ cc -I. -c -o hello.o hello.c
cc -o hello hello.o
- % <userinput>scons hello</userinput>
+ % <userinput>scons -Q hello</userinput>
scons: `hello' is up to date.
% <userinput>edit hello.h</userinput>
[CHANGE THE CONTENTS OF hello.h]
- % <userinput>scons hello</userinput>
- cc -I. -c hello.c -o hello.o
+ % <userinput>scons -Q hello</userinput>
+ cc -I. -c -o hello.o hello.c
cc -o hello hello.o
- %
</literallayout>
<para>
(':' on POSIX/Linux, ';' on Windows).
Either way, &SCons; creates the
right command-line options
- so that the followin example:
+ so that the following example:
</para>
<programlisting>
- env = Environment(CPPPATH = ['include', '/home/project/inc'])
- hello = env.Program('hello.c')
+ Program('hello.c', CPPPATH = ['include', '/home/project/inc'])
</programlisting>
<para>
</para>
<literallayout>
- % <userinput>scons hello</userinput>
- cc -Iinclude -I/home/project/inc -c hello.c -o hello.o
+ % <userinput>scons -Q hello</userinput>
+ cc -Iinclude -I/home/project/inc -c -o hello.o hello.c
cc -o hello hello.o
</literallayout>
</para>
<literallayout>
- % <userinput>scons hello</userinput>
- cl /Iinclude /I\home\project\inc /Fohello.obj hello.c
- link /OUT:hello.exe hello.obj
+ C:\><userinput>scons -Q hello.exe</userinput>
+ cl /nologo /Iinclude /I\home\project\inc /c hello.c /Fohello.obj
+ link /nologo /OUT:hello.exe hello.obj
</literallayout>
</section>
the implicit dependencies
that its scanners find,
for use by later builds.
- You do this either by specifying the
+ You can do this by specifying the
&implicit-cache; option on the command line:
</para>
<literallayout>
- % <userinput>scons --implicit-cache hello</userinput>
- cc -c hello.c -o hello.o
+ % <userinput>scons -Q --implicit-cache hello</userinput>
+ cc -c -o hello.o hello.c
cc -o hello hello.o
- % <userinput>scons hello</userinput>
+ % <userinput>scons -Q hello</userinput>
scons: `hello' is up to date.
</literallayout>
<para>
- Or by setting the &implicit_cache; option
+ If you don't want to specify &implicit-cache;
+ on the command line each time,
+ you can make it the default behavior for your build
+ by setting the &implicit_cache; option
in an &SConscript; file:
</para>
- <literallayout>
+ <programlisting>
SetOption('implicit_cache', 1)
- </literallayout>
+ </programlisting>
- <para>
+ <!--
- &SCons; does not cache implicit dependencies like this by default
- because XXX
+ <para>
+ XXX
+
</para>
<para>
-
- XXX
+ &SCons; does not cache implicit dependencies like this by default
+ because XXX
+
</para>
+ -->
+
<section>
<title>The &implicit-deps-changed; Option</title>
<para>
- XXX
+ When using cached implicit dependencies,
+ sometimes you want to "start fresh"
+ and have &SCons; re-scan the files
+ for which it previously cached the dependencies.
+ For example,
+ if you have recently installed a new version of
+ external code that you use for compilation,
+ the external header files will have changed
+ and the previously-cached implicit dependencies
+ will be out of date.
+ You can update them by
+ running &SCons; with the &implicit-deps-changed; option:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons -Q --implicit-deps-changed hello</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ </literallayout>
+
+ <para>
+
+ In this case, &SCons; will re-scan all of the implicit dependencies
+ and cache updated copies of the information.
</para>
<para>
- XXX
+ By default when caching dependencies,
+ &SCons; notices when a file has been modified
+ and re-scans the file for any updated
+ implicit dependency information.
+ Sometimes, however, you may want
+ to force &SCons; to use the cached implicit dependencies,
+ even if the source files changed.
+ This can speed up a build for example,
+ when you have changed your source files
+ but know that you haven't changed
+ any <literal>#include</literal> lines.
+ In this case,
+ you can use the &implicit-deps-unchanged; option:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons -Q --implicit-deps-unchanged hello</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ </literallayout>
+
+ <para>
+
+ In this case,
+ &SCons; will assume that the cached implicit
+ dependencies are correct and
+ will not bother to re-scan changed files.
+ For typical builds after small,
+ incremental changes to source files,
+ the savings may not be very big,
+ but sometimes every bit of
+ improved performance counts.
</para>
</para>
<programlisting>
- env = Environment()
- hello = env.Program('hello.c')
- env.Ignore(hello, 'hello.h')
+ hello = Program('hello.c')
+ Ignore(hello, 'hello.h')
</programlisting>
<!-- XXX mention that you can use arrays for target and source? -->
+ <!--
+ <scons_output example="ignore">
+ <command>scons -Q hello</command>
+ <command>scons -Q hello</command>
+ <command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</command>
+ <command>scons -Q hello</command>
+ XXX THIS EXAMPLE SHOULD BE UP-TO-DATE! XXX
+ </scons_output>
+ -->
+
<literallayout>
- % <userinput>scons hello</userinput>
- cc -c hello.c -o hello.o
- cc -o hello hello.o
- % <userinput>scons hello</userinput>
- scons: `hello' is up to date.
- % <userinput>edit hello.h</userinput>
- [CHANGE THE CONTENTS OF hello.h]
- % <userinput>scons hello</userinput>
- scons: `hello' is up to date.
+ % <userinput>scons -Q hello</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
+ % <userinput>edit hello.h</userinput>
+ [CHANGE THE CONTENTS OF hello.h]
+ % <userinput>scons -Q hello</userinput>
+ scons: `hello' is up to date.
</literallayout>
<para>
On the other hand,
sometimes a file depends on another file
- that has no &SCons; scanner will detect.
+ that is not detected by an &SCons; scanner.
For this situation,
&SCons; allows you to specific explicitly that one file
depends on another file,
<!-- XXX mention that you can use arrays for target and source? -->
<literallayout>
- % <userinput>scons hello</userinput>
+ % <userinput>scons -Q hello</userinput>
cc -c hello.c -o hello.o
cc -o hello hello.o
- % <userinput>scons hello</userinput>
+ % <userinput>scons -Q hello</userinput>
scons: `hello' is up to date.
% <userinput>edit other_file</userinput>
[CHANGE THE CONTENTS OF other_file]
- % <userinput>scons hello</userinput>
+ % <userinput>scons -Q hello</userinput>
cc -c hello.c -o hello.o
cc -o hello hello.o
</literallayout>
</para>
<scons_output example="ex1">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
in multiple directories, like main.c in the above example.
Second, unlike standard recursive use of &Make;,
- &SCons; stays in the top-level directory and
- issues commands
+ &SCons; stays in the top-level directory
+ (where the &SConstruct; file lives)
+ and issues commands that use the path names
+ from the top-level directory to the
+ target and source files within the hierarchy.
</para>
by appending a &hash; (hash mark)
to the beginning of the path name:
-
</para>
<scons_example name="ex2">
</para>
<scons_output example="ex2">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
</para>
<scons_output example="ex3">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
There are two ways to export a variable,
such as a construction environment,
- from one &SConscript; file,
+ from an &SConscript; file,
so that it may be used by other &SConscript; files.
First, you can call the &Export;
function with a list of variables,
<para>
- XXX
+ You may export more than one variable name at a time:
</para>
<para>
- XXX
+ Because white space is not legal in Python variable names,
+ the &Export; function will even automatically split
+ a string into separate names for you:
</para>
<para>
- XXX
+ Once a variable has been exported from a calling
+ &SConscript; file,
+ it may be used in other &SConscript; files
+ by calling the &Import; function:
</para>
<para>
- XXX
+ The &Import; call makes the <literal>env</literal> construction
+ environment available to the &SConscript; file,
+ after which the variable can be used to build
+ programs, libraries, etc.
+
+ </para>
+
+ <para>
+
+ Like the &Export; function,
+ the &Import; function can be used
+ with multiple variable names:
</para>
<para>
- Which is exactly equivalent to:
+ And the &Import; function will similarly
+ split a string along white-space
+ into separate variable names:
</para>
<para>
- XXX
+ Lastly, as a special case,
+ you may import all of the variables that
+ have been exported by supplying an asterisk
+ to the &Import; function:
+
+ </para>
+
+ <sconstruct>
+ Import('*')
+ env = env.Copy(DEBUG = debug)
+ env.Program('prog', ['prog.c'])
+ </sconstruct>
+
+ <para>
+
+ If you're dealing with a lot of &SConscript; files,
+ this can be a lot simpler than keeping
+ arbitrary lists of imported variables in each file.
</para>
<para>
- XXX
+ Sometimes, you would like to be able to
+ use information from a subsidiary
+ &SConscript file in some way.
+ For example,
+ suppose that you want to create one
+ library from source files
+ scattered throughout a number
+ of subsidiary &SConscript; files.
+ You can do this by using the &Return;
+ function to return values
+ from the subsidiary &SConscript; files
+ to the calling file.
</para>
- <sconstruct>
- obj = env.Object('foo.c')
- Return('obj')
- </sconstruct>
+ <para>
+
+ If, for example, we have two subdirectories
+ &foo; and &bar;
+ that should each contribute a source
+ file to a Library,
+ what we'd like to be able to do is
+ collect the object files
+ from the subsidiary &SConscript; calls
+ like this:
+
+ </para>
+
+ <scons_example name="Return">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ Export('env')
+ objs = []
+ for subdir in ['foo', 'bar']:
+ o = SConscript('%s/SConscript' % subdir)
+ objs.append(o)
+ env.Library('prog', objs)
+ </file>
+ <directory name="foo"></directory>
+ <directory name="bar"></directory>
+ <file name="foo/SConscript">
+ Import('env')
+ obj = env.Object('foo.c')
+ Return('obj')
+ </file>
+ <file name="bar/SConscript">
+ Import('env')
+ obj = env.Object('bar.c')
+ Return('obj')
+ </file>
+ <file name="foo/foo.c">
+ void foo(void) { printf("foo/foo.c\n"); }
+ </file>
+ <file name="bar/bar.c">
+ void bar(void) { printf("bar/bar.c\n"); }
+ </file>
+ </scons_example>
<para>
- XXX
+ We can do this by using the &Return;
+ function in the
+ <literal>foo/SConscript</literal> file like this:
</para>
- <sconstruct>
- objs = []
- for subdir in ['foo', 'bar']:
- o = SConscript('%s/SConscript' % subdir)
- objs.append(o)
- env.Library('prog', objs)
- </sconstruct>
+ <scons_example_file example="Return" name="foo/SConscript">
+ </scons_example_file>
<para>
- XXX
+ (The corresponding
+ <literal>bar/SConscript</literal>
+ file should be pretty obvious.)
+ Then when we run &SCons;,
+ the object files from the subsidiary subdirectories
+ are all correctly archived in the desired library:
</para>
+ <scons_output example="Return">
+ <command>scons -Q</command>
+ </scons_output>
+
</section>
</section>
</para>
+
<programlisting>
env = Environment()
env.Program('prog1', ['main.c', 'foo1.c', 'foo2.c'])
- </programlisting>
+ </programlisting>
<para>
</para>
+
<programlisting>
env = Environment()
env.Program('prog2', ['main.c', 'bar1.c', 'bar2.c'])
- </programlisting>
+ </programlisting>
<para>
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c prog1/foo1.c -o prog1/foo1.o
- cc -c prog1/foo2.c -o prog1/foo2.o
- cc -c prog1/main.c -o prog1/main.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o prog1/foo1.o prog1/foo1.c
+ cc -c -o prog1/foo2.o prog1/foo2.c
+ cc -c -o prog1/main.o prog1/main.c
cc -o prog1/prog1 prog1/main.o prog1/foo1.o prog1/foo2.o
- cc -c prog2/bar1.c -o prog2/bar1.o
- cc -c prog2/bar2.c -o prog2/bar2.o
- cc -c prog2/main.c -o prog2/main.o
+ cc -c -o prog2/bar1.o prog2/bar1.c
+ cc -c -o prog2/bar2.o prog2/bar2.c
+ cc -c -o prog2/main.o prog2/main.c
cc -o prog2/prog2 prog2/main.o prog2/bar1.o prog2/bar2.o
</literallayout>
in multiple directories, like main.c in the above example.
Second, unlike standard recursive use of &Make;,
- &SCons; stays in the top-level directory and
- issues commands
+ &SCons; stays in the top-level directory
+ (where the &SConstruct; file lives)
+ and issues commands that use the path names
+ from the top-level directory to the
+ target and source files within the hierarchy.
</para>
by appending a &hash; (hash mark)
to the beginning of the path name:
-
</para>
- <literallayout>
+ <programlisting>
env = Environment()
env.Program('prog', ['main.c', '#lib/foo1.c', 'foo2.c'])
- </literallayout>
+ </programlisting>
<para>
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c lib/foo1.c -o lib/foo1.o
- cc -c src/prog/foo2.c -o src/prog/foo2.o
- cc -c src/prog/main.c -o src/prog/main.o
- cc -o src/prog/prog prog/main.o lib/foo1.o prog/foo2.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o lib/foo1.o lib/foo1.c
+ cc -c -o src/prog/foo2.o src/prog/foo2.c
+ cc -c -o src/prog/main.o src/prog/main.c
+ cc -o src/prog/prog src/prog/main.o lib/foo1.o src/prog/foo2.o
</literallayout>
<para>
</para>
- <literallayout>
+ <programlisting>
env = Environment()
env.Program('prog', ['main.c', '/usr/joe/lib/foo1.c', 'foo2.c'])
- </literallayout>
+ </programlisting>
<para>
</para>
<literallayout>
- % <userinput>scons</userinput>
- cc -c /usr/joe/lib/foo1.c -o /usr/joe/lib/foo1.o
- cc -c src/prog/foo2.c -o src/prog/foo2.o
- cc -c src/prog/main.c -o src/prog/main.o
- cc -o src/prog/prog prog/main.o /usr/joe/lib/foo1.o prog/foo2.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o src/prog/foo2.o src/prog/foo2.c
+ cc -c -o src/prog/main.o src/prog/main.c
+ cc -c -o /usr/joe/lib/foo1.o /usr/joe/lib/foo1.c
+ cc -o src/prog/prog src/prog/main.o /usr/joe/lib/foo1.o src/prog/foo2.o
</literallayout>
<para>
There are two ways to export a variable,
such as a construction environment,
- from one &SConscript; file,
+ from an &SConscript; file,
so that it may be used by other &SConscript; files.
First, you can call the &Export;
function with a list of variables,
<para>
- XXX
+ You may export more than one variable name at a time:
</para>
<para>
- XXX
+ Because white space is not legal in Python variable names,
+ the &Export; function will even automatically split
+ a string into separate names for you:
</para>
<para>
Second, you can specify a list of
- variables to exported as a second argument
+ variables to export as a second argument
to the &SConscript; function call:
</para>
<para>
- XXX
+ Once a variable has been exported from a calling
+ &SConscript; file,
+ it may be used in other &SConscript; files
+ by calling the &Import; function:
</para>
<para>
- XXX
+ The &Import; call makes the <literal>env</literal> construction
+ environment available to the &SConscript; file,
+ after which the variable can be used to build
+ programs, libraries, etc.
+
+ </para>
+
+ <para>
+
+ Like the &Export; function,
+ the &Import; function can be used
+ with multiple variable names:
</para>
<para>
- Which is exactly equivalent to:
+ And the &Import; function will similarly
+ split a string along white-space
+ into separate variable names:
</para>
<para>
- XXX
+ Lastly, as a special case,
+ you may import all of the variables that
+ have been exported by supplying an asterisk
+ to the &Import; function:
+
+ </para>
+
+ <programlisting>
+ Import('*')
+ env = env.Copy(DEBUG = debug)
+ env.Program('prog', ['prog.c'])
+ </programlisting>
+
+ <para>
+
+ If you're dealing with a lot of &SConscript; files,
+ this can be a lot simpler than keeping
+ arbitrary lists of imported variables in each file.
</para>
<para>
- XXX
+ Sometimes, you would like to be able to
+ use information from a subsidiary
+ &SConscript; file in some way.
+ For example,
+ suppose that you want to create one
+ library from source files
+ scattered throughout a number
+ of subsidiary &SConscript; files.
+ You can do this by using the &Return;
+ function to return values
+ from the subsidiary &SConscript; files
+ to the calling file.
+
+ </para>
+
+ <para>
+
+ If, for example, we have two subdirectories
+ &foo; and &bar;
+ that should each contribute a source
+ file to a Library,
+ what we'd like to be able to do is
+ collect the object files
+ from the subsidiary &SConscript; calls
+ like this:
</para>
<programlisting>
- obj = env.Object('foo.c')
- Return('obj')
+ env = Environment()
+ Export('env')
+ objs = []
+ for subdir in ['foo', 'bar']:
+ o = SConscript('%s/SConscript' % subdir)
+ objs.append(o)
+ env.Library('prog', objs)
</programlisting>
<para>
- XXX
+ We can do this by using the &Return;
+ function in the
+ <literal>foo/SConscript</literal> file like this:
</para>
+
<programlisting>
- objs = []
- for subdir in ['foo', 'bar']:
- o = SConscript('%s/SConscript' % subdir)
- objs.append(o)
- env.Library('prog', objs)
- </programlisting>
+ Import('env')
+ obj = env.Object('foo.c')
+ Return('obj')
+ </programlisting>
<para>
- XXX
+ (The corresponding
+ <literal>bar/SConscript</literal>
+ file should be pretty obvious.)
+ Then when we run &SCons;,
+ the object files from the subsidiary subdirectories
+ are all correctly archived in the desired library:
</para>
+ <literallayout>
+ % <userinput>scons -Q</userinput>
+ cc -c -o bar/bar.o bar/bar.c
+ cc -c -o foo/foo.o foo/foo.c
+ ar r libprog.a foo/foo.o bar/bar.o
+ ranlib libprog.a
+ </literallayout>
+
</section>
</section>
&simple;
</chapter>
- <chapter id="chap-environments">
- <title>Construction Environments</title>
- &environments;
- </chapter>
-
<chapter id="chap-libraries">
<title>Building and Linking with Libraries</title>
&libraries;
&depends;
</chapter>
+ <chapter id="chap-environments">
+ <title>Construction Environments</title>
+ &environments;
+ </chapter>
+
<chapter id="chap-default">
<title>Default Targets</title>
&default;
&variants;
</chapter>
+ <!--
+
<chapter id="chap-builders-built-in">
<title>Built-In Builders</title>
&builders-built-in;
</chapter>
+ -->
+
<chapter id="chap-builders-writing">
<title>Writing Your Own Builders</title>
&builders-writing;
&builders-commands;
</chapter>
+ <!--
+
<chapter id="chap-actions">
<title>SCons Actions</title>
&actions;
</chapter>
+ -->
+
<chapter id="chap-scanners">
<title>Writing Scanners</title>
&scanners;
&repositories;
</chapter>
+ <!--
+
<chapter id="chap-sourcecode">
<title>Fetching Files From Source Code Management Systems</title>
&sourcecode;
</chapter>
+ -->
+
<chapter id="chap-caching">
<title>Caching Built Files</title>
&caching;
&alias;
</chapter>
+ <!--
+
<chapter id="chap-run">
<title>How to Run &SCons;</title>
&run;
&troubleshoot;
</chapter>
+ -->
+
<!--
AddPostAction()
AddPreAction()
Tools()
-->
+ <!--
+
<appendix id="app-example">
<title>Complex &SCons; Example</title>
&example;
&ant;
</appendix>
+ -->
+
</book>
&simple;
</chapter>
- <chapter id="chap-environments">
- <title>Construction Environments</title>
- &environments;
- </chapter>
-
<chapter id="chap-libraries">
<title>Building and Linking with Libraries</title>
&libraries;
&depends;
</chapter>
+ <chapter id="chap-environments">
+ <title>Construction Environments</title>
+ &environments;
+ </chapter>
+
<chapter id="chap-default">
<title>Default Targets</title>
&default;
&variants;
</chapter>
+ <!--
+
<chapter id="chap-builders-built-in">
<title>Built-In Builders</title>
&builders-built-in;
</chapter>
+ -->
+
<chapter id="chap-builders-writing">
<title>Writing Your Own Builders</title>
&builders-writing;
&builders-commands;
</chapter>
+ <!--
+
<chapter id="chap-actions">
<title>SCons Actions</title>
&actions;
</chapter>
+ -->
+
<chapter id="chap-scanners">
<title>Writing Scanners</title>
&scanners;
&repositories;
</chapter>
+ <!--
+
<chapter id="chap-sourcecode">
<title>Fetching Files From Source Code Management Systems</title>
&sourcecode;
</chapter>
+ -->
+
<chapter id="chap-caching">
<title>Caching Built Files</title>
&caching;
&alias;
</chapter>
+ <!--
+
<chapter id="chap-run">
<title>How to Run &SCons;</title>
&run;
&troubleshoot;
</chapter>
+ -->
+
<!--
AddPostAction()
AddPreAction()
Tools()
-->
+ <!--
+
<appendix id="app-example">
<title>Complex &SCons; Example</title>
&example;
&ant;
</appendix>
+ -->
+
</book>
<emphasis>easier</emphasis>
for non-programmers to learn
than the cryptic languages of other build tools,
- which are usally invented by programmers for other programmers.
- This is in no small part to the
+ which are usually invented by programmers for other programmers.
+ This is in no small part due to the
consistency and readability that are built in to Python.
It just so happens that making a real, live
scripting language the basis for the
</para>
+ <!--
+
<section>
<title>Why &SCons;?</title>
</section>
+ -->
+
<section>
<title>&SCons; Principles</title>
down the default &SCons; behavior to guarantee a correct build,
we also try to make it easy to speed up &SCons;
through optimization options that let you trade off
- guaranteed correctness for speed.
+ guaranteed correctness in all end cases for
+ a speedier build in the usual cases.
</para>
</listitem>
</section>
+ <!--
+
<section>
<title>History</title>
</section>
+ -->
+
<!--
<section>
and time people have contributed over the past few years.
The "core team"
of Chad Austin, Anthony Roach, Charles Crain,
- Steve Leblanc, Greg Spencer and Christoph Wiedemann
+ Steve Leblanc, Gary Oerbrunner, Greg Spencer and Christoph Wiedemann
have been great about reviewing my (and other) changes
and catching problems before they get in the code base.
Of particular technical note:
<para>
Special thanks to David Snopek for contributing
- his underlying "Autocons" code that formed
+ his underlying "Autoscons" code that formed
the basis of Christoph's work with the Configure functionality.
David was extremely generous in making
this code available to &SCons;,
</para>
+ <!--
+
<para>
&SCons; has received contributions
Jeff Petkau (significant fixes for CacheDir and other areas),
Stefan Reichor (Ghostscript support),
Zed Shaw (Append() and Replace() environment methods),
- Terrel Shumway (build and test fixes, as well as the SCons Wiki),
- sam th (dynamic checks for utilities)
- and Moshe Zadke (Debian packaging).
+ Terrel Shumway (build and test fixes, as well as the SCons Wiki)
+ and
+ sam th (dynamic checks for utilities).
</para>
+ -->
+
<para>
Thanks to Peter Miller
<emphasis>easier</emphasis>
for non-programmers to learn
than the cryptic languages of other build tools,
- which are usally invented by programmers for other programmers.
- This is in no small part to the
+ which are usually invented by programmers for other programmers.
+ This is in no small part due to the
consistency and readability that are built in to Python.
It just so happens that making a real, live
scripting language the basis for the
</para>
+ <!--
+
<section>
<title>Why &SCons;?</title>
</section>
+ -->
+
<section>
<title>&SCons; Principles</title>
<para>
There are a few overriding principles
- we try to live up to in designing and implementing &SCons:
+ we try to live up to in designing and implementing &SCons;:
</para>
down the default &SCons; behavior to guarantee a correct build,
we also try to make it easy to speed up &SCons;
through optimization options that let you trade off
- guaranteed correctness for speed.
+ guaranteed correctness in all end cases for
+ a speedier build in the usual cases.
</para>
</listitem>
</section>
+ <!--
+
<section>
<title>History</title>
</section>
+ -->
+
<!--
<section>
and time people have contributed over the past few years.
The "core team"
of Chad Austin, Anthony Roach, Charles Crain,
- Steve Leblanc, Greg Spencer and Christoph Wiedemann
+ Steve Leblanc, Gary Oerbrunner, Greg Spencer and Christoph Wiedemann
have been great about reviewing my (and other) changes
and catching problems before they get in the code base.
Of particular technical note:
<para>
Special thanks to David Snopek for contributing
- his underlying "Autocons" code that formed
+ his underlying "Autoscons" code that formed
the basis of Christoph's work with the Configure functionality.
David was extremely generous in making
this code available to &SCons;,
</para>
+ <!--
+
<para>
&SCons; has received contributions
Jeff Petkau (significant fixes for CacheDir and other areas),
Stefan Reichor (Ghostscript support),
Zed Shaw (Append() and Replace() environment methods),
- Terrel Shumway (build and test fixes, as well as the SCons Wiki),
- sam th (dynamic checks for utilities)
- and Moshe Zadke (Debian packaging).
+ Terrel Shumway (build and test fixes, as well as the SCons Wiki)
+ and
+ sam th (dynamic checks for utilities).
</para>
+ -->
+
<para>
Thanks to Peter Miller
<para>
- If you want to receive announcements about &SCons,
+ If you want to receive announcements about &SCons;,
join the low-volume &scons-announce; mailing list.
</para>
and next under the <filename>/usr/repository2</filename> tree.
&SCons; expects that any files it searches
for will be found in the same position
- relative to the top-level directory XXX
+ relative to the top-level directory.
In the above example, if the &hello_c; file is not
found in the local build tree,
&SCons; will search first for
</para>
<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>
gcc -c /usr/repository1/hello.c -o hello.o
gcc -o hello hello.o
</scons_output>
</scons_example>
<scons_output example="ex3">
- <command>scons</command>
+ <command>scons -Q</command>
</scons_output>
<para>
</para>
<literallayout>
- % <userinput>scons -Y /usr/repository1 -Y /usr/repository2</userinput>
+ % <userinput>scons -Q -Y /usr/repository1 -Y /usr/repository2</userinput>
</literallayout>
<para>
<scons_example name="ex4">
<file name="SConstruct">
env = Environment()
- env.Program('hello.c')
+ env.Program(['hello.c', 'file1.c', 'file2.c'])
Repository('/usr/repository1', '/usr/repository2')
</file>
<file name="hello.c">
int main() { printf("Hello, world!\n"); }
</file>
+ <file name="file1.c">
+ int f1() { printf("file1\n"); }
+ </file>
+ <file name="file2.c">
+ int f2() { printf("file2.c\n"); }
+ </file>
</scons_example>
- <literallayout>
- % <userinput>cd /usr/repository1</userinput>
- % <userinput>scons</userinput>
- gcc -c hello.c -o hello.o
- gcc -o hello hello.o
- </literallayout>
+ <scons_output example="ex4">
+ <command>cd /usr/repository1</command>
+ <command>scons -Q</command>
+ </scons_output>
<para>
</para>
+ <!--
+ <scons_output example="ex4">
+ <command>cd $HOME/build</command>
+ <command>edit hello.c</command>
+ <command>scons -Q -Y __ROOT__/usr/repository1</command>
+ </scons_output>
+ -->
<literallayout>
% <userinput>cd $HOME/build</userinput>
% <userinput>edit hello.c</userinput>
- % <userinput>scons -Y /usr/repository1</userinput>
- gcc -c hello.c -o hello.o
- gcc -o hello hello.o
- XXXXXXX
+ % <userinput>scons -Q -Y /usr/repository1</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o /usr/repository1/file1.o /usr/repository1/file2.o
</literallayout>
<para>
Notice that &SCons; realizes that it does not need to
- rebuild a local XXX.o file,
- but instead uses the already-compiled XXX.o file
+ rebuild local copies file1.o and file2.o files,
+ but instead uses the already-compiled files
from the repository.
</para>
<literallayout>
% <userinput>mkdir $HOME/build2</userinput>
% <userinput>cd $HOME/build2</userinput>
- % <userinput>scons -Y /usr/all/repository hello</userinput>
+ % <userinput>scons -Q -Y /usr/all/repository hello</userinput>
scons: `hello' is up-to-date.
</literallayout>
</para>
- <scons_example name="ex1">
+ <scons_example name="ex5">
<file name="SConstruct" printme="1">
env = Environment()
hello = env.Program('hello.c')
% scons -Y /usr/all/repository hello
Local copy of hello from /usr/all/repository/hello
scons: `hello' is up-to-date.
- XXXXXX DO WE REALLY REPORT up-to-date, TOO?
</literallayout>
<para>
(Notice that, because the act of making the local copy
is not considered a "build" of the &hello; file,
&SCons; still reports that it is up-to-date.)
- XXXXXX DO WE REALLY REPORT up-to-date, TOO?
</para>
and next under the <filename>/usr/repository2</filename> tree.
&SCons; expects that any files it searches
for will be found in the same position
- relative to the top-level directory XXX
+ relative to the top-level directory.
In the above example, if the &hello_c; file is not
found in the local build tree,
&SCons; will search first for
</para>
<literallayout>
- % <userinput>scons</userinput>
- gcc -c hello.c -o hello.o
- gcc -o hello hello.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
</literallayout>
<para>
</para>
+
+
<literallayout>
- % <userinput>scons</userinput>
+ % <userinput>scons -Q</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
gcc -c /usr/repository1/hello.c -o hello.o
gcc -o hello hello.o
</literallayout>
</para>
+
+
<literallayout>
- % <userinput>scons</userinput>
- gcc -c /usr/repository2/hello.c -o hello.o
- gcc -o hello hello.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
</literallayout>
<para>
</para>
<literallayout>
- % <userinput>scons -Y /usr/repository1 -Y /usr/repository2</userinput>
+ % <userinput>scons -Q -Y /usr/repository1 -Y /usr/repository2</userinput>
</literallayout>
<para>
</para>
+
+
<literallayout>
% <userinput>cd /usr/repository1</userinput>
- % <userinput>scons</userinput>
- gcc -c hello.c -o hello.o
- gcc -o hello hello.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o file1.o file1.c
+ cc -c -o file2.o file2.c
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o file1.o file2.o
</literallayout>
<para>
</para>
+ <!--
+ <scons_output example="ex4">
+ <command>cd $HOME/build</command>
+ <command>edit hello.c</command>
+ <command>scons -Q -Y __ROOT__/usr/repository1</command>
+ </scons_output>
+ -->
<literallayout>
% <userinput>cd $HOME/build</userinput>
% <userinput>edit hello.c</userinput>
- % <userinput>scons -Y /usr/repository1</userinput>
- gcc -c hello.c -o hello.o
- gcc -o hello hello.o
- XXXXXXX
+ % <userinput>scons -Q -Y /usr/repository1</userinput>
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o /usr/repository1/file1.o /usr/repository1/file2.o
</literallayout>
<para>
Notice that &SCons; realizes that it does not need to
- rebuild a local XXX.o file,
- but instead uses the already-compiled XXX.o file
+ rebuild local copies file1.o and file2.o files,
+ but instead uses the already-compiled files
from the repository.
</para>
<literallayout>
% <userinput>mkdir $HOME/build2</userinput>
% <userinput>cd $HOME/build2</userinput>
- % <userinput>scons -Y /usr/all/repository hello</userinput>
+ % <userinput>scons -Q -Y /usr/all/repository hello</userinput>
scons: `hello' is up-to-date.
</literallayout>
% scons -Y /usr/all/repository hello
Local copy of hello from /usr/all/repository/hello
scons: `hello' is up-to-date.
- XXXXXX DO WE REALLY REPORT up-to-date, TOO?
</literallayout>
<para>
(Notice that, because the act of making the local copy
is not considered a "build" of the &hello; file,
&SCons; still reports that it is up-to-date.)
- XXXXXX DO WE REALLY REPORT up-to-date, TOO?
</para>
-->
- <para>
+ <para>
- XXX
+ &SCons; has built-in scanners that know how to look in
+ C, Fortran and IDL source files for information about
+ other files that targets built from those files depend on--for example,
+ in the case of files that use the C preprocessor,
+ the <filename>.h</filename> files that are specified
+ using <literal>#include</literal> lines in the source.
+ You can use the same mechanisms that &SCons; uses to create
+ its built-in scanners to write scanners of your own for file types
+ that &SCons; does not know how to scan "out of the box."
+
+ </para>
- </para>
+ <section>
+ <title>A Simple Scanner Example</title>
- <section>
- <title>XXX</title>
+ <para>
- <para>
+ Suppose, for example, that we want to create a simple scanner
+ for <filename>.foo</filename> files.
+ A <filename>.foo</filename> file contains some text that
+ will be processed,
+ and can include other files on lines that begin
+ with <literal>include</literal>
+ followed by a file name:
- XXX
+ </para>
- </para>
+ <programlisting>
+ include filename.foo
+ </programlisting>
- </section>
+ <para>
+
+ Scanning a file will be handled by a Python function
+ that you must supply.
+ Here is a function that will use the Python
+ <filename>re</filename> module
+ to scan for the <literal>include</literal> lines in our example:
+
+ </para>
+
+ <programlisting>
+ import re
+
+ include_re = re.compile(r'^include\\s+(\\S+)$', re.M)
+
+ def kfile_scan(node, env, path, arg):
+ contents = node.get_contents()
+ return include_re.findall(contents)
+ </programlisting>
+
+ <para>
+
+ The scanner function must
+ accept the four specified arguments
+ and return a list of implicit dependencies.
+ Presumably, these would be dependencies found
+ from examining the contents of the file,
+ although the function can perform any
+ manipulation at all to generate the list of
+ dependencies.
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>node</term>
+
+ <listitem>
+ <para>
+
+ An &SCons; node object representing the file being scanned.
+ The path name to the file can be
+ used by converting the node to a string
+ using the <literal>str()</literal> function,
+ or an internal &SCons; <literal>get_contents()</literal>
+ object method can be used to fetch the contents.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>env</term>
+
+ <listitem>
+ <para>
+
+ The construction environment in effect for this scan.
+ The scanner function may choose to use construction
+ variables from this environment to affect its behavior.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>path</term>
+
+ <listitem>
+ <para>
+
+ A list of directories that form the search path for included files
+ for this scanner.
+ This is how &SCons; handles the &CPPPATH; and &LIBPATH;
+ variables.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>arg</term>
+
+ <listitem>
+ <para>
+
+ An optional argument that you can choose to
+ have passed to this scanner function by
+ various scanner instances.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ A Scanner object is created using the &Scanner; function,
+ which typically takes an <literal>skeys</literal> argument
+ to associate the type of file suffix with this scanner.
+ The Scanner object must then be associated with the
+ &SCANNERS; construction variable of a construction environment,
+ typically by using the &Append; method:
+
+ </para>
+
+ <programlisting>
+ kscan = Scanner(function = kfile_scan,
+ skeys = ['.k'])
+ env.Append(SCANNERS = kscan)
+ </programlisting>
+
+ <para>
+
+ When we put it all together, it looks like:
+
+ </para>
+
+ <scons_example name="scan">
+ <file name="SConstruct" printme="1">
+ import re
+
+ include_re = re.compile(r'^include\\s+(\\S+)$', re.M)
+
+ def kfile_scan(node, env, path):
+ contents = node.get_contents()
+ includes = include_re.findall(contents)
+ return includes
+
+ kscan = Scanner(function = kfile_scan,
+ skeys = ['.k'])
+
+ env = Environment(ENV = {'PATH' : '__ROOT__/usr/local/bin'})
+ env.Append(SCANNERS = kscan)
+
+ env.Command('foo', 'foo.k', 'kprocess < $SOURCES > $TARGET')
+ </file>
+ <file name="foo.k">
+ include other_file
+ </file>
+ <file name="other_file">
+ other_file
+ </file>
+ <directory name="__ROOT__/usr"></directory>
+ <directory name="__ROOT__/usr/local"></directory>
+ <directory name="__ROOT__/usr/local/bin"></directory>
+ <file name="__ROOT_/usr/local/bin/kprocess" chmod="755">
+ cat
+ </file>
+ </scons_example>
+
+ <!--
+
+ <para>
+
+ Now if we run &scons;
+ and then re-run it after changing the contents of
+ <filename>other_file</filename>,
+ the <filename>foo</filename>
+ target file will be automatically rebuilt:
+
+ </para>
+
+ <scons_output example="scan">
+ <command>scons -Q</command>
+ <command output=" [CHANGE THE CONTENTS OF other_file]">edit other_file</command>
+ <command>scons -Q</command>
+ <command>scons -Q</command>
+ </scons_output>
+
+ -->
+
+ </section>
-->
- <para>
+ <para>
- XXX
+ &SCons; has built-in scanners that know how to look in
+ C, Fortran and IDL source files for information about
+ other files that targets built from those files depend on--for example,
+ in the case of files that use the C preprocessor,
+ the <filename>.h</filename> files that are specified
+ using <literal>#include</literal> lines in the source.
+ You can use the same mechanisms that &SCons; uses to create
+ its built-in scanners to write scanners of your own for file types
+ that &SCons; does not know how to scan "out of the box."
+
+ </para>
- </para>
+ <section>
+ <title>A Simple Scanner Example</title>
- <section>
- <title>XXX</title>
+ <para>
- <para>
+ Suppose, for example, that we want to create a simple scanner
+ for <filename>.foo</filename> files.
+ A <filename>.foo</filename> file contains some text that
+ will be processed,
+ and can include other files on lines that begin
+ with <literal>include</literal>
+ followed by a file name:
- XXX
+ </para>
- </para>
+ <programlisting>
+ include filename.foo
+ </programlisting>
- </section>
+ <para>
+
+ Scanning a file will be handled by a Python function
+ that you must supply.
+ Here is a function that will use the Python
+ <filename>re</filename> module
+ to scan for the <literal>include</literal> lines in our example:
+
+ </para>
+
+ <programlisting>
+ import re
+
+ include_re = re.compile(r'^include\\s+(\\S+)$', re.M)
+
+ def kfile_scan(node, env, path, arg):
+ contents = node.get_contents()
+ return include_re.findall(contents)
+ </programlisting>
+
+ <para>
+
+ The scanner function must
+ accept the four specified arguments
+ and return a list of implicit dependencies.
+ Presumably, these would be dependencies found
+ from examining the contents of the file,
+ although the function can perform any
+ manipulation at all to generate the list of
+ dependencies.
+
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>node</term>
+
+ <listitem>
+ <para>
+
+ An &SCons; node object representing the file being scanned.
+ The path name to the file can be
+ used by converting the node to a string
+ using the <literal>str()</literal> function,
+ or an internal &SCons; <literal>get_contents()</literal>
+ object method can be used to fetch the contents.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>env</term>
+
+ <listitem>
+ <para>
+
+ The construction environment in effect for this scan.
+ The scanner function may choose to use construction
+ variables from this environment to affect its behavior.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>path</term>
+
+ <listitem>
+ <para>
+
+ A list of directories that form the search path for included files
+ for this scanner.
+ This is how &SCons; handles the &CPPPATH; and &LIBPATH;
+ variables.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>arg</term>
+
+ <listitem>
+ <para>
+
+ An optional argument that you can choose to
+ have passed to this scanner function by
+ various scanner instances.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+
+ A Scanner object is created using the &Scanner; function,
+ which typically takes an <literal>skeys</literal> argument
+ to associate the type of file suffix with this scanner.
+ The Scanner object must then be associated with the
+ &SCANNERS; construction variable of a construction environment,
+ typically by using the &Append; method:
+
+ </para>
+
+ <programlisting>
+ kscan = Scanner(function = kfile_scan,
+ skeys = ['.k'])
+ env.Append(SCANNERS = kscan)
+ </programlisting>
+
+ <para>
+
+ When we put it all together, it looks like:
+
+ </para>
+
+ <programlisting>
+ import re
+
+ include_re = re.compile(r'^include\\s+(\\S+)$', re.M)
+
+ def kfile_scan(node, env, path):
+ contents = node.get_contents()
+ includes = include_re.findall(contents)
+ return includes
+
+ kscan = Scanner(function = kfile_scan,
+ skeys = ['.k'])
+
+ env = Environment(ENV = {'PATH' : '/usr/local/bin'})
+ env.Append(SCANNERS = kscan)
+
+ env.Command('foo', 'foo.k', 'kprocess < $SOURCES > $TARGET')
+ </programlisting>
+
+ <!--
+
+ <para>
+
+ Now if we run &scons;
+ and then re-run it after changing the contents of
+ <filename>other_file</filename>,
+ the <filename>foo</filename>
+ target file will be automatically rebuilt:
+
+ </para>
+
+ <scons_output example="scan">
+ <command>scons -Q</command>
+ <command output=" [CHANGE THE CONTENTS OF other_file]">edit other_file</command>
+ <command>scons -Q</command>
+ <command>scons -Q</command>
+ </scons_output>
+
+ -->
+
+ </section>
The most straightforward way to establish a build directory
uses the fact that the usual way to
- set up a build hierarcy is to have an
+ set up a build hierarchy is to have an
&SConscript; file in the source subdirectory.
If you then pass a &build_dir; argument to the
&SConscript; function call:
</para>
- <sconstruct>
- SConscript('src/SConscript', build_dir='build')
- </sconstruct>
-
- <para>
-
- &SCons; will then build all of the files in
- the &build; subdirectory:
-
- </para>
-
<scons_example name="ex1">
<file name="SConstruct" printme="1">
+ SConscript('src/SConscript', build_dir='build')
+ </file>
+ <file name="src/SConscript">
env = Environment()
env.Program('hello.c')
</file>
- <file name="hello.c">
+ <file name="src/hello.c">
int main() { printf("Hello, world!\n"); }
</file>
</scons_example>
+ <para>
+
+ &SCons; will then build all of the files in
+ the &build; subdirectory:
+
+ </para>
+
<scons_output example="ex1">
- <command>ls -1 src</command>
- <command>scons</command>
- <command>ls -1 build</command>
+ <command>ls src</command>
+ <command>scons -Q</command>
+ <command>ls build</command>
</scons_output>
<para>
&SCons; duplicates source files in build directories
because it's the most straightforward way to guarantee a correct build
- <emphasis>regardless of include-file directory paths</emphasis>,
+ <emphasis>regardless of include-file directory paths,
+ relative references between files,
+ or tool support for putting files in different locations</emphasis>,
and the &SCons; philosophy is to, by default,
guarantee a correct build in all cases.
- Here is an example of an end case where duplicating
- source files in a build directory
- is necessary for a correct build:
</para>
<para>
- XXX
+ The most direct reason to duplicate source files
+ in build directories
+ is simply that some tools (mostly older vesions)
+ are written to only build their output files
+ in the same directory as the source files.
+ In this case, the choices are either
+ to build the output file in the source directory
+ and move it to the build directory,
+ or to duplicate the source files in the build directory.
+
+ </para>
+
+ <para>
+
+ Additionally,
+ relative references between files
+ can cause problems if we don't
+ just duplicate the hierarchy of source files
+ in the build directory.
+ You can see this at work in
+ use of the C preprocessor <literal>#include</literal>
+ mechanism with double quotes, not angle brackets:
</para>
<sconstruct>
- env = Environmnet()
+ #include "file.h"
</sconstruct>
<para>
- XXX
+ The <emphasis>de facto</emphasis> standard behavior
+ for most C compilers in this case
+ is to first look in the same directory
+ as the source file that contains the <literal>#include</literal> line,
+ then to look in the directories in the preprocessor search path.
+ Add to this that the &SCons; implementation of
+ support for code repositories
+ (described below)
+ means not all of the files
+ will be found in the same directory hierarchy,
+ and the simplest way to make sure
+ that the right include file is found
+ is to duplicate the source files into the build directory,
+ which provides a correct build
+ regardless of the original location(s) of the source files.
</para>
- <literallayout>
- % <userinput>scons</userinput>
- cc -c build/hello.c -o build/hello.o
- cc -o build/hello build/hello.o
- </literallayout>
+ <para>
- </section>
+ Although source-file duplication guarantees a correct build
+ even in these end-cases,
+ it <emphasis>can</emphasis> usually be safely disabled.
+ The next section describes
+ how you can disable the duplication of source files
+ in the build directory.
+
+ </para>
+
+ </section>
<section>
<title>Telling &SCons; to Not Duplicate Source Files in the Build Directory</title>
<para>
- In most cases, however,
- having &SCons; place its target files in a build subdirectory
+ In most cases and with most tool sets,
+ &SCons; can place its target files in a build subdirectory
<emphasis>without</emphasis>
- duplicating the source files works just fine.
+ duplicating the source files
+ and everything will work just fine.
You can disable the default &SCons; behavior
by specifying <literal>duplicate=0</literal>
when you call the &SConscript; function:
</para>
<literallayout>
- % <userinput>ls -1 src</userinput>
+ % <userinput>ls src</userinput>
SConscript
hello.c
- % <userinput>scons</userinput>
+ % <userinput>scons -Q</userinput>
cc -c src/hello.c -o build/hello.o
cc -o build/hello build/hello.o
- % <userinput>ls -1 build</userinput>
+ % <userinput>ls build</userinput>
hello
hello.o
</literallayout>
<para>
- XXX
-
- </para>
-
- <para>
-
When using the &BuildDir; function directly,
&SCons; still duplicates the source files
in the build directory by default:
<scons_output example="ex_builddir">
<command>ls src</command>
- <command>scons</command>
- <command>ls -1 build</command>
+ <command>scons -Q</command>
+ <command>ls build</command>
</scons_output>
<para>
<scons_output example="ex_duplicate_0">
<command>ls src</command>
- <command>scons</command>
- <command>ls -1 build</command>
+ <command>scons -Q</command>
+ <command>ls build</command>
</scons_output>
</section>
</para>
<scons_example name="example_builddir_sconscript">
- <file name="SConstruct" printme="1">
+ <file name="SConstruct">
+ BuildDir('build', 'src')
+ SConscript('build/SConscript')
+ </file>
+ <file name="src/SConscript" printme="1">
env = Environment()
env.Program('hello.c')
</file>
- <file name="SConscript">
- BuildDir('build', 'src')
- SConscript('build/SConscript')
+ <file name="src/hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
</scons_example>
<para>
- Then our &SConscript; file could look like:
+ Then our &SConstruct; file could look like:
</para>
- <scons_example_file example="example_builddir_sconscript" name="SConscript">
+ <scons_example_file example="example_builddir_sconscript" name="SConstruct">
</scons_example_file>
<para>
</para>
<scons_output example="example_builddir_sconscript">
- <command>ls -1 src</command>
- <command>scons</command>
- <command>ls -1 build</command>
+ <command>ls src</command>
+ <command>scons -Q</command>
+ <command>ls build</command>
</scons_output>
<para>
</section>
+ <!--
+
<section>
<title>Why You'd Want to Call &BuildDir; Instead of &SConscript;</title>
</para>
</section>
+
+ -->
The most straightforward way to establish a build directory
uses the fact that the usual way to
- set up a build hierarcy is to have an
+ set up a build hierarchy is to have an
&SConscript; file in the source subdirectory.
If you then pass a &build_dir; argument to the
&SConscript; function call:
</para>
<literallayout>
- % <userinput>ls -1 src</userinput>
- SConscript
- hello.c
- % <userinput>scons</userinput>
- cc -c build/hello.c -o build/hello.o
+ % <userinput>ls src</userinput>
+ SConscript hello.c
+ % <userinput>scons -Q</userinput>
+ cc -c -o build/hello.o build/hello.c
cc -o build/hello build/hello.o
- % <userinput>ls -1 build</userinput>
- hello
- hello.c
- hello.o
+ % <userinput>ls build</userinput>
+ SConscript hello hello.c hello.o
</literallayout>
<para>
&SCons; duplicates source files in build directories
because it's the most straightforward way to guarantee a correct build
- <emphasis>regardless of include-file directory paths</emphasis>,
+ <emphasis>regardless of include-file directory paths,
+ relative references between files,
+ or tool support for putting files in different locations</emphasis>,
and the &SCons; philosophy is to, by default,
guarantee a correct build in all cases.
- Here is an example of an end case where duplicating
- source files in a build directory
- is necessary for a correct build:
</para>
<para>
- XXX
+ The most direct reason to duplicate source files
+ in build directories
+ is simply that some tools (mostly older vesions)
+ are written to only build their output files
+ in the same directory as the source files.
+ In this case, the choices are either
+ to build the output file in the source directory
+ and move it to the build directory,
+ or to duplicate the source files in the build directory.
+
+ </para>
+
+ <para>
+
+ Additionally,
+ relative references between files
+ can cause problems if we don't
+ just duplicate the hierarchy of source files
+ in the build directory.
+ You can see this at work in
+ use of the C preprocessor <literal>#include</literal>
+ mechanism with double quotes, not angle brackets:
</para>
<programlisting>
- env = Environmnet()
+ #include "file.h"
</programlisting>
<para>
- XXX
+ The <emphasis>de facto</emphasis> standard behavior
+ for most C compilers in this case
+ is to first look in the same directory
+ as the source file that contains the <literal>#include</literal> line,
+ then to look in the directories in the preprocessor search path.
+ Add to this that the &SCons; implementation of
+ support for code repositories
+ (described below)
+ means not all of the files
+ will be found in the same directory hierarchy,
+ and the simplest way to make sure
+ that the right include file is found
+ is to duplicate the source files into the build directory,
+ which provides a correct build
+ regardless of the original location(s) of the source files.
</para>
- <literallayout>
- % <userinput>scons</userinput>
- cc -c build/hello.c -o build/hello.o
- cc -o build/hello build/hello.o
- </literallayout>
+ <para>
- </section>
+ Although source-file duplication guarantees a correct build
+ even in these end-cases,
+ it <emphasis>can</emphasis> usually be safely disabled.
+ The next section describes
+ how you can disable the duplication of source files
+ in the build directory.
+
+ </para>
+
+ </section>
<section>
<title>Telling &SCons; to Not Duplicate Source Files in the Build Directory</title>
<para>
- In most cases, however,
- having &SCons; place its target files in a build subdirectory
+ In most cases and with most tool sets,
+ &SCons; can place its target files in a build subdirectory
<emphasis>without</emphasis>
- duplicating the source files works just fine.
+ duplicating the source files
+ and everything will work just fine.
You can disable the default &SCons; behavior
by specifying <literal>duplicate=0</literal>
when you call the &SConscript; function:
</para>
<literallayout>
- % <userinput>ls -1 src</userinput>
+ % <userinput>ls src</userinput>
SConscript
hello.c
- % <userinput>scons</userinput>
+ % <userinput>scons -Q</userinput>
cc -c src/hello.c -o build/hello.o
cc -o build/hello build/hello.o
- % <userinput>ls -1 build</userinput>
+ % <userinput>ls build</userinput>
hello
hello.o
</literallayout>
<para>
- XXX
-
- </para>
-
- <para>
-
When using the &BuildDir; function directly,
&SCons; still duplicates the source files
in the build directory by default:
<literallayout>
% <userinput>ls src</userinput>
hello.c
- % <userinput>scons</userinput>
- cc -c build/hello.c -o build/hello.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o build/hello.o build/hello.c
cc -o build/hello build/hello.o
- % <userinput>ls -1 build</userinput>
- hello
- hello.c
- hello.o
+ % <userinput>ls build</userinput>
+ hello hello.c hello.o
</literallayout>
<para>
<literallayout>
% <userinput>ls src</userinput>
hello.c
- % <userinput>scons</userinput>
- cc -c src/hello.c -o build/hello.o
+ % <userinput>scons -Q</userinput>
+ cc -c -o build/hello.o src/hello.c
cc -o build/hello build/hello.o
- % <userinput>ls -1 build</userinput>
- hello
- hello.o
+ % <userinput>ls build</userinput>
+ hello hello.o
</literallayout>
</section>
<para>
- Then our &SConscript; file could look like:
+ Then our &SConstruct; file could look like:
</para>
+
<programlisting>
BuildDir('build', 'src')
SConscript('build/SConscript')
- </programlisting>
+ </programlisting>
<para>
</para>
<literallayout>
- % <userinput>ls -1 src</userinput>
- SConscript
- hello.c
- % <userinput>scons</userinput>
- cc -c build/hello.c -o build/hello.o
+ % <userinput>ls src</userinput>
+ SConscript hello.c
+ % <userinput>scons -Q</userinput>
+ cc -c -o build/hello.o build/hello.c
cc -o build/hello build/hello.o
- % <userinput>ls -1 build</userinput>
- hello
- hello.c
- hello.o
+ % <userinput>ls build</userinput>
+ SConscript hello hello.c hello.o
</literallayout>
<para>
</section>
+ <!--
+
<section>
<title>Why You'd Want to Call &BuildDir; Instead of &SConscript;</title>
</para>
</section>
+
+ -->
<para>
- X
+ XXX
</para>
<para>
- X
+ XXX
</para>
<scons_example name="ex_bitkeeper">
<file name="SConstruct" printme="1">
env = Environment()
- env.SourceCode('.', env.BitKeeper('XXX'))
+ env.SourceCode('.', env.BitKeeper())
env.Program('hello.c')
</file>
+ <file name="s.hello.c">
+ s.hello.c
+ </file>
</scons_example>
<scons_output example="ex_bitkeeper">
- <userinput>scons</userinput>
+ <command>scons -Q</command>
</scons_output>
</section>
<para>
- X
+ XXX
</para>
<scons_example name="ex_cvs">
<file name="SConstruct" printme="1">
env = Environment()
- env.SourceCode('.', env.CVS('XXX'))
+ env.SourceCode('.', env.CVS('/usr/local/CVS'))
env.Program('hello.c')
</file>
</scons_example>
<scons_output example="ex_cvs">
- <userinput>scons</userinput>
+ <command>scons -Q</command>
</scons_output>
</section>
<para>
- X
+ XXX
</para>
env.SourceCode('.', env.RCS())
env.Program('hello.c')
</file>
+ <file name="hello.c,v">
+ hello.c,v
+ </file>
</scons_example>
<scons_output example="ex_rcs">
- <userinput>scons</userinput>
+ <command>scons -Q</command>
</scons_output>
</section>
<para>
- X
+ XXX
</para>
env.SourceCode('.', env.SCCS())
env.Program('hello.c')
</file>
+ <file name="s.hello.c">
+ s.hello.c
+ </file>
</scons_example>
<scons_output example="ex_sccs">
- <userinput>scons</userinput>
+ <command>scons -Q</command>
</scons_output>
</section>
<para>
- X
+ XXX
</para>
</scons_example>
<scons_output example="ex_subversion">
- <userinput>scons</userinput>
+ <command>scons -Q</command>
</scons_output>
</section>
<para>
- X
+ XXX
</para>
<para>
- X
+ XXX
</para>
<programlisting>
env = Environment()
- env.SourceCode('.', env.BitKeeper('XXX'))
+ env.SourceCode('.', env.BitKeeper())
env.Program('hello.c')
</programlisting>
<literallayout>
- % <userinput>scons</userinput>
- XXX
+ % <userinput>scons -Q</userinput>
+ bk get -
+ bk get hello.c
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
</literallayout>
</section>
<para>
- X
+ XXX
</para>
<programlisting>
env = Environment()
- env.SourceCode('.', env.CVS('XXX'))
+ env.SourceCode('.', env.CVS('/usr/local/CVS'))
env.Program('hello.c')
</programlisting>
<literallayout>
- % <userinput>scons</userinput>
- XXX
+ % <userinput>scons -Q</userinput>
+ cvs -d /usr/local/CVS co -
+ cvs -d /usr/local/CVS co hello.c
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
</literallayout>
</section>
<para>
- X
+ XXX
</para>
</programlisting>
<literallayout>
- % <userinput>scons</userinput>
- XXX
+ % <userinput>scons -Q</userinput>
+ co -
+ co hello.c
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
</literallayout>
</section>
<para>
- X
+ XXX
</para>
</programlisting>
<literallayout>
- % <userinput>scons</userinput>
- XXX
+ % <userinput>scons -Q</userinput>
+ sccs get -
+ sccs get hello.c
+ cc -c -o hello.o hello.c
+ cc -o hello hello.o
</literallayout>
</section>
+ <!--
+
<section>
<title>Fetching Source Code From Subversion</title>
<para>
- X
+ XXX
</para>
- <programlisting>
+ <scons_example name="ex_subversion">
+ <file name="SConstruct" printme="1">
env = Environment()
env.SourceCode('.', env.Subversion('XXX'))
env.Program('hello.c')
- </programlisting>
+ </file>
+ </scons_example>
- <literallayout>
- % <userinput>scons</userinput>
- XXX
- </literallayout>
+ <scons_output example="ex_subversion">
+ <command>scons -Q</command>
+ </scons_output>
</section>
+
+ -->
=head1 Variant builds
-
-=head2 Hello, World! for baNaNa and peAcH OS's
-
-Variant builds require just another simple extension. Let's take as an
-example a requirement to allow builds for both the baNaNa and peAcH
-operating systems. In this case, we are using a distributed file system,
-such as NFS to access the particular system, and only one or the other of
-the systems has to be compiled for any given invocation of C<cons>. Here's
-one way we could set up the F<Construct> file for our B<Hello, World!>
-application:
-
- # Construct file for Hello, World!
-
- die qq(OS must be specified) unless $OS = $ARG{OS};
- die qq(OS must be "peach" or "banana")
- if $OS ne "peach" && $OS ne "banana";
-
- # Where to put all our shared products.
- $EXPORT = "#export/$OS";
-
- Export qw( CONS INCLUDE LIB BIN );
-
- # Standard directories for sharing products.
- $INCLUDE = "$EXPORT/include";
- $LIB = "$EXPORT/lib";
- $BIN = "$EXPORT/bin";
-
- # A standard construction environment.
- $CONS = new cons (
- CPPPATH => $INCLUDE, # Include path for C Compilations
- LIBPATH => $LIB, # Library path for linking programs
- LIBS => '-lworld', # List of standard libraries
- );
-
- # $BUILD is where we will derive everything.
- $BUILD = "#build/$OS";
-
- # Tell cons where the source files for $BUILD are.
- Link $BUILD => 'src';
-
- Build (
- "$BUILD/hello/Conscript",
- "$BUILD/world/Conscript",
- );
-
-Now if we login to a peAcH system, we can build our B<Hello, World!>
-application for that platform:
-
- % cons export OS=peach
- Install build/peach/world/world.h as export/peach/include/world.h
- cc -Iexport/peach/include -c build/peach/hello/hello.c -o build/peach/hello/hello.o
- cc -Iexport/peach/include -c build/peach/world/world.c -o build/peach/world/world.o
- ar r build/peach/world/libworld.a build/peach/world/world.o
- ar: creating build/peach/world/libworld.a
- ranlib build/peach/world/libworld.a
- Install build/peach/world/libworld.a as export/peach/lib/libworld.a
- cc -o build/peach/hello/hello build/peach/hello/hello.o -Lexport/peach/lib -lworld
- Install build/peach/hello/hello as export/peach/bin/hello
-
-
=head2 Variations on a theme
Other variations of this model are possible. For example, you might decide
<scons_example name="ex_variants">
<file name="SConstruct" printme="1">
- platform = ARGUMENT.get('OS', Platform())
+ platform = ARGUMENTS.get('OS', Platform())
include = "#export/$PLATFORM/include"
lib = "#export/$PLATFORM/lib"
bin = "#export/$PLATFORM/bin"
env = Environment(PLATFORM = platform,
+ BINDIR = bin,
+ INCDIR = include,
+ LIBDIR = lib,
CPPPATH = [include],
- LIB = lib,
- LIBS = '-lworld')
+ LIBPATH = [lib],
+ LIBS = 'world')
Export('env')
- SConscript('src/SConscript', build_dir='build/$PLATFORM')
+ env.SConscript('src/SConscript', build_dir='build/$PLATFORM')
#
#BuildDir("#build/$PLATFORM", 'src')
#SConscript("build/$PLATFORM/hello/SConscript")
#SConscript("build/$PLATFORM/world/SConscript")
</file>
+ <directory name="src"></directory>
+ <directory name="src/hello"></directory>
+ <directory name="src/world"></directory>
+ <file name="src/SConscript">
+ Import('env')
+ SConscript('hello/SConscript')
+ SConscript('world/SConscript')
+ </file>
+ <file name="src/hello/SConscript">
+ Import('env')
+ hello = env.Program('hello.c')
+ env.Install('$BINDIR', hello)
+ </file>
+ <file name="src/hello/hello.c">
+ #include "world.h"
+ int main(int argc, char *argv[]) { printf "hello.c\n"; world(); }
+ </file>
+ <file name="src/world/SConscript">
+ Import('env')
+ world = env.Library('world.c')
+ env.Install('$LIBDIR', world)
+ env.Install('$INCDIR', 'world.h')
+ </file>
+ <file name="src/world/world.h">
+ #define STRING "world.h"
+ extern int world();
+ </file>
+ <file name="src/world/world.c">
+ int world() { printf "world.c\n"; }
+ </file>
</scons_example>
<para>
</para>
<scons_output example="ex_variants" os="posix">
- <command>scons OS=linux</command>
+ <command>scons -Q OS=linux</command>
</scons_output>
<para>
</para>
<scons_output example="ex_variants" os="win32">
- <command>scons OS=windows</command>
+ <command>scons -Q OS=windows</command>
</scons_output>
+ <!--
+
<scons_example name="ex_var2">
- <programlisting>
<file name="SConstruct" printme="1">
- env = Environment(OS = )
+ env = Environment(OS = ARGUMENTS.get('OS'))
for os in ['newell', 'post']:
SConscript('src/SConscript', build_dir='build/' + os)
</file>
</scons_example>
<scons_output example="ex_var2">
- % <userinput>scons</userinput>
+ <command>scons -Q</command>
</scons_output>
+
+ -->
=head1 Variant builds
-
-=head2 Hello, World! for baNaNa and peAcH OS's
-
-Variant builds require just another simple extension. Let's take as an
-example a requirement to allow builds for both the baNaNa and peAcH
-operating systems. In this case, we are using a distributed file system,
-such as NFS to access the particular system, and only one or the other of
-the systems has to be compiled for any given invocation of C<cons>. Here's
-one way we could set up the F<Construct> file for our B<Hello, World!>
-application:
-
- # Construct file for Hello, World!
-
- die qq(OS must be specified) unless $OS = $ARG{OS};
- die qq(OS must be "peach" or "banana")
- if $OS ne "peach" && $OS ne "banana";
-
- # Where to put all our shared products.
- $EXPORT = "#export/$OS";
-
- Export qw( CONS INCLUDE LIB BIN );
-
- # Standard directories for sharing products.
- $INCLUDE = "$EXPORT/include";
- $LIB = "$EXPORT/lib";
- $BIN = "$EXPORT/bin";
-
- # A standard construction environment.
- $CONS = new cons (
- CPPPATH => $INCLUDE, # Include path for C Compilations
- LIBPATH => $LIB, # Library path for linking programs
- LIBS => '-lworld', # List of standard libraries
- );
-
- # $BUILD is where we will derive everything.
- $BUILD = "#build/$OS";
-
- # Tell cons where the source files for $BUILD are.
- Link $BUILD => 'src';
-
- Build (
- "$BUILD/hello/Conscript",
- "$BUILD/world/Conscript",
- );
-
-Now if we login to a peAcH system, we can build our B<Hello, World!>
-application for that platform:
-
- % cons export OS=peach
- Install build/peach/world/world.h as export/peach/include/world.h
- cc -Iexport/peach/include -c build/peach/hello/hello.c -o build/peach/hello/hello.o
- cc -Iexport/peach/include -c build/peach/world/world.c -o build/peach/world/world.o
- ar r build/peach/world/libworld.a build/peach/world/world.o
- ar: creating build/peach/world/libworld.a
- ranlib build/peach/world/libworld.a
- Install build/peach/world/libworld.a as export/peach/lib/libworld.a
- cc -o build/peach/hello/hello build/peach/hello/hello.o -Lexport/peach/lib -lworld
- Install build/peach/hello/hello as export/peach/bin/hello
-
-
=head2 Variations on a theme
Other variations of this model are possible. For example, you might decide
</para>
<programlisting>
- platform = ARGUMENT.get('OS', Platform())
+ platform = ARGUMENTS.get('OS', Platform())
include = "#export/$PLATFORM/include"
lib = "#export/$PLATFORM/lib"
bin = "#export/$PLATFORM/bin"
env = Environment(PLATFORM = platform,
+ BINDIR = bin,
+ INCDIR = include,
+ LIBDIR = lib,
CPPPATH = [include],
- LIB = lib,
- LIBS = '-lworld')
+ LIBPATH = [lib],
+ LIBS = 'world')
Export('env')
- SConscript('src/SConscript', build_dir='build/$PLATFORM')
+ env.SConscript('src/SConscript', build_dir='build/$PLATFORM')
#
#BuildDir("#build/$PLATFORM", 'src')
</para>
<literallayout>
- $ <userinput>scons OS=linux</userinput>
- Install build/linux/world/world.h as export/linux/include/world.h
- cc -Iexport/linux/include -c build/linux/hello/hello.c -o build/linux/hello/hello.o
- cc -Iexport/linux/include -c build/linux/world/world.c -o build/linux/world/world.o
+ % <userinput>scons -Q OS=linux</userinput>
+ Install file: "build/linux/world/world.h" as "export/linux/include/world.h"
+ cc -Iexport/linux/include -c -o build/linux/hello/hello.o build/linux/hello/hello.c
+ cc -Iexport/linux/include -c -o build/linux/world/world.o build/linux/world/world.c
ar r build/linux/world/libworld.a build/linux/world/world.o
- ar: creating build/linux/world/libworld.a
ranlib build/linux/world/libworld.a
- Install build/linux/world/libworld.a as export/linux/lib/libworld.a
+ Install file: "build/linux/world/libworld.a" as "export/linux/lib/libworld.a"
cc -o build/linux/hello/hello build/linux/hello/hello.o -Lexport/linux/lib -lworld
- Install build/linux/hello/hello as export/linux/bin/hello
+ Install file: "build/linux/hello/hello" as "export/linux/bin/hello"
</literallayout>
<para>
</para>
- <!--
- cl /Fohello.obj hello.c
- link /Fohello.exe hello.obj
- -->
<literallayout>
- C:\test\><userinput>scons OS=linux</userinput>
- Install build\linux\world\world.h as export\linux\include\world.h
- cl /Iexport\linux\include /Fobuild\linux\hello\hello.obj build\linux\hello\hello.c
- cl /Iexport\linux\include /Fobuild\linux\world\world.obj build\linux\world\world.c
- XXX
- ar r build\linux\world\world.lib build\linux\world\world.obj
- Install build\linux\world\world.lib as export\linux\lib\libworld.a
- link /Fobuild\linux\hello\hello.exe build\linux\hello\hello.obj -Lexport\linux\lib world.lib
- Install build\linux\hello\hello.exe as export\linux\bin\hello.exe
+ C:\><userinput>scons -Q OS=windows</userinput>
+ Install file: "build/windows/world/world.h" as "export/windows/include/world.h"
+ cl /nologo /Iexport\windows\include /c build\windows\hello\hello.c /Fobuild\windows\hello\hello.obj
+ cl /nologo /Iexport\windows\include /c build\windows\world\world.c /Fobuild\windows\world\world.obj
+ lib /nologo /OUT:build\windows\world\world.lib build\windows\world\world.obj
+ Install file: "build/windows/world/world.lib" as "export/windows/lib/world.lib"
+ link /nologo /OUT:build\windows\hello\hello.exe /LIBPATH:export\windows\lib world.lib build\windows\hello\hello.obj
+ Install file: "build/windows/hello/hello.exe" as "export/windows/bin/hello.exe"
</literallayout>
- <programlisting>
- env = Environment(OS = )
+ <!--
+
+ <scons_example name="ex_var2">
+ <file name="SConstruct" printme="1">
+ env = Environment(OS = ARGUMENTS.get('OS'))
for os in ['newell', 'post']:
SConscript('src/SConscript', build_dir='build/' + os)
- </programlisting>
+ </file>
+ </scons_example>
- <literallayout>
- % <userinput>scons</userinput>
- </literallayout>
+ <scons_output example="ex_var2">
+ <command>scons -Q</command>
+ </scons_output>
+
+ -->
%define name scons
-%define version 0.92
+%define version 0.93
%define release 1
Summary: an Open Source software construction tool
-RELEASE X.XX - XXX
+RELEASE 0.93 - Thu, 23 Oct 2003 07:26:55 -0500
From J.T. Conklin:
- Supply a warning when -j is used and threading isn't built in to
the current version of Python.
+ - First release of the User's Guide (finally, and despite a lot
+ of things still missing from it...).
+
From Clark McGrew:
- Generalize the action for .tex files so that it will decide whether
1.5.2, you may not have distutils installed. If you are running
Python version 1.6 or later, you should be fine.
-NOTE TO RED HAT USERS: All Red Hat Linux versions up to 7.3 still ship
-Python 1.5.2 as the default, so you probably do *not* have distutils
+NOTE TO RED HAT USERS: Red Hat shipped Python 1.5.2 as the default all
+the way up to Red Hat Linux 7.3, so you probably do *not* have distutils
installed, unless you have already done so manually or are running Red
Hat 8.0 or later.
-RELEASE X.XX - XXX
+RELEASE 0.93 - Thu, 23 Oct 2003 07:26:55 -0500
This is the fourth beta release of SCons. Please consult the
CHANGES.txt file for a list of specific changes since last release.
# version = os.environ['SCONS_VERSION']
#except KeyError:
# version = '__VERSION__'
-version = '0.92'
+version = '0.93'
scons_version = 'scons-%s' % version