summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/man/scons.1148
-rw-r--r--doc/scons.mod3
-rw-r--r--doc/user/command-line.in233
-rw-r--r--doc/user/command-line.sgml237
-rw-r--r--src/CHANGES.txt2
-rw-r--r--src/engine/SCons/Environment.py13
-rw-r--r--src/engine/SCons/EnvironmentTests.py19
-rw-r--r--src/engine/SCons/Script/SConscript.py94
-rw-r--r--src/engine/SCons/Script/__init__.py20
-rw-r--r--test/TARGETS.py109
10 files changed, 800 insertions, 78 deletions
diff --git a/doc/man/scons.1 b/doc/man/scons.1
index ff2864c..453ff66 100644
--- a/doc/man/scons.1
+++ b/doc/man/scons.1
@@ -2374,6 +2374,13 @@ Later calls to
will add to the (now empty) default-target list
like normal.
+The current list of targets added using the
+.BR Default ()
+function or method is available in the
+.B DEFAULT_TARGETS
+list;
+see below.
+
'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.TP
.RI DefaultEnvironment([ args ])
@@ -3567,6 +3574,147 @@ or the user's current PATHEXT
(os.environ['PATHEXT'])
by default.
+.SS SConscript Variables
+In addition to the global functions and methods,
+.B scons
+supports a number of Python variables
+that can be used in SConscript files
+to affect how you want the build to be performed.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+ARGUMENTS
+A dictionary of all the
+.IR keyword = value
+arguments specified on the command line.
+The dictionary is not in order,
+and if a given keyword has
+more than one value assigned to it
+on the command line,
+the last (right-most) value is
+the one in the
+.B ARGUMENTS
+dictionary.
+
+.ES
+if ARGUMENTS.get('debug', 0):
+ env = Environment(CCFLAGS = '-g')
+else:
+ env = Environment()
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+BUILD_TARGETS
+A list of the targets which
+.B scons
+will actually try to build,
+regardless of whether they were specified on
+the command line or via the
+.BR Default ()
+function or method.
+The elements of this list may be strings
+.I or
+nodes, so you should run the list through the Python
+.B str
+function to make sure any Node path names
+are converted to strings.
+
+Because this list may be taken from the
+list of targets specified using the
+.BR Default ()
+function or method,
+the contents of the list may change
+on each successive call to
+.BR Default ().
+See the
+.B DEFAULT_TARGETS
+list, below,
+for additional information.
+
+.ES
+if 'foo' in BUILD_TARGETS:
+ print "Don't forget to test the `foo' program!"
+if 'special/program' in BUILD_TARGETS:
+ SConscript('special')
+.EE
+.IP
+Note that the
+.B BUILD_TARGETS
+list only contains targets expected listed
+on the command line or via calls to the
+.BR Default ()
+function or method.
+It does
+.I not
+contain all dependent targets that will be built as
+a result of making the sure the explicitly-specified
+targets are up to date.
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+COMMAND_LINE_TARGETS
+A list of the targets explicitly specified on
+the command line.
+If there are no targets specified on the command line,
+the list is empty.
+This can be used, for example,
+to take specific actions only
+when a certain target or targets
+is explicitly being built:
+
+.ES
+if 'foo' in COMMAND_LINE_TARGETS:
+ print "Don't forget to test the `foo' program!"
+if 'special/program' in COMMAND_LINE_TARGETS:
+ SConscript('special')
+.EE
+
+'\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.TP
+DEFAULT_TARGETS
+A list of the target
+.I nodes
+that have been specified using the
+.BR Default ()
+function or method.
+The elements of the list are nodes,
+so you need to run them through the Python
+.B str
+function to get at the path name for each Node.
+
+.ES
+print str(DEFAULT_TARGETS[0])
+if 'foo' in map(str, DEFAULT_TARGETS):
+ print "Don't forget to test the `foo' program!"
+.EE
+.IP
+The contents of the
+.B DEFAULT_TARGETS
+list change on on each successive call to the
+.BR Default ()
+function:
+
+.ES
+print map(str, DEFAULT_TARGETS) # originally []
+Default('foo')
+print map(str, DEFAULT_TARGETS) # now a node ['foo']
+Default('bar')
+print map(str, DEFAULT_TARGETS) # now a node ['foo', 'bar']
+Default(None)
+print map(str, DEFAULT_TARGETS) # back to []
+.EE
+.IP
+Consequently, be sure to use
+.B DEFAULT_TARGETS
+only after you've made all of your
+.BR Default ()
+calls,
+or else simply be careful of the order
+of these statements in your SConscript files
+so that you don't look for a specific
+default target before it's actually been added to the list.
+
.SS Construction Variables
.\" XXX From Gary Ruben, 23 April 2002:
.\" I think it would be good to have an example with each construction
diff --git a/doc/scons.mod b/doc/scons.mod
index d9b955f..443be67 100644
--- a/doc/scons.mod
+++ b/doc/scons.mod
@@ -174,6 +174,9 @@
-->
<!ENTITY ARGUMENTS "<varname>ARGUMENTS</varname>">
+<!ENTITY BUILD_TARGETS "<varname>BUILD_TARGETS</varname>">
+<!ENTITY COMMAND_LINE_TARGETS "<varname>COMMAND_LINE_TARGETS</varname>">
+<!ENTITY DEFAULT_TARGETS "<varname>DEFAULT_TARGETS</varname>">
diff --git a/doc/user/command-line.in b/doc/user/command-line.in
index 09ee8ce..9367c09 100644
--- a/doc/user/command-line.in
+++ b/doc/user/command-line.in
@@ -73,12 +73,71 @@
</section>
<section>
+ <title>Getting at Command-Line Targets</title>
+
+ <para>
+
+ &SCons; supports a &COMMAND_LINE_TARGETS; variable
+ that lets you get at the list of targets that the
+ user specified on the command line.
+ You can use the targets to manipulate the
+ build in any way you wish.
+ As a simple example,
+ suppose that you want to print a reminder
+ to the user whenever a specific program is built.
+ You can do this by checking for the
+ target in the &COMMAND_LINE_TARGETS; list:
+
+ </para>
+
+ <scons_example name="COMMAND_LINE_TARGETS">
+ <file name="SConstruct" printme="1">
+ if 'bar' in COMMAND_LINE_TARGETS:
+ print "Don't forget to copy `bar' to the archive!"
+ Default(Program('foo.c'))
+ Program('bar.c')
+ </file>
+ <file name="foo.c">
+ foo.c
+ </file>
+ <file name="bar.c">
+ foo.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ Then, running &SCons; with the default target
+ works as it always does,
+ but explicity specifying the &bar; target
+ on the command line generates the warning message:
+
+ </para>
+
+ <scons_output example="COMMAND_LINE_TARGETS">
+ <command>scons -Q</command>
+ <command>scons -Q bar</command>
+ </scons_output>
+
+ <para>
+
+ Another practical use for the &COMMAND_LINE_TARGETS; variable
+ might be to speed up a build
+ by only reading certain subsidiary &SConscript;
+ files if a specific target is requested.
+
+ </para>
+
+ </section>
+
+ <section>
<title>Controlling the Default Targets</title>
<para>
One of the most basic things you can control
- is which targets &SCons; will build by default.
+ is which targets &SCons; will build by default--that is,
+ when there are no targets specified on the command line.
As mentioned previously,
&SCons; will normally build every target
in or below the current directory
@@ -276,22 +335,182 @@
<command>scons -Q .</command>
</scons_output>
- </section>
+ <section>
+ <title>Getting at the List of Default Targets</title>
+
+ <para>
+
+ &SCons; supports a &DEFAULT_TARGETS; variable
+ that lets you get at the current list of default targets.
+ 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,
+ so you need to convert the list elements to strings
+ if you want to print them or look for a specific target name.
+ Fortunately, you can do this easily
+ by using the Python <function>map</function> function
+ to run the list through <function>str</function>:
- <!--
+ </para>
+
+ <scons_example name="DEFAULT_TARGETS_1">
+ <file name="SConstruct" printme="1">
+ prog1 = Program('prog1.c')
+ Default(prog1)
+ print "DEFAULT_TARGETS is", map(str, DEFAULT_TARGETS)
+ </file>
+ <file name="prog1.c">
+ prog1.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ (Keep in mind that all of the manipulation of the
+ &DEFAULT_TARGETS; list takes place during the
+ first phase when &SCons; is reading up the &SConscript; files,
+ which is obvious if
+ we leave off the <literal>-Q</literal> flag when we run &SCons;:)
+
+ </para>
+
+ <scons_output example="DEFAULT_TARGETS_1">
+ <command>scons</command>
+ </scons_output>
+
+ <para>
+
+ Second,
+ the contents of the &DEFAULT_TARGETS; list change
+ in response to calls to the &Default: function,
+ as you can see from the following &SConstruct; file:
+
+ </para>
+
+ <scons_example name="DEFAULT_TARGETS_2">
+ <file name="SConstruct" printme="1">
+ prog1 = Program('prog1.c')
+ Default(prog1)
+ print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS)
+ prog2 = Program('prog2.c')
+ Default(prog2)
+ print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS)
+ </file>
+ <file name="prog1.c">
+ prog1.c
+ </file>
+ <file name="prog2.c">
+ prog2.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which yields the output:
+
+ </para>
+
+ <scons_output example="DEFAULT_TARGETS_2">
+ <command>scons</command>
+ </scons_output>
+
+ <para>
+
+ In practice, this simply means that you
+ need to pay attention to the order in
+ which you call the &Default; function
+ and refer to the &DEFAULT_TARGETS; list,
+ to make sure that you don't examine the
+ list before you've added the default targets
+ you expect to find in it.
+
+ </para>
+
+ </section>
+
+ </section>
<section>
- <title>Getting at Command-Line Targets</title>
+ <title>Getting at the List of Build Targets, Regardless of Origin</title>
<para>
- XXX
+ We've already been introduced to the
+ &COMMAND_LINE_TARGETS; variable,
+ which contains a list of targets specified on the command line,
+ and the &DEFAULT_TARGETS; variable,
+ which contains a list of targets specified
+ via calls to the &Default; method or function.
+ Sometimes, however,
+ you want a list of whatever targets
+ &SCons; will try to build,
+ regardless of whether the targets came from the
+ command line or a &Default; call.
+ You could code this up by hand, as follows:
</para>
- </section>
+ <sconstruct>
+ if COMMAND_LINE_TARGETS:
+ targets = COMMAND_LINE_TARGETS
+ else:
+ targets = DEFAULT_TARGETS
+ </sconstruct>
- -->
+ <para>
+
+ &SCons;, however, provides a convenient
+ &BUILD_TARGETS; variable
+ that eliminates the need for this by-hand manipulation.
+ Essentially, the &BUILD_TARGETS; variable
+ contains a list of the command-line targets,
+ if any were specified,
+ and if no command-line targets were specified,
+ it contains a list of the targets specified
+ via the &Default; method or function.
+
+ </para>
+
+ <para>
+
+ Because &BUILD_TARGETS; may contain a list of &SCons; nodes,
+ you must convert the list elements to strings
+ if you want to print them or look for a specific target name,
+ just like the &DEFAULT_TARGETS; list:
+
+ </para>
+
+ <scons_example name="BUILD_TARGETS_1">
+ <file name="SConstruct" printme="1">
+ prog1 = Program('prog1.c')
+ Program('prog2.c')
+ Default(prog1)
+ print "BUILD_TARGETS is", map(str, BUILD_TARGETS)
+ </file>
+ <file name="prog1.c">
+ prog1.c
+ </file>
+ <file name="prog2.c">
+ prog2.c
+ </file>
+ </scons_example>
+
+ <para>
+
+ Notice how the value of &BUILD_TARGETS;
+ changes depending on whether a target is
+ specified on the command line:
+
+ </para>
+
+ <scons_output example="BUILD_TARGETS_1">
+ <command>scons -Q</command>
+ <command>scons -Q prog2</command>
+ <command>scons -Q -c .</command>
+ </scons_output>
+
+ </section>
<section>
<title>Command-Line <varname>variable</varname>=<varname>value</varname> Build Options</title>
diff --git a/doc/user/command-line.sgml b/doc/user/command-line.sgml
index 3377b69..f6f219c 100644
--- a/doc/user/command-line.sgml
+++ b/doc/user/command-line.sgml
@@ -72,12 +72,68 @@
</section>
<section>
+ <title>Getting at Command-Line Targets</title>
+
+ <para>
+
+ &SCons; supports a &COMMAND_LINE_TARGETS; variable
+ that lets you get at the list of targets that the
+ user specified on the command line.
+ You can use the targets to manipulate the
+ build in any way you wish.
+ As a simple example,
+ suppose that you want to print a reminder
+ to the user whenever a specific program is built.
+ You can do this by checking for the
+ target in the &COMMAND_LINE_TARGETS; list:
+
+ </para>
+
+ <programlisting>
+ if 'bar' in COMMAND_LINE_TARGETS:
+ print "Don't forget to copy `bar' to the archive!"
+ Default(Program('foo.c'))
+ Program('bar.c')
+ </programlisting>
+
+ <para>
+
+ Then, running &SCons; with the default target
+ works as it always does,
+ but explicity specifying the &bar; target
+ on the command line generates the warning message:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons -Q</userinput>
+ cc -c -o foo.o foo.c
+ cc -o foo foo.o
+ % <userinput>scons -Q bar</userinput>
+ Don't forget to copy `bar' to the archive!
+ cc -c -o bar.o bar.c
+ cc -o bar bar.o
+ </literallayout>
+
+ <para>
+
+ Another practical use for the &COMMAND_LINE_TARGETS; variable
+ might be to speed up a build
+ by only reading certain subsidiary &SConscript;
+ files if a specific target is requested.
+
+ </para>
+
+ </section>
+
+ <section>
<title>Controlling the Default Targets</title>
<para>
One of the most basic things you can control
- is which targets &SCons; will build by default.
+ is which targets &SCons; will build by default--that is,
+ when there are no targets specified on the command line.
As mentioned previously,
&SCons; will normally build every target
in or below the current directory
@@ -259,22 +315,189 @@
cc -o prog2 prog2.o
</literallayout>
- </section>
+ <section>
+ <title>Getting at the List of Default Targets</title>
+
+ <para>
+
+ &SCons; supports a &DEFAULT_TARGETS; variable
+ that lets you get at the current list of default targets.
+ 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,
+ so you need to convert the list elements to strings
+ if you want to print them or look for a specific target name.
+ Fortunately, you can do this easily
+ by using the Python <function>map</function> function
+ to run the list through <function>str</function>:
+
+ </para>
+
+ <programlisting>
+ prog1 = Program('prog1.c')
+ Default(prog1)
+ print "DEFAULT_TARGETS is", map(str, DEFAULT_TARGETS)
+ </programlisting>
- <!--
+ <para>
+
+ (Keep in mind that all of the manipulation of the
+ &DEFAULT_TARGETS; list takes place during the
+ first phase when &SCons; is reading up the &SConscript; files,
+ which is obvious if
+ we leave off the <literal>-Q</literal> flag when we run &SCons;:)
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ DEFAULT_TARGETS is ['prog1']
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cc -c -o prog1.o prog1.c
+ cc -o prog1 prog1.o
+ scons: done building targets.
+ </literallayout>
+
+ <para>
+
+ Second,
+ the contents of the &DEFAULT_TARGETS; list change
+ in response to calls to the &Default;: function,
+ as you can see from the following &SConstruct; file:
+
+ </para>
+
+ <programlisting>
+ prog1 = Program('prog1.c')
+ Default(prog1)
+ print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS)
+ prog2 = Program('prog2.c')
+ Default(prog2)
+ print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS)
+ </programlisting>
+
+ <para>
+
+ Which yields the output:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons</userinput>
+ scons: Reading SConscript files ...
+ DEFAULT_TARGETS is now ['prog1']
+ DEFAULT_TARGETS is now ['prog1', 'prog2']
+ scons: done reading SConscript files.
+ scons: Building targets ...
+ cc -c -o prog1.o prog1.c
+ cc -o prog1 prog1.o
+ cc -c -o prog2.o prog2.c
+ cc -o prog2 prog2.o
+ scons: done building targets.
+ </literallayout>
+
+ <para>
+
+ In practice, this simply means that you
+ need to pay attention to the order in
+ which you call the &Default; function
+ and refer to the &DEFAULT_TARGETS; list,
+ to make sure that you don't examine the
+ list before you've added the default targets
+ you expect to find in it.
+
+ </para>
+
+ </section>
+
+ </section>
<section>
- <title>Getting at Command-Line Targets</title>
+ <title>Getting at the List of Build Targets, Regardless of Origin</title>
<para>
- XXX
+ We've already been introduced to the
+ &COMMAND_LINE_TARGETS; variable,
+ which contains a list of targets specified on the command line,
+ and the &DEFAULT_TARGETS; variable,
+ which contains a list of targets specified
+ via calls to the &Default; method or function.
+ Sometimes, however,
+ you want a list of whatever targets
+ &SCons; will try to build,
+ regardless of whether the targets came from the
+ command line or a &Default; call.
+ You could code this up by hand, as follows:
</para>
- </section>
+ <programlisting>
+ if COMMAND_LINE_TARGETS:
+ targets = COMMAND_LINE_TARGETS
+ else:
+ targets = DEFAULT_TARGETS
+ </programlisting>
+
+ <para>
+
+ &SCons;, however, provides a convenient
+ &BUILD_TARGETS; variable
+ that eliminates the need for this by-hand manipulation.
+ Essentially, the &BUILD_TARGETS; variable
+ contains a list of the command-line targets,
+ if any were specified,
+ and if no command-line targets were specified,
+ it contains a list of the targets specified
+ via the &Default; method or function.
+
+ </para>
+
+ <para>
+
+ Because &BUILD_TARGETS; may contain a list of &SCons; nodes,
+ you must convert the list elements to strings
+ if you want to print them or look for a specific target name,
+ just like the &DEFAULT_TARGETS; list:
+
+ </para>
+
+ <programlisting>
+ prog1 = Program('prog1.c')
+ Program('prog2.c')
+ Default(prog1)
+ print "BUILD_TARGETS is", map(str, BUILD_TARGETS)
+ </programlisting>
+
+ <para>
+
+ Notice how the value of &BUILD_TARGETS;
+ changes depending on whether a target is
+ specified on the command line:
+
+ </para>
+
+ <literallayout>
+ % <userinput>scons -Q</userinput>
+ BUILD_TARGETS is ['prog1']
+ cc -c -o prog1.o prog1.c
+ cc -o prog1 prog1.o
+ % <userinput>scons -Q prog2</userinput>
+ BUILD_TARGETS is ['prog2']
+ cc -c -o prog2.o prog2.c
+ cc -o prog2 prog2.o
+ % <userinput>scons -Q -c .</userinput>
+ BUILD_TARGETS is ['.']
+ Removed prog1.o
+ Removed prog1
+ Removed prog2.o
+ Removed prog2
+ </literallayout>
- -->
+ </section>
<section>
<title>Command-Line <varname>variable</varname>=<varname>value</varname> Build Options</title>
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 2905339..8629589 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -25,6 +25,8 @@ RELEASE X.XX - XXX, XX XXX XXXX XX:XX:XX -XXXX
- Fix subclassing the Environment and Scanner classes.
+ - Add BUILD_TARGETS, COMMAND_LINE_TARGETS and DEFAULT_TARGETS variables.
+
From Steve Leblanc:
- SGI fixes: Fix C++ compilation, add a separate Tool/sgic++.py module.
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index 6c6ad8a..26be483 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -64,7 +64,6 @@ class _Null:
_null = _Null
-DefaultTargets = None
CleanTargets = {}
CalculatorArgs = {}
@@ -811,18 +810,6 @@ class Base:
source_factory=self.fs.Entry)
return bld(self, target, source)
- def Default(self, *targets):
- global DefaultTargets
- if DefaultTargets is None:
- DefaultTargets = []
- for t in targets:
- if t is None:
- DefaultTargets = []
- elif isinstance(t, SCons.Node.Node):
- DefaultTargets.append(t)
- else:
- DefaultTargets.extend(self.arg2nodes(t, self.fs.Entry))
-
def Depends(self, target, dependency):
"""Explicity specify that 'target's depend on 'dependency'."""
tlist = self.arg2nodes(target, self.fs.Entry)
diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py
index 2861f85..e6fd5c9 100644
--- a/src/engine/SCons/EnvironmentTests.py
+++ b/src/engine/SCons/EnvironmentTests.py
@@ -1484,25 +1484,6 @@ class EnvironmentTestCase(unittest.TestCase):
finally:
os.chdir(save)
- def test_Default(self):
- """Test the Default() method"""
- env = Environment(FOO = 'fff', BAR = 'bbb')
-
- t = env.Default(None)
- assert SCons.Environment.DefaultTargets == []
-
- t = env.Default('xyz')
- d = map(str, SCons.Environment.DefaultTargets)
- assert d == ['xyz'], d
-
- t = env.Default('$FOO')
- d = map(str, SCons.Environment.DefaultTargets)
- assert d == ['xyz', 'fff'], d
-
- t = env.Default(None, '$BAR', 'another_file')
- d = map(str, SCons.Environment.DefaultTargets)
- assert d == ['bbb', 'another_file'], d
-
def test_Depends(self):
"""Test the explicit Depends method."""
env = Environment(FOO = 'xxx', BAR='yyy')
diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py
index fff1869..8894df7 100644
--- a/src/engine/SCons/Script/SConscript.py
+++ b/src/engine/SCons/Script/SConscript.py
@@ -53,13 +53,27 @@ import string
import sys
import traceback
import types
+import UserList
+
+launch_dir = os.path.abspath(os.curdir)
def do_nothing(text): pass
HelpFunction = do_nothing
-arguments = {}
+Arguments = {}
+CommandLineTargets = []
+DefaultCalled = None
+DefaultTargets = []
GlobalDict = {}
-launch_dir = os.path.abspath(os.curdir)
+
+class TargetList(UserList.UserList):
+ def _do_nothing(self, *args, **kw):
+ pass
+ def _add_Default(self, list):
+ self.extend(list)
+ def _clear(self):
+ del self[:]
+BuildTargets = TargetList()
# global exports set by Export():
global_exports = {}
@@ -71,10 +85,16 @@ sconscript_chdir = 1
sconscript_reading = 0
def _scons_add_args(alist):
- global arguments
for arg in alist:
a, b = string.split(arg, '=', 2)
- arguments[a] = b
+ Arguments[a] = b
+
+def _scons_add_targets(tlist):
+ if tlist:
+ CommandLineTargets.extend(tlist)
+ BuildTargets.extend(tlist)
+ BuildTargets._add_Default = BuildTargets._do_nothing
+ BuildTargets._clear = BuildTargets._do_nothing
def get_calling_namespaces():
"""Return the locals and globals for the function that called
@@ -387,6 +407,26 @@ class SConsEnvironment(SCons.Environment.Base):
# as global functions.
#
+ def Default(self, *targets):
+ global DefaultCalled
+ global DefaultTargets
+ DefaultCalled = 1
+ for t in targets:
+ if t is None:
+ # Delete the elements from the list in-place, don't
+ # reassign an empty list to DefaultTargets, so that the
+ # DEFAULT_TARGETS variable will still point to the
+ # same object we point to.
+ del DefaultTargets[:]
+ BuildTargets._clear()
+ elif isinstance(t, SCons.Node.Node):
+ DefaultTargets.append(t)
+ BuildTargets._add_Default([t])
+ else:
+ nodes = self.arg2nodes(t, self.fs.Entry)
+ DefaultTargets.extend(nodes)
+ BuildTargets._add_Default(nodes)
+
def EnsureSConsVersion(self, major, minor):
"""Exit abnormally if the SCons version is not late enough."""
if not self._check_version(major,minor,SCons.__version__):
@@ -460,7 +500,7 @@ class SConsEnvironment(SCons.Environment.Base):
#
SCons.Environment.Environment = SConsEnvironment
-def Options(files=None, args=arguments):
+def Options(files=None, args=Arguments):
return SCons.Options.Options(files, args)
def SetBuildSignatureType(type):
@@ -545,6 +585,7 @@ class DefaultEnvironmentCall:
# DefaultEnvironment().
GlobalDefaultEnvironmentFunctions = [
# Methods from the SConsEnvironment class, above.
+ 'Default',
'EnsurePythonVersion',
'EnsureSConsVersion',
'Exit',
@@ -566,7 +607,6 @@ GlobalDefaultEnvironmentFunctions = [
'CacheDir',
'Clean',
'Command',
- 'Default',
'Depends',
'Dir',
'File',
@@ -624,23 +664,31 @@ def BuildDefaultGlobals():
SConstruct and SConscript files.
"""
- globals = {}
- globals['Action'] = SCons.Action.Action
- globals['ARGUMENTS'] = arguments
- globals['BoolOption'] = SCons.Options.BoolOption
- globals['Builder'] = SCons.Builder.Builder
- globals['Configure'] = SCons.SConf.SConf
- globals['EnumOption'] = SCons.Options.EnumOption
- globals['Environment'] = SCons.Environment.Environment
- globals['ListOption'] = SCons.Options.ListOption
- globals['Options'] = Options
- globals['PackageOption'] = SCons.Options.PackageOption
- globals['PathOption'] = SCons.Options.PathOption
- globals['Platform'] = SCons.Platform.Platform
- globals['Return'] = Return
- globals['Scanner'] = SCons.Scanner.Base
- globals['Tool'] = SCons.Tool.Tool
- globals['WhereIs'] = SCons.Util.WhereIs
+ globals = {
+ # Global functions that don't get executed through the
+ # default Environment.
+ 'Action' : SCons.Action.Action,
+ 'BoolOption' : SCons.Options.BoolOption,
+ 'Builder' : SCons.Builder.Builder,
+ 'Configure' : SCons.SConf.SConf,
+ 'EnumOption' : SCons.Options.EnumOption,
+ 'Environment' : SCons.Environment.Environment,
+ 'ListOption' : SCons.Options.ListOption,
+ 'Options' : Options,
+ 'PackageOption' : SCons.Options.PackageOption,
+ 'PathOption' : SCons.Options.PathOption,
+ 'Platform' : SCons.Platform.Platform,
+ 'Return' : Return,
+ 'Scanner' : SCons.Scanner.Base,
+ 'Tool' : SCons.Tool.Tool,
+ 'WhereIs' : SCons.Util.WhereIs,
+
+ # Other variables we provide.
+ 'ARGUMENTS' : Arguments,
+ 'BUILD_TARGETS' : BuildTargets,
+ 'COMMAND_LINE_TARGETS' : CommandLineTargets,
+ 'DEFAULT_TARGETS' : DefaultTargets,
+ }
# Functions we might still convert to Environment methods.
globals['CScan'] = SCons.Defaults.CScan
diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py
index a533c29..71ed2be 100644
--- a/src/engine/SCons/Script/__init__.py
+++ b/src/engine/SCons/Script/__init__.py
@@ -753,6 +753,7 @@ def _main(args, parser):
else:
targets.append(a)
SCons.Script.SConscript._scons_add_args(xmit_args)
+ SCons.Script.SConscript._scons_add_targets(targets)
target_top = None
if options.climb_up:
@@ -865,6 +866,7 @@ def _main(args, parser):
# There are no targets specified on the command line,
# so if they used -u, -U or -D, we may have to restrict
# what actually gets built.
+ d = None
if target_top:
if options.climb_up == 1:
# -u, local directory and below
@@ -886,18 +888,18 @@ def _main(args, parser):
# or not a file, so go ahead and keep it as a default
# target and let the engine sort it out:
return 1
- default_targets = SCons.Environment.DefaultTargets
- if default_targets is None:
- default_targets = []
- else:
- default_targets = filter(check_dir, default_targets)
- SCons.Environment.DefaultTargets = default_targets
+ d = filter(check_dir, SCons.Script.SConscript.DefaultTargets)
+ SCons.Script.SConscript.DefaultTargets[:] = d
target_top = None
lookup_top = None
- targets = SCons.Environment.DefaultTargets
- if targets is None:
- targets = [fs.Dir('.')]
+ if SCons.Script.SConscript.DefaultCalled:
+ targets = SCons.Script.SConscript.DefaultTargets
+ else:
+ if d is None:
+ d = [fs.Dir('.')]
+ targets = d
+
if not targets:
sys.stderr.write("scons: *** No targets specified and no Default() targets found. Stop.\n")
diff --git a/test/TARGETS.py b/test/TARGETS.py
new file mode 100644
index 0000000..5c73d81
--- /dev/null
+++ b/test/TARGETS.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test use of the COMMAND_LINE_TARGETS and DEFAULT_TARGETS variables.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+print COMMAND_LINE_TARGETS
+print map(str, BUILD_TARGETS)
+Default('.')
+print COMMAND_LINE_TARGETS
+print map(str, BUILD_TARGETS)
+""")
+
+test.write('aaa', 'aaa\n')
+test.write('bbb', 'bbb\n')
+
+expect = test.wrap_stdout(read_str = "[]\n[]\n[]\n['.']\n",
+ build_str = "scons: `.' is up to date.\n")
+test.run(stdout = expect)
+
+expect = test.wrap_stdout(read_str = "['.']\n['.']\n['.']\n['.']\n",
+ build_str = "scons: `.' is up to date.\n")
+test.run(arguments = '.', stdout = expect)
+
+expect = test.wrap_stdout(read_str = "['aaa']\n['aaa']\n['aaa']\n['aaa']\n",
+ build_str = "scons: Nothing to be done for `aaa'.\n")
+test.run(arguments = 'aaa', stdout = expect)
+
+expect = test.wrap_stdout(read_str = "['bbb', 'aaa']\n['bbb', 'aaa']\n['bbb', 'aaa']\n['bbb', 'aaa']\n",
+ build_str = """\
+scons: Nothing to be done for `bbb'.
+scons: Nothing to be done for `aaa'.
+""")
+test.run(arguments = 'bbb ccc=xyz -n aaa', stdout = expect)
+
+test.write('SConstruct', """
+env = Environment()
+print map(str, DEFAULT_TARGETS)
+print map(str, BUILD_TARGETS)
+Default('aaa')
+print map(str, DEFAULT_TARGETS)
+print map(str, BUILD_TARGETS)
+env.Default('bbb')
+print map(str, DEFAULT_TARGETS)
+print map(str, BUILD_TARGETS)
+env.Default(None)
+print map(str, DEFAULT_TARGETS)
+print map(str, BUILD_TARGETS)
+env.Default('ccc')
+""")
+
+test.write('ccc', "ccc\n")
+
+expect = test.wrap_stdout(build_str = "scons: Nothing to be done for `ccc'.\n",
+ read_str = """\
+[]
+[]
+['aaa']
+['aaa']
+['aaa', 'bbb']
+['aaa', 'bbb']
+[]
+[]
+""")
+test.run(stdout = expect)
+
+expect = test.wrap_stdout(build_str = "scons: `.' is up to date.\n",
+ read_str = """\
+[]
+['.']
+['aaa']
+['.']
+['aaa', 'bbb']
+['.']
+[]
+['.']
+""")
+test.run(arguments = '.', stdout = expect)
+
+test.pass_test()