orig = SCons.Node.FS.EntryProxy
class MyEntryProxy(orig):
def __str__(self):
- return string.replace(str(self._Proxy__subject), os.sep, Sep)
+ return str(self._Proxy__subject).replace(os.sep, Sep)
SCons.Node.FS.EntryProxy = MyEntryProxy
# Slip our own RDirs() method into the Node.FS.File class so that the
# running on to what's appropriate for the example system.
orig_RDirs = SCons.Node.FS.File.RDirs
def my_RDirs(self, pathlist, orig_RDirs=orig_RDirs):
- return map(lambda x: string.replace(str(x), os.sep, Sep),
- orig_RDirs(self, pathlist))
+ return [str(x).replace(os.sep, Sep) for x in orig_RDirs(self, pathlist)]
SCons.Node.FS.File.RDirs = my_RDirs
class Curry:
def Str(target, source, env, cmd=""):
result = []
for cmd in env.subst_list(cmd, target=target, source=source):
- result.append(string.join(map(str, cmd)))
- return string.join(result, '\\n')
+ result.append(' '.join(map(str, cmd)))
+ return '\\n'.join(result)
class ToolSurrogate:
def __init__(self, tool, variable, func, varlist):
}
toollist = ToolList[platform]
-filter_tools = string.split('%(tools)s')
+filter_tools = '%(tools)s'.split()
if filter_tools:
toollist = [x for x in toollist if x[0] in filter_tools]
# Here is where the heavy lifting begins. The following methods
# handle the begin-end tags of our SCons examples.
+ def for_display(self, contents):
+ contents = contents.replace('__ROOT__', '')
+ contents = contents.replace('<', '<')
+ contents = contents.replace('>', '>')
+ return contents
+
def start_scons_example(self, attrs):
t = [t for t in attrs if t[0] == 'name']
if t:
i = len(f.data) - 1
while f.data[i] == ' ':
i = i - 1
- output = f.data[:i+1].replace('__ROOT__', '')
- output = output.replace('<', '<')
- output = output.replace('>', '>')
+ output = self.for_display(f.data[:i+1])
self.outfp.write(output)
if e.data and e.data[0] == '\n':
e.data = e.data[1:]
content = engine_re.sub(r' File "bootstrap/src/engine/SCons/', content)
content = file_re.sub(r'\1 <module>', content)
content = nodelist_re.sub(r"\1 'NodeList' object \2", content)
- content = content.replace('<', '<')
- content = content.replace('>', '>')
+ content = self.for_display(content)
self.outfp.write(p + content + '\n')
if o.data[0] == '\n':
def end_sconstruct(self):
f = self.f
self.outfp.write('<programlisting>')
- output = f.data.replace('__ROOT__', '')
+ output = self.for_display(f.data)
self.outfp.write(output + '</programlisting>')
delattr(self, 'f')
self.afunclist = self.afunclist[:-1]
<section id="sect-envs">
- <title>&ConsEnvs</title>
+ <title>&ConsEnvs;</title>
<para>
<footnote>
<para>
It would be nice if we could avoid re-inventing the wheel here by
- using some other Python-based tool &Autoconf replacement--like what
+ using some other Python-based tool &Autoconf; replacement--like what
was supposed to come out of the Software Carpentry configuration
tool contest. It will probably be most efficient to roll our own
logic initially and convert if something better does come along.
MyBuilder = Builder(command = "$XX $XXFLAGS -c $_INPUTS -o $target")
env.Command(targets = 'bar.out', sources = 'bar.in',
- command = "sed '1d' < $source > $target")
+ command = "sed '1d' < $source > $target")
</programlisting>
<para>
<programlisting>
env = Environment(FUNC = myfunc)
env.Command(target = 'foo.out', source = 'foo.in',
- command = "${FUNC($<)}")
+ command = "${FUNC($<)}")
</programlisting>
<para>
<literal>target</literal> (that is, one passed to the
&Build; or &Clean; method). Objects which a top-level
<literal>target</literal> is directly dependent upon have a
- <literal>level</literal> of <1>, their direct dependencies have a
- <literal>level</literal> of <2>, etc. Typically used to indent
+ <literal>level</literal> of <1>, their direct dependencies have a
+ <literal>level</literal> of <2>, etc. Typically used to indent
output to reflect the recursive levels.
</para>
<para>
As a next-generation build tool,
- &SCons should fundamentally
+ &SCons; should fundamentally
improve on its predecessors.
Rather than simply being driven by trying to
<emphasis>not</emphasis> be like previous tools,
<para>
By default, the &SCons; utility searches for a file named
- &SConstruct;, &Sconstruct; or &sconstruct (in that order) in the
+ &SConstruct;, &Sconstruct; or &sconstruct; (in that order) in the
current directory, and reads its configuration from the first file
found. A <option>-f</option> command-line option exists to read a
different file name.
Any variables (not just &SCons; objects) that are to be shared between configuration files must be
explicitly passed in the &SConscript; call
- using the &Export method:
+ using the &Export; method:
</para>
<para>
- &SCons; will allow users to share &consenvs, as well as other &SCons;
+ &SCons; will allow users to share &consenvs;, as well as other &SCons;
objects and Python variables, by importing them from a central, shared
repository using normal Python syntax:
<para>
An alternate &SCons; interface would provide backwards
- compatibility with the classic &Make utility.
+ compatibility with the classic &Make; utility.
This would be done by embedding the &SCons; Build Engine
in a Python script that can translate existing
&Makefile;s into the underlying calls to the
<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>
&SCons; is a software construction tool (build tool, or make tool)
implemented in Python, which uses Python scripts as "configuration
files" for software builds. Based on the design which won the
- Software Carpentry build tool competition, &SCons solves a number of
+ Software Carpentry build tool competition, &SCons; solves a number of
problems associated with other build tools, especially including the
classic and ubiquitous &Make; itself.
<mediaobject>
<imageobject>
- <imagedata fileref="arch" format="eps" align="center">
+ <imagedata fileref="arch" format="eps" align="center"/>
</imageobject>
<imageobject>
- <imagedata fileref="arch.jpg" format="jpg" align="center">
+ <imagedata fileref="arch.jpg" format="jpg" align="center"/>
</imageobject>
<!-- PDF files?
<imageobject>
- <imagedata fileref="arch.pdf" align="center">
+ <imagedata fileref="arch.pdf" align="center"/>
</imageobject>
-->
</mediaobject>
<mediaobject>
<imageobject>
- <imagedata fileref="node" format="eps" align="center">
+ <imagedata fileref="node" format="eps" align="center"/>
</imageobject>
<imageobject>
- <imagedata fileref="node.jpg" format="jpg" align="center">
+ <imagedata fileref="node.jpg" format="jpg" align="center"/>
</imageobject>
<!-- PDF files?
<imageobject>
- <imagedata fileref="node.pdf" align="center">
+ <imagedata fileref="node.pdf" align="center"/>
</imageobject>
-->
</mediaobject>
<mediaobject>
<imageobject>
- <imagedata fileref="scanner" format="eps" align="center">
+ <imagedata fileref="scanner" format="eps" align="center"/>
</imageobject>
<imageobject>
- <imagedata fileref="scanner.jpg" format="jpg" align="center">
+ <imagedata fileref="scanner.jpg" format="jpg" align="center"/>
</imageobject>
<!-- PDF files?
<imageobject>
- <imagedata fileref="scanner.pdf" align="center">
+ <imagedata fileref="scanner.pdf" align="center"/>
</imageobject>
-->
</mediaobject>
signature information for &Node; objects.
The signature subsystem in &SCons;
supports multiple ways to
- determine whether a &Node is up-to-date
+ determine whether a &Node; is up-to-date
by using an abstract &Sig; class
as a strategy wrapper:
<mediaobject>
<imageobject>
- <imagedata fileref="sig" format="eps" align="center">
+ <imagedata fileref="sig" format="eps" align="center"/>
</imageobject>
<imageobject>
- <imagedata fileref="sig.jpg" format="jpg" align="center">
+ <imagedata fileref="sig.jpg" format="jpg" align="center"/>
</imageobject>
<!-- PDF files?
<imageobject>
- <imagedata fileref="sig.pdf" align="center">
+ <imagedata fileref="sig.pdf" align="center"/>
</imageobject>
-->
</mediaobject>
<mediaobject>
<imageobject>
- <imagedata fileref="builder" format="eps" align="center">
+ <imagedata fileref="builder" format="eps" align="center"/>
</imageobject>
<imageobject>
- <imagedata fileref="builder.jpg" format="jpg" align="center">
+ <imagedata fileref="builder.jpg" format="jpg" align="center"/>
</imageobject>
<!-- PDF files?
<imageobject>
- <imagedata fileref="builder.pdf" align="center">
+ <imagedata fileref="builder.pdf" align="center"/>
</imageobject>
-->
</mediaobject>
<mediaobject>
<imageobject>
- <imagedata fileref="job-task" format="eps" align="center">
+ <imagedata fileref="job-task" format="eps" align="center"/>
</imageobject>
<imageobject>
- <imagedata fileref="job-task.jpg" format="jpg" align="center">
+ <imagedata fileref="job-task.jpg" format="jpg" align="center"/>
</imageobject>
<!-- PDF files?
<imageobject>
- <imagedata fileref="job-task.pdf" align="center">
+ <imagedata fileref="job-task.pdf" align="center"/>
</imageobject>
-->
</mediaobject>
<para>
- The &Taskmaster uses the node subsystem's
+ The &Taskmaster; uses the node subsystem's
&Walker; class to walk the dependency tree,
and the &Sig; class to use the
appropriate method
<para>
&Builder; objects are associated with a &consenv; through a
- &consvar; named &BUILDERS;, a list of the &Builder objects that
- will be available for execution through the &consenv:
+ &consvar; named &BUILDERS;, a list of the &Builder; objects that
+ will be available for execution through the &consenv;:
</para>
&Scanner; objects are associated with a &consenv; through a
&consvar; named &SCANNERS;, a list of the &Scanner; objects that
- will be available through the &consenv:
+ will be available through the &consenv;:
</para>
The most noticeable difference between &scons; and &Make;, or most
other build tools, is that the configuration files are actually
Python scripts, generically called "SConscripts" (although the
- top-level "Makefile" is named &SConstruct). Users do not have to
+ top-level "Makefile" is named &SConstruct;). Users do not have to
learn a new language syntax, but instead configure dependency
information by making direct calls to the Python API of the
- &SCons; Build Engine. Here is an example &SConstruct file which
+ &SCons; Build Engine. Here is an example &SConstruct; file which
builds a program in side-by-side normal and debug versions:
</para>
<holder>O'Reilly & Associates, Inc.</holder>
</copyright>
<publisher>
- <publishername>O'Reilly & Associates, Inc.</publishername>
+ <publishername>O'Reilly & Associates, Inc.</publishername>
</publisher>
<title>Managing Projects with Make, 2nd Ed.</title>
</biblioentry>
<para>
- In practice, these restrictions can be overridden as necessaryfor
+ In practice, these restrictions can be overridden as necessary--for
example, when changing comments or documentation.
</para>
</para>
<sconstruct>
- b = Builder(action = 'build < $SOURCE > $TARGET')
+ b = Builder(action = 'build < $SOURCE > $TARGET')
</sconstruct>
<para>
</para>
<sconstruct>
- b = Builder(action = Action('build < $SOURCE > $TARGET'))
+ b = Builder(action = Action('build < $SOURCE > $TARGET'))
</sconstruct>
<para>
</para>
<programlisting>
- b = Builder(action = 'build < $SOURCE > $TARGET')
+ b = Builder(action = 'build < $SOURCE > $TARGET')
</programlisting>
<para>
</para>
<programlisting>
- b = Builder(action = Action('build < $SOURCE > $TARGET'))
+ b = Builder(action = Action('build < $SOURCE > $TARGET'))
</programlisting>
<para>
</para>
<programlisting>
- bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
</programlisting>
<para>
<scons_example name="ex1">
<file name="SConstruct">
- bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env = Environment(BUILDERS = {'Foo' : bld})
import os
env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
</scons_example>
<sconstruct>
- bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env = Environment(BUILDERS = {'Foo' : bld})
</sconstruct>
env = Environment()
import os
env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
- bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env.Append(BUILDERS = {'Foo' : bld})
env.Foo('file.foo', 'file.input')
env.Program('hello.c')
<sconstruct>
env = Environment()
- bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env.Append(BUILDERS = {'Foo' : bld})
env.Foo('file.foo', 'file.input')
env.Program('hello.c')
<sconstruct>
env = Environment()
- bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env['BUILDERS']['Foo'] = bld
env.Foo('file.foo', 'file.input')
env.Program('hello.c')
<scons_example name="ex4">
<file name="SConstruct">
- bld = Builder(action = 'foobuild < $SOURCE > $TARGET',
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET',
suffix = '.foo',
src_suffix = '.input')
env = Environment(BUILDERS = {'Foo' : bld})
</scons_example>
<sconstruct>
- bld = Builder(action = 'foobuild < $SOURCE > $TARGET',
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET',
suffix = '.foo',
src_suffix = '.input')
env = Environment(BUILDERS = {'Foo' : bld})
<programlisting>
def generate_actions(source, target, env, for_signature):
- return 'foobuild < %s > %s' % (target[0], source[0])
+ return 'foobuild < %s > %s' % (target[0], source[0])
</programlisting>
<para>
<scons_example name="ex6">
<file name="SConstruct">
def generate_actions(source, target, env, for_signature):
- return 'foobuild < %s > %s' % (source[0], target[0])
+ return 'foobuild < %s > %s' % (source[0], target[0])
bld = Builder(generator = generate_actions,
suffix = '.foo',
src_suffix = '.input')
<sconstruct>
def generate_actions(source, target, env, for_signature):
- return 'foobuild < %s > %s' % (source[0], target[0])
+ return 'foobuild < %s > %s' % (source[0], target[0])
bld = Builder(generator = generate_actions,
suffix = '.foo',
src_suffix = '.input')
<scons_example name="MY_EMITTER">
<file name="SConstruct" printme="1">
- bld = Builder(action = 'my_command $SOURCES > $TARGET',
+ bld = Builder(action = 'my_command $SOURCES > $TARGET',
suffix = '.foo',
src_suffix = '.input',
emitter = '$MY_EMITTER')
</scons_example>
<sconstruct>
- bld = Builder(action = 'my_command $SOURCES > $TARGET',
+ bld = Builder(action = 'my_command $SOURCES > $TARGET',
suffix = '.foo',
src_suffix = '.input',
emitter = '$MY_EMITTER')
<file name="site_scons/site_init.py" printme=1>
def TOOL_ADD_HEADER(env):
"""A Tool to add a header from $HEADER to the source file"""
- add_header = Builder(action=['echo "$HEADER" > $TARGET',
- 'cat $SOURCE >> $TARGET'])
+ add_header = Builder(action=['echo "$HEADER" > $TARGET',
+ 'cat $SOURCE >> $TARGET'])
env.Append(BUILDERS = {'AddHeader' : add_header})
env['HEADER'] = '' # set default value
</file>
<programlisting>
- bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env = Environment(BUILDERS = {'Foo' : bld})
</programlisting>
<programlisting>
env = Environment()
- bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
+ 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 < $SOURCE > $TARGET')
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET')
env['BUILDERS']['Foo'] = bld
env.Foo('file.foo', 'file.input')
env.Program('hello.c')
<programlisting>
- bld = Builder(action = 'foobuild < $SOURCE > $TARGET',
+ bld = Builder(action = 'foobuild < $SOURCE > $TARGET',
suffix = '.foo',
src_suffix = '.input')
env = Environment(BUILDERS = {'Foo' : bld})
<programlisting>
def generate_actions(source, target, env, for_signature):
- return 'foobuild < %s > %s' % (source[0], target[0])
+ return 'foobuild < %s > %s' % (source[0], target[0])
bld = Builder(generator = generate_actions,
suffix = '.foo',
src_suffix = '.input')
</programlisting>
<programlisting>
- bld = Builder(action = 'my_command $SOURCES > $TARGET',
+ bld = Builder(action = 'my_command $SOURCES > $TARGET',
suffix = '.foo',
src_suffix = '.input',
emitter = '$MY_EMITTER')
choices to a specific set of allowed colors.
This can be set up quite easily
using the &EnumVariable;,
- which takes a list of &allowed_values
+ which takes a list of &allowed_values;
in addition to the variable name,
default value,
and help text arguments:
&SCons; supports a &DEFAULT_TARGETS; variable
that lets you get at the current list of default targets.
- The &DEFAULT_TARGETS variable has
+ The &DEFAULT_TARGETS; variable has
two important differences from the &COMMAND_LINE_TARGETS; variable.
First, the &DEFAULT_TARGETS; variable is a list of
internal &SCons; nodes,
choices to a specific set of allowed colors.
This can be set up quite easily
using the &EnumVariable;,
- which takes a list of &allowed_values
+ which takes a list of &allowed_values;
in addition to the variable name,
default value,
and help text arguments:
&SCons; supports a &DEFAULT_TARGETS; variable
that lets you get at the current list of default targets.
- The &DEFAULT_TARGETS variable has
+ The &DEFAULT_TARGETS; variable has
two important differences from the &COMMAND_LINE_TARGETS; variable.
First, the &DEFAULT_TARGETS; variable is a list of
internal &SCons; nodes,
#!/usr/bin/env python
import os
import sys
- if len(sys.argv) > 1:
+ if len(sys.argv) > 1:
keys = sys.argv[1:]
else:
keys = sorted(os.environ.keys())
#!/usr/bin/env python
import os
import sys
- if len(sys.argv) > 1:
+ if len(sys.argv) > 1:
keys = sys.argv[1:]
else:
keys = sorted(os.environ.keys())
<programlisting>
env = Environment()
d = env.ParseFlags(["!echo -I/opt/include", "!echo -L/opt/lib", "-lfoo"])
- for k,v in l:
+ for k,v in sorted(d.items()):
if v:
print k, v
env.MergeFlags(d)
% <userinput>scons -Q --debug=stacktrace</userinput>
scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'.
scons: internal stack trace:
- File "bootstrap/src/engine/SCons/Job.py", line 197, in start
+ File "bootstrap/src/engine/SCons/Job.py", line 199, in start
task.prepare()
File "bootstrap/src/engine/SCons/Script/Main.py", line 167, in prepare
return SCons.Taskmaster.OutOfDateTask.prepare(self)
Change Log
+RELEASE X.X.X -
+
+ From Dirk Baechle:
+
+ - Fix XML in documentation.
+
+
RELEASE 1.3.0 - Tue, 23 Mar 2010 21:44:19 -0400
From Steven Knight: