summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2007-01-07 07:23:05 (GMT)
committerSteven Knight <knight@baldmt.com>2007-01-07 07:23:05 (GMT)
commit8e31352a5b5a500263a8d0d3aee7288970a67b4c (patch)
tree05e6aee9b46b530443e01bbb762b68775a6bb0ff /src
parenta4fa510f9025ccb4ffeddefe26ce17e01c6a2b8f (diff)
downloadSCons-8e31352a5b5a500263a8d0d3aee7288970a67b4c.zip
SCons-8e31352a5b5a500263a8d0d3aee7288970a67b4c.tar.gz
SCons-8e31352a5b5a500263a8d0d3aee7288970a67b4c.tar.bz2
Merged revisions 1738-1754,1756 via svnmerge from
http://scons.tigris.org/svn/scons/branches/core ........ r1741 | stevenknight | 2006-12-16 22:51:07 -0600 (Sat, 16 Dec 2006) | 1 line 0.96.D527 - Give the f90 and f95 Tool modules knowledge of how to build source files of earlier Fortran versions. ........ r1742 | stevenknight | 2006-12-16 23:22:54 -0600 (Sat, 16 Dec 2006) | 1 line 0.96.D528 - Better handling of timestamp fallback if there's no md5 module. ........ r1743 | stevenknight | 2006-12-17 00:21:31 -0600 (Sun, 17 Dec 2006) | 1 line 0.96.D529 - Fix portability of new tests on systems that don't have TeX installed. ........ r1744 | stevenknight | 2006-12-19 15:30:16 -0600 (Tue, 19 Dec 2006) | 1 line 0.96.D530 - Eliminate the ListBuilder subclass in favor of using the Executor's target lists. ........ r1745 | stevenknight | 2006-12-19 18:54:26 -0600 (Tue, 19 Dec 2006) | 1 line 0.96.D531 - Eliminate of MultiStepBuilder as a separate Builder subclass. ........ r1746 | garyo | 2006-12-21 13:21:08 -0600 (Thu, 21 Dec 2006) | 1 line Minor doc fix, thanks to Douglas Landgraf. ........ r1747 | stevenknight | 2006-12-21 17:13:55 -0600 (Thu, 21 Dec 2006) | 1 line 0.96.D533 - Add CFLAGS for options common to C/C++. (Gary Oberbrunner) ........ r1748 | stevenknight | 2007-01-03 19:48:05 -0600 (Wed, 03 Jan 2007) | 1 line 0.96.D534 - Fix signature storage when targets are retrieved from CacheDir(). ........ r1749 | stevenknight | 2007-01-04 16:48:47 -0600 (Thu, 04 Jan 2007) | 1 line 0.96.D535 - Teach the lex and yacc tools about target files generated by different flex/bison options, and about Objective C suffixes. (Pupeno) ........ r1750 | stevenknight | 2007-01-04 17:14:38 -0600 (Thu, 04 Jan 2007) | 1 line 0.96.D536 - Refactor duplicate disambiguation logic in Entry.get_contents(). ........ r1751 | stevenknight | 2007-01-05 13:00:54 -0600 (Fri, 05 Jan 2007) | 1 line 0.96.D537 - Fix lprof regression from 0.96.92. ........ r1752 | stevenknight | 2007-01-05 20:43:48 -0600 (Fri, 05 Jan 2007) | 1 line 0.96.D538 - Fix caching of Builder suffix matching (to fix lprof regression). ........ r1753 | stevenknight | 2007-01-06 00:03:16 -0600 (Sat, 06 Jan 2007) | 1 line 0.96.D539 - Fix --include-dir when using MinGW. (Paul) ........ r1754 | stevenknight | 2007-01-06 00:24:53 -0600 (Sat, 06 Jan 2007) | 1 line 0.96.D540 - Make bootstrap.py something useful to execute SCons out of a source directory. ........ r1756 | stevenknight | 2007-01-06 21:32:11 -0600 (Sat, 06 Jan 2007) | 1 line 0.96.D541 - Update the Copyright year string to include 2007. Automate updating the month+year string in man page title headers. Fix hard-coded __revision__ strings that crept into some older tests. ........
Diffstat (limited to 'src')
-rw-r--r--src/CHANGES.txt32
-rw-r--r--src/engine/SCons/Builder.py301
-rw-r--r--src/engine/SCons/BuilderTests.py62
-rw-r--r--src/engine/SCons/Environment.py15
-rw-r--r--src/engine/SCons/EnvironmentTests.py3
-rw-r--r--src/engine/SCons/Node/FS.py55
-rw-r--r--src/engine/SCons/Node/FSTests.py19
-rw-r--r--src/engine/SCons/Node/__init__.py2
-rw-r--r--src/engine/SCons/SConfTests.py6
-rw-r--r--src/engine/SCons/Script/Main.py1
-rw-r--r--src/engine/SCons/Taskmaster.py10
-rw-r--r--src/engine/SCons/TaskmasterTests.py7
-rw-r--r--src/engine/SCons/Tool/bcc32.py6
-rw-r--r--src/engine/SCons/Tool/cc.py6
-rw-r--r--src/engine/SCons/Tool/cc.xml26
-rw-r--r--src/engine/SCons/Tool/f90.py4
-rw-r--r--src/engine/SCons/Tool/f95.py7
-rw-r--r--src/engine/SCons/Tool/icc.py2
-rw-r--r--src/engine/SCons/Tool/lex.py53
-rw-r--r--src/engine/SCons/Tool/mingw.py2
-rw-r--r--src/engine/SCons/Tool/msvc.py6
-rw-r--r--src/engine/SCons/Tool/mwcc.py5
-rw-r--r--src/engine/SCons/Tool/qt.py4
-rw-r--r--src/engine/SCons/Tool/yacc.py53
-rw-r--r--src/engine/SCons/Tool/yacc.xml17
-rw-r--r--src/engine/SCons/Warnings.py3
-rw-r--r--src/script/scons-time.py2
-rw-r--r--src/test_copyrights.py265
28 files changed, 564 insertions, 410 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index e7f4937..3678dd1 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -14,6 +14,11 @@ RELEASE 0.97 - XXX
- Allow arbitrary white space after a SWIG %module declaration.
+ From Paul:
+
+ - When compiling resources under MinGW, make sure there's a space
+ between the --include-dir option and its argument.
+
From Jay Kint:
- Alleviate long command line issues on Windows by executing command
@@ -65,6 +70,19 @@ RELEASE 0.97 - XXX
files control over what exceptions cause a string to expand to ''
vs. terminating processing with an error.
+ - Allow the f90.py and f95.py Tool modules to compile earlier source
+ source files of earlier Fortran version.
+
+ - Fix storing signatures of files retrieved from CacheDir() so they're
+ correctly identified as up-to-date next invocation.
+
+ - Make sure lists of computed source suffixes cached by Builder objects
+ don't persist across changes to the list of source Builders (so the
+ addition of suffixes like .ui by the qt.py Tool module take effect).
+
+ - Enhance the bootstrap.py script to allow it to be used to execute
+ SCons more easily from a checked-out source tree.
+
From Ben Leslie:
- Fix post-Memoizer value caching misspellings in Node.FS._doLookup().
@@ -93,6 +111,9 @@ RELEASE 0.97 - XXX
- Eliminate some unnecessary os.path.normpath() calls.
+ - Add a $CFLAGS variable for C-specific options, leaving $CCFLAGS
+ for options common to C and C++.
+
From Tom Parker:
- Have the error message print the missing file that Qt can't find.
@@ -107,6 +128,17 @@ RELEASE 0.97 - XXX
specified on the command line (and not intuited from the old way of
calling it with just ".sconsign").
+ From Jose Pablo Ezequiel "Pupeno" Fernandez Silva:
+
+ - Give the 'lex' tool knowledge of the additional target files produced
+ by the flex "--header-file=" and "--tables-file=" options.
+
+ - Give the 'yacc' tool knowledge of the additional target files produced
+ by the bison "-g", "--defines=" and "--graph=" options.
+
+ - Generate intermediate files with Objective C file suffixes (.m) when
+ the lex and yacc source files have appropriate suffixes (.lm and .ym).
+
From Sohail Somain:
- Have the mslink.py Tool only look for a 'link' executable on Windows
diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py
index d5f566a..d625ed7 100644
--- a/src/engine/SCons/Builder.py
+++ b/src/engine/SCons/Builder.py
@@ -16,20 +16,9 @@ building new types of files in their configurations, without having to
dive any deeper into this subsystem.
The base class here is BuilderBase. This is a concrete base class which
-does, in fact, represent most Builder objects that we (or users) create.
+does, in fact, represent the Builder objects that we (or users) create.
-There is (at present) one subclasses:
-
- MultiStepBuilder
-
- This is a Builder that knows how to "chain" Builders so that
- users can specify a source file that requires multiple steps
- to turn into a target file. A canonical example is building a
- program from yacc input file, which requires invoking a builder
- to turn the .y into a .c, the .c into a .o, and the .o into an
- executable program.
-
-There is also two proxies that look like Builders:
+There is also a proxy that looks like a Builder:
CompositeBuilder
@@ -39,11 +28,6 @@ There is also two proxies that look like Builders:
(compilers, compile options) for different flavors of source
files.
- ListBuilder
-
- This proxies for a Builder *invocation* where the target
- is a list of files, not a single file.
-
Builders and their proxies have the following public interface methods
used by other modules:
@@ -227,10 +211,9 @@ class OverrideWarner(UserDict.UserDict):
"""A class for warning about keyword arguments that we use as
overrides in a Builder call.
- This class exists to handle the fact that a single MultiStepBuilder
- call can actually invoke multiple builders as a result of a single
- user-level Builder call. This class only emits the warnings once,
- no matter how many Builders are invoked.
+ This class exists to handle the fact that a single Builder call
+ can actually invoke multiple builders. This class only emits the
+ warnings once, no matter how many Builders are invoked.
"""
def __init__(self, dict):
UserDict.UserDict.__init__(self, dict)
@@ -240,13 +223,10 @@ class OverrideWarner(UserDict.UserDict):
if self.already_warned:
return
for k in self.keys():
- try:
+ if misleading_keywords.has_key(k):
alt = misleading_keywords[k]
- except KeyError:
- pass
- else:
- SCons.Warnings.warn(SCons.Warnings.MisleadingKeywordsWarning,
- "Did you mean to use `%s' instead of `%s'?" % (alt, k))
+ msg = "Did you mean to use `%s' instead of `%s'?" % (alt, k)
+ SCons.Warnings.warn(SCons.Warnings.MisleadingKeywordsWarning, msg)
self.already_warned = 1
def Builder(**kw):
@@ -284,15 +264,12 @@ def Builder(**kw):
elif SCons.Util.is_List(emitter):
kw['emitter'] = ListEmitter(emitter)
- if kw.has_key('src_builder'):
- ret = apply(MultiStepBuilder, (), kw)
- else:
- ret = apply(BuilderBase, (), kw)
+ result = apply(BuilderBase, (), kw)
if not composite is None:
- ret = CompositeBuilder(ret, composite)
+ result = CompositeBuilder(result, composite)
- return ret
+ return result
def _node_errors(builder, env, tlist, slist):
"""Validate that the lists of target and source nodes are
@@ -304,7 +281,7 @@ def _node_errors(builder, env, tlist, slist):
# were specified.
for t in tlist:
if t.side_effect:
- raise UserError, "Multiple ways to build the same target were specified for: %s" % str(t)
+ raise UserError, "Multiple ways to build the same target were specified for: %s" % t
if t.has_explicit_builder():
if not t.env is None and not t.env is env:
action = t.builder.action
@@ -312,22 +289,21 @@ def _node_errors(builder, env, tlist, slist):
contents = action.get_contents(tlist, slist, env)
if t_contents == contents:
- SCons.Warnings.warn(SCons.Warnings.DuplicateEnvironmentWarning,
- "Two different environments were specified for target %s,\n\tbut they appear to have the same action: %s"%(str(t), action.genstring(tlist, slist, t.env)))
-
+ msg = "Two different environments were specified for target %s,\n\tbut they appear to have the same action: %s" % (t, action.genstring(tlist, slist, t.env))
+ SCons.Warnings.warn(SCons.Warnings.DuplicateEnvironmentWarning, msg)
else:
- raise UserError, "Two environments with different actions were specified for the same target: %s"%str(t)
-
+ msg = "Two environments with different actions were specified for the same target: %s" % t
+ raise UserError, msg
if builder.multi:
if t.builder != builder:
- if isinstance(t.builder, ListBuilder) and isinstance(builder, ListBuilder) and t.builder.builder == builder.builder:
- raise UserError, "Two different target sets have a target in common: %s"%str(t)
- else:
- raise UserError, "Two different builders (%s and %s) were specified for the same target: %s"%(t.builder.get_name(env), builder.get_name(env), str(t))
- elif isinstance(t.builder, ListBuilder) ^ isinstance(builder, ListBuilder):
- raise UserError, "Cannot build same target `%s' as singular and list"%str(t)
+ msg = "Two different builders (%s and %s) were specified for the same target: %s" % (t.builder.get_name(env), builder.get_name(env), t)
+ raise UserError, msg
+ if t.get_executor().targets != tlist:
+ msg = "Two different target lists have a target in common: %s (from %s and from %s)" % (t, map(str, t.get_executor().targets), map(str, tlist))
+ raise UserError, msg
elif t.sources != slist:
- raise UserError, "Multiple ways to build the same target were specified for: %s (from %s and from %s)" % (str(t), map(str,t.sources), map(str,slist))
+ msg = "Multiple ways to build the same target were specified for: %s (from %s and from %s)" % (t, map(str, t.sources), map(str, slist))
+ raise UserError, msg
if builder.single_source:
if len(slist) > 1:
@@ -388,6 +364,7 @@ class BuilderBase:
name = None,
chdir = _null,
is_explicit = 1,
+ src_builder = [],
**overrides):
if __debug__: logInstanceCreation(self, 'Builder.BuilderBase')
self._memo = {}
@@ -432,6 +409,10 @@ class BuilderBase:
self.executor_kw['chdir'] = chdir
self.is_explicit = is_explicit
+ if not SCons.Util.is_List(src_builder):
+ src_builder = [ src_builder ]
+ self.src_builder = src_builder
+
def __nonzero__(self):
raise InternalError, "Do not test for the Node.builder attribute directly; use Node.has_builder() instead"
@@ -557,6 +538,9 @@ class BuilderBase:
def _execute(self, env, target, source, overwarn={}, executor_kw={}):
# We now assume that target and source are lists or None.
+ if self.src_builder:
+ source = self.src_builder_sources(env, source, overwarn)
+
if self.single_source and len(source) > 1 and target is None:
result = []
if target is None: target = [None]*len(source)
@@ -570,31 +554,26 @@ class BuilderBase:
tlist, slist = self._create_nodes(env, target, source)
- if len(tlist) == 1:
- builder = self
- else:
- builder = ListBuilder(self, env, tlist)
-
# Check for errors with the specified target/source lists.
- _node_errors(builder, env, tlist, slist)
+ _node_errors(self, env, tlist, slist)
# The targets are fine, so find or make the appropriate Executor to
# build this particular list of targets from this particular list of
# sources.
- if builder.multi:
- get_executor = builder.get_multi_executor
+ if self.multi:
+ get_executor = self.get_multi_executor
else:
- get_executor = builder.get_single_executor
+ get_executor = self.get_single_executor
executor = get_executor(env, tlist, slist, executor_kw)
# Now set up the relevant information in the target Nodes themselves.
for t in tlist:
t.cwd = env.fs.getcwd()
- t.builder_set(builder)
+ t.builder_set(self)
t.env_set(env)
t.add_source(slist)
t.set_executor(executor)
- t.set_explicit(builder.is_explicit)
+ t.set_explicit(self.is_explicit)
return SCons.Node.NodeList(tlist)
@@ -650,35 +629,6 @@ class BuilderBase:
suffix = suffix(env, sources)
return env.subst(suffix)
- def _src_suffixes_key(self, env):
- return id(env)
-
- memoizer_counters.append(SCons.Memoize.CountDict('src_suffixes', _src_suffixes_key))
-
- def src_suffixes(self, env):
- """
- Returns the list of source suffixes for this Builder.
-
- The suffix list may contain construction variable expansions,
- so we have to evaluate the individual strings. To avoid doing
- this over and over, we memoize the results for each construction
- environment.
- """
- memo_key = id(env)
- try:
- memo_dict = self._memo['src_suffixes']
- except KeyError:
- memo_dict = {}
- self._memo['src_suffixes'] = memo_dict
- else:
- try:
- return memo_dict[memo_key]
- except KeyError:
- pass
- result = map(lambda x, s=self, e=env: e.subst(x), self.src_suffix)
- memo_dict[memo_key] = result
- return result
-
def set_src_suffix(self, src_suffix):
if not src_suffix:
src_suffix = []
@@ -712,72 +662,15 @@ class BuilderBase:
"""
self.emitter[suffix] = emitter
-
-
-class ListBuilder(SCons.Util.Proxy):
- """A Proxy to support building an array of targets (for example,
- foo.o and foo.h from foo.y) from a single Action execution.
- """
-
- def __init__(self, builder, env, tlist):
- if __debug__: logInstanceCreation(self, 'Builder.ListBuilder')
- SCons.Util.Proxy.__init__(self, builder)
- self.builder = builder
- self.target_scanner = builder.target_scanner
- self.source_scanner = builder.source_scanner
- self.env = env
- self.tlist = tlist
- self.multi = builder.multi
- self.single_source = builder.single_source
-
- def targets(self, node):
- """Return the list of targets for this builder instance.
+ def add_src_builder(self, builder):
"""
- return self.tlist
-
- def get_name(self, env):
- """Attempts to get the name of the Builder."""
-
- return "ListBuilder(%s)" % self.builder.get_name(env)
-
-class MultiStepBuilder(BuilderBase):
- """This is a builder subclass that can build targets in
- multiple steps. The src_builder parameter to the constructor
- accepts a builder that is called to build sources supplied to
- this builder. The targets of that first build then become
- the sources of this builder.
-
- If this builder has a src_suffix supplied, then the src_builder
- builder is NOT invoked if the suffix of a source file matches
- src_suffix.
- """
-
- memoizer_counters = []
-
- def __init__(self, src_builder,
- action = None,
- prefix = '',
- suffix = '',
- src_suffix = '',
- target_factory = None,
- source_factory = None,
- target_scanner = None,
- source_scanner = None,
- emitter=None,
- single_source=0):
- if __debug__: logInstanceCreation(self, 'Builder.MultiStepBuilder')
- BuilderBase.__init__(self, action, prefix, suffix, src_suffix,
- target_factory, source_factory,
- target_scanner, source_scanner, emitter,
- single_source = single_source)
- if not SCons.Util.is_List(src_builder):
- src_builder = [ src_builder ]
- self.src_builder = src_builder
-
- def _get_sdict_key(self, env):
- return id(env)
+ Add a new Builder to the list of src_builders.
- memoizer_counters.append(SCons.Memoize.CountDict('_get_sdict', _get_sdict_key))
+ This requires wiping out cached values so that the computed
+ lists of source suffixes get re-calculated.
+ """
+ self._memo = {}
+ self.src_builder.append(builder)
def _get_sdict(self, env):
"""
@@ -788,35 +681,26 @@ class MultiStepBuilder(BuilderBase):
This dictionary is used for each target specified, so we save a
lot of extra computation by memoizing it for each construction
environment.
+
+ Note that this is re-computed each time, not cached, because there
+ might be changes to one of our source Builders (or one of their
+ source Builders, and so on, and so on...) that we can't "see."
+
+ The underlying methods we call cache their computed values,
+ though, so we hope repeatedly aggregating them into a dictionary
+ like this won't be too big a hit. We may need to look for a
+ better way to do this if performance data show this has turned
+ into a significant bottleneck.
"""
- memo_key = id(env)
- try:
- memo_dict = self._memo['_get_sdict']
- except KeyError:
- memo_dict = {}
- self._memo['_get_sdict'] = memo_dict
- else:
- try:
- return memo_dict[memo_key]
- except KeyError:
- pass
sdict = {}
- for bld in self.src_builder:
- if SCons.Util.is_String(bld):
- try:
- bld = env['BUILDERS'][bld]
- except KeyError:
- continue
+ for bld in self.get_src_builders(env):
for suf in bld.src_suffixes(env):
sdict[suf] = bld
- memo_dict[memo_key] = sdict
return sdict
- def _execute(self, env, target, source, overwarn={}, executor_kw={}):
- # We now assume that target and source are lists or None.
+ def src_builder_sources(self, env, source, overwarn={}):
source_factory = env.get_factory(self.source_factory)
slist = env.arg2nodes(source, source_factory)
- final_sources = []
sdict = self._get_sdict(env)
@@ -834,13 +718,15 @@ class MultiStepBuilder(BuilderBase):
return suf
return None
+ result = []
+
for snode in slist:
match_suffix = match_src_suffix(snode)
if match_suffix:
try:
bld = sdict[match_suffix]
except KeyError:
- final_sources.append(snode)
+ result.append(snode)
else:
tlist = bld._execute(env, None, [snode], overwarn)
# If the subsidiary Builder returned more than one
@@ -848,39 +734,56 @@ class MultiStepBuilder(BuilderBase):
# Builder isn't capable of building.
if len(tlist) > 1:
tlist = filter(match_src_suffix, tlist)
- final_sources.extend(tlist)
+ result.extend(tlist)
else:
- final_sources.append(snode)
+ result.append(snode)
- return BuilderBase._execute(self, env, target, final_sources, overwarn)
+ return result
+
+ def _get_src_builders_key(self, env):
+ return id(env)
+
+ memoizer_counters.append(SCons.Memoize.CountDict('get_src_builders', _get_src_builders_key))
def get_src_builders(self, env):
- """Return all the src_builders for this Builder.
+ """
+ Returns the list of source Builders for this Builder.
- This is essentially a recursive descent of the src_builder "tree."
+ This exists mainly to look up Builders referenced as
+ strings in the 'BUILDER' variable of the construction
+ environment and cache the result.
"""
- ret = []
+ memo_key = id(env)
+ try:
+ memo_dict = self._memo['get_src_builders']
+ except KeyError:
+ memo_dict = {}
+ self._memo['get_src_builders'] = memo_dict
+ else:
+ try:
+ return memo_dict[memo_key]
+ except KeyError:
+ pass
+
+ builders = []
for bld in self.src_builder:
if SCons.Util.is_String(bld):
- # All Environments should have a BUILDERS
- # variable, so no need to check for it.
try:
bld = env['BUILDERS'][bld]
except KeyError:
continue
- ret.append(bld)
- return ret
+ builders.append(bld)
+
+ memo_dict[memo_key] = builders
+ return builders
- def _src_suffixes_key(self, env):
+ def _subst_src_suffixes_key(self, env):
return id(env)
- memoizer_counters.append(SCons.Memoize.CountDict('src_suffixes', _src_suffixes_key))
+ memoizer_counters.append(SCons.Memoize.CountDict('subst_src_suffixes', _subst_src_suffixes_key))
- def src_suffixes(self, env):
+ def subst_src_suffixes(self, env):
"""
- Returns the list of source suffixes for all src_builders of this
- Builder.
-
The suffix list may contain construction variable expansions,
so we have to evaluate the individual strings. To avoid doing
this over and over, we memoize the results for each construction
@@ -888,19 +791,31 @@ class MultiStepBuilder(BuilderBase):
"""
memo_key = id(env)
try:
- memo_dict = self._memo['src_suffixes']
+ memo_dict = self._memo['subst_src_suffixes']
except KeyError:
memo_dict = {}
- self._memo['src_suffixes'] = memo_dict
+ self._memo['subst_src_suffixes'] = memo_dict
else:
try:
return memo_dict[memo_key]
except KeyError:
pass
- suffixes = BuilderBase.src_suffixes(self, env)
+ suffixes = map(lambda x, s=self, e=env: e.subst(x), self.src_suffix)
+ memo_dict[memo_key] = suffixes
+ return suffixes
+
+ def src_suffixes(self, env):
+ """
+ Returns the list of source suffixes for all src_builders of this
+ Builder.
+
+ This is essentially a recursive descent of the src_builder "tree."
+ (This value isn't cached because there may be changes in a
+ src_builder many levels deep that we can't see.)
+ """
+ suffixes = self.subst_src_suffixes(env)
for builder in self.get_src_builders(env):
suffixes.extend(builder.src_suffixes(env))
- memo_dict[memo_key] = suffixes
return suffixes
class CompositeBuilder(SCons.Util.Proxy):
diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py
index 4e196e2..acf0722 100644
--- a/src/engine/SCons/BuilderTests.py
+++ b/src/engine/SCons/BuilderTests.py
@@ -147,6 +147,8 @@ class Environment:
class MyAction:
def __init__(self, action):
self.action = action
+ def __call__(self, *args, **kw):
+ pass
def get_executor(self, env, overrides, tlist, slist, executor_kw):
return ['executor'] + [self.action]
@@ -716,8 +718,8 @@ class BuilderTestCase(unittest.TestCase):
assert 0
- def test_ListBuilder(self):
- """Testing ListBuilder class."""
+ def test_lists(self):
+ """Testing handling lists of targets and source"""
def function2(target, source, env, tlist = [outfile, outfile2], **kw):
for t in target:
open(str(t), 'w').write("function2\n")
@@ -770,15 +772,17 @@ class BuilderTestCase(unittest.TestCase):
assert os.path.exists(test.workpath('sub1'))
assert os.path.exists(test.workpath('sub2'))
- def test_MultiStepBuilder(self):
- """Testing MultiStepBuilder class."""
+ def test_src_builder(self):
+ """Testing Builders with src_builder"""
+ # These used to be MultiStepBuilder objects until we
+ # eliminated it as a separate class
env = Environment()
builder1 = SCons.Builder.Builder(action='foo',
src_suffix='.bar',
suffix='.foo')
- builder2 = SCons.Builder.MultiStepBuilder(action=MyAction('act'),
- src_builder = builder1,
- src_suffix = '.foo')
+ builder2 = SCons.Builder.Builder(action=MyAction('act'),
+ src_builder = builder1,
+ src_suffix = '.foo')
tgt = builder2(env, source=[])
assert tgt == [], tgt
@@ -800,22 +804,22 @@ class BuilderTestCase(unittest.TestCase):
s = map(str, tgt.sources[0].sources)
assert s == ['aaa.bar'], s
- builder3 = SCons.Builder.MultiStepBuilder(action = 'foo',
- src_builder = 'xyzzy',
- src_suffix = '.xyzzy')
+ builder3 = SCons.Builder.Builder(action = 'foo',
+ src_builder = 'xyzzy',
+ src_suffix = '.xyzzy')
assert builder3.get_src_builders(Environment()) == []
builder4 = SCons.Builder.Builder(action='bld4',
src_suffix='.i',
suffix='_wrap.c')
- builder5 = SCons.Builder.MultiStepBuilder(action=MyAction('act'),
- src_builder=builder4,
- suffix='.obj',
- src_suffix='.c')
- builder6 = SCons.Builder.MultiStepBuilder(action=MyAction('act'),
- src_builder=builder5,
- suffix='.exe',
- src_suffix='.obj')
+ builder5 = SCons.Builder.Builder(action=MyAction('act'),
+ src_builder=builder4,
+ suffix='.obj',
+ src_suffix='.c')
+ builder6 = SCons.Builder.Builder(action=MyAction('act'),
+ src_builder=builder5,
+ suffix='.exe',
+ src_suffix='.obj')
tgt = builder6(env, 'test', 'test.i')[0]
s = str(tgt)
assert s == 'test.exe', s
@@ -1359,9 +1363,8 @@ class BuilderTestCase(unittest.TestCase):
b1 = SCons.Builder.Builder(action='foo', suffix='.o')
b2 = SCons.Builder.Builder(action='foo', suffix='.c')
- b3 = SCons.Builder.MultiStepBuilder(action='bar',
- src_suffix = '.foo',
- src_builder = b1)
+ b3 = SCons.Builder.Builder(action='bar', src_suffix = '.foo',
+ src_builder = b1)
b4 = SCons.Builder.Builder(action={})
b5 = SCons.Builder.Builder(action='foo', name='builder5')
b6 = SCons.Builder.Builder(action='foo')
@@ -1407,17 +1410,6 @@ class BuilderTestCase(unittest.TestCase):
for B in b3.get_src_builders(env2):
assert B.get_name(env2) == 'B1'
- tgts = b1(env, target = [outfile, outfile2], source='moo')
- for t in tgts:
- name = t.builder.get_name(env)
- assert name == 'ListBuilder(bldr1)', name
- # The following are not symbolically correct, because the
- # ListBuilder was only created on behalf of env, so it
- # would probably be OK if better correctness
- # env-to-builder mappings caused this to fail in the
- # future.
- assert t.builder.get_name(env2) == 'ListBuilder(B1)'
-
tgt = b4(env, target = 'moo', source='cow')
assert tgt[0].builder.get_name(env) == 'bldr4'
@@ -1529,7 +1521,7 @@ class CompositeBuilderTestCase(unittest.TestCase):
assert isinstance(tgt.builder, SCons.Builder.BuilderBase)
tgt = builder(env, target='t2', source='t2a.foo t2b.ina')[0]
- assert isinstance(tgt.builder, SCons.Builder.MultiStepBuilder), tgt.builder.__dict__
+ assert isinstance(tgt.builder, SCons.Builder.BuilderBase), tgt.builder.__dict__
bar_bld = SCons.Builder.Builder(action = 'a-bar',
src_suffix = '.inb',
@@ -1543,10 +1535,10 @@ class CompositeBuilderTestCase(unittest.TestCase):
builder.add_action('.bar', 'bar')
tgt = builder(env, target='t3-foo', source='t3a.foo t3b.ina')[0]
- assert isinstance(tgt.builder, SCons.Builder.MultiStepBuilder)
+ assert isinstance(tgt.builder, SCons.Builder.BuilderBase)
tgt = builder(env, target='t3-bar', source='t3a.bar t3b.inb')[0]
- assert isinstance(tgt.builder, SCons.Builder.MultiStepBuilder)
+ assert isinstance(tgt.builder, SCons.Builder.BuilderBase)
flag = 0
tgt = builder(env, target='t5', source=['test5a.foo', 'test5b.inb'])[0]
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index 4761ea0..e2883f4 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -54,7 +54,6 @@ import SCons.Node.Python
import SCons.Platform
import SCons.SConsign
import SCons.Sig
-import SCons.Sig.MD5
import SCons.Sig.TimeStamp
import SCons.Subst
import SCons.Tool
@@ -513,6 +512,7 @@ class SubstitutionEnvironment:
"""
dict = {
'ASFLAGS' : [],
+ 'CFLAGS' : [],
'CCFLAGS' : [],
'CPPDEFINES' : [],
'CPPFLAGS' : [],
@@ -641,6 +641,8 @@ class SubstitutionEnvironment:
elif arg == '-pthread':
dict['CCFLAGS'].append(arg)
dict['LINKFLAGS'].append(arg)
+ elif arg[:5] == '-std=':
+ dict['CFLAGS'].append(arg) # C only
elif arg[0] == '+':
dict['CCFLAGS'].append(arg)
dict['LINKFLAGS'].append(arg)
@@ -1667,8 +1669,15 @@ class Base(SubstitutionEnvironment):
def SourceSignatures(self, type):
type = self.subst(type)
if type == 'MD5':
- import SCons.Sig.MD5
- self._calc_module = SCons.Sig.MD5
+ try:
+ import SCons.Sig.MD5
+ except ImportError:
+ msg = "No MD5 module available, using time stamps"
+ SCons.Warnings.warn(SCons.Warnings.NoMD5ModuleWarning, msg)
+ import SCons.Sig.TimeStamp
+ self._calc_module = SCons.Sig.TimeStamp
+ else:
+ self._calc_module = SCons.Sig.MD5
elif type == 'timestamp':
import SCons.Sig.TimeStamp
self._calc_module = SCons.Sig.TimeStamp
diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py
index f0f73da..c015bc1 100644
--- a/src/engine/SCons/EnvironmentTests.py
+++ b/src/engine/SCons/EnvironmentTests.py
@@ -658,6 +658,7 @@ sys.exit(1)
empty = {
'ASFLAGS' : [],
+ 'CFLAGS' : [],
'CCFLAGS' : [],
'CPPDEFINES' : [],
'CPPFLAGS' : [],
@@ -686,6 +687,7 @@ sys.exit(1)
"-Wl,-R,rpath2 " + \
"-Wl,-Rrpath3 " + \
"-Wp,-cpp " + \
+ "-std=c99 " + \
"-framework Carbon " + \
"-frameworkdir=fwd1 " + \
"-Ffwd2 " + \
@@ -698,6 +700,7 @@ sys.exit(1)
d = env.ParseFlags(s)
assert d['ASFLAGS'] == ['-as'], d['ASFLAGS']
+ assert d['CFLAGS'] == ['-std=c99']
assert d['CCFLAGS'] == ['-X', '-Wa,-as',
'-pthread', '-mno-cygwin',
('-arch', 'i386'), ('-isysroot', '/tmp'),
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 08b8d7d..8db2928 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -48,7 +48,6 @@ import SCons.Action
from SCons.Debug import logInstanceCreation
import SCons.Errors
import SCons.Node
-import SCons.Sig.MD5
import SCons.Subst
import SCons.Util
import SCons.Warnings
@@ -776,7 +775,7 @@ class Entry(Base):
def diskcheck_match(self):
pass
- def disambiguate(self):
+ def disambiguate(self, must_exist=None):
"""
"""
if self.isdir():
@@ -802,6 +801,9 @@ class Entry(Base):
self.srcnode().isdir():
self.__class__ = Dir
self._morph()
+ elif must_exist:
+ msg = "No such file or directory: '%s'" % self.abspath
+ raise SCons.Errors.UserError, msg
else:
self.__class__ = File
self._morph()
@@ -825,18 +827,17 @@ class Entry(Base):
Since this should return the real contents from the file
system, we check to see into what sort of subclass we should
morph this Entry."""
- if self.isfile():
- self.__class__ = File
- self._morph()
- return self.get_contents()
- if self.isdir():
- self.__class__ = Dir
- self._morph()
+ try:
+ self = self.disambiguate(must_exist=1)
+ except SCons.Errors.UserError, e:
+ # There was nothing on disk with which to disambiguate
+ # this entry. Leave it as an Entry, but return a null
+ # string so calls to get_contents() in emitters and the
+ # like (e.g. in qt.py) don't have to disambiguate by hand
+ # or catch the exception.
+ return ''
+ else:
return self.get_contents()
- if self.islink():
- return '' # avoid errors for dangling symlinks
- msg = "No such file or directory: '%s'" % self.abspath
- raise SCons.Errors.UserError, msg
def must_be_a_Dir(self):
"""Called to make sure a Node is a Dir. Since we're an
@@ -1259,7 +1260,13 @@ class FS(LocalFS):
self.CacheDebug = self.CacheDebugWrite
def CacheDir(self, path):
- self.CachePath = path
+ try:
+ import SCons.Sig.MD5
+ except ImportError:
+ msg = "No MD5 module available, CacheDir() not supported"
+ SCons.Warnings.warn(SCons.Warnings.NoMD5ModuleWarning, msg)
+ else:
+ self.CachePath = path
def build_dir_target_climb(self, orig, dir, tail):
"""Create targets in corresponding build directories
@@ -2026,16 +2033,23 @@ class File(Base):
b = self.is_derived()
if not b and not self.has_src_builder():
return None
+
+ retrieved = None
if b and self.fs.CachePath:
if self.fs.cache_show:
if CacheRetrieveSilent(self, [], None, execute=1) == 0:
self.build(presub=0, execute=0)
- self.set_state(SCons.Node.executed)
- return 1
- elif CacheRetrieve(self, [], None, execute=1) == 0:
+ retrieved = 1
+ else:
+ if CacheRetrieve(self, [], None, execute=1) == 0:
+ retrieved = 1
+ if retrieved:
+ # Record build signature information, but don't
+ # push it out to cache. (We just got it from there!)
self.set_state(SCons.Node.executed)
- return 1
- return None
+ SCons.Node.Node.built(self)
+
+ return retrieved
def built(self):
@@ -2285,12 +2299,15 @@ class File(Base):
return None, None
ninfo = self.get_binfo().ninfo
if not hasattr(ninfo, 'bsig'):
+ import SCons.Errors
raise SCons.Errors.InternalError, "cachepath(%s) found no bsig" % self.path
elif ninfo.bsig is None:
+ import SCons.Errors
raise SCons.Errors.InternalError, "cachepath(%s) found a bsig of None" % self.path
# Add the path to the cache signature, because multiple
# targets built by the same action will all have the same
# build signature, and we have to differentiate them somehow.
+ import SCons.Sig.MD5
cache_sig = SCons.Sig.MD5.collect([ninfo.bsig, self.path])
subdir = string.upper(cache_sig[0])
dir = os.path.join(self.fs.CachePath, subdir)
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index 434709c..ec3c322 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -1224,12 +1224,9 @@ class FSTestCase(_tempdirTestCase):
# test Entry.get_contents()
e = fs.Entry('does_not_exist')
- exc_caught = 0
- try:
- e.get_contents()
- except SCons.Errors.UserError:
- exc_caught = 1
- assert exc_caught, "Should have caught an IOError"
+ c = e.get_contents()
+ assert c == "", c
+ assert e.__class__ == SCons.Node.FS.Entry
test.write("file", "file\n")
try:
@@ -1250,7 +1247,7 @@ class FSTestCase(_tempdirTestCase):
os.symlink('nonexistent', test.workpath('dangling_symlink'))
e = fs.Entry('dangling_symlink')
c = e.get_contents()
- assert e.__class__ == SCons.Node.FS.Entry
+ assert e.__class__ == SCons.Node.FS.Entry, e.__class__
assert c == "", c
test.write("tstamp", "tstamp\n")
@@ -1866,12 +1863,8 @@ class EntryTestCase(_tempdirTestCase):
assert e3f.__class__ is SCons.Node.FS.File, e3f.__class__
e3n = fs.Entry('e3n')
- exc_caught = None
- try:
- e3n.get_contents()
- except SCons.Errors.UserError:
- exc_caught = 1
- assert exc_caught, "did not catch expected SCons.Errors.UserError"
+ e3n.get_contents()
+ assert e3n.__class__ is SCons.Node.FS.Entry, e3n.__class__
test.subdir('e4d')
test.write('e4f', "e4f\n")
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index e5d064e..e17666b 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -219,7 +219,7 @@ class Node:
# what line in what file created the node, for example).
Annotate(self)
- def disambiguate(self):
+ def disambiguate(self, must_exist=None):
return self
def get_suffix(self):
diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py
index 3ad4cc7..22ec188 100644
--- a/src/engine/SCons/SConfTests.py
+++ b/src/engine/SCons/SConfTests.py
@@ -201,6 +201,12 @@ class SConfTestCase(unittest.TestCase):
pass
def calc_signature(self, calc):
pass
+ def get_executor(self):
+ class Executor:
+ pass
+ e = Executor()
+ e.targets = [self]
+ return e
return [MyNode('n1'), MyNode('n2')]
try:
self.scons_env.Append(BUILDERS = {'SConfActionBuilder' : MyBuilder()})
diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py
index 6eedbab..96f1526 100644
--- a/src/engine/SCons/Script/Main.py
+++ b/src/engine/SCons/Script/Main.py
@@ -961,6 +961,7 @@ def _main(args, parser):
SCons.Warnings.DeprecatedWarning,
SCons.Warnings.DuplicateEnvironmentWarning,
SCons.Warnings.MissingSConscriptWarning,
+ SCons.Warnings.NoMD5ModuleWarning,
SCons.Warnings.NoMetaclassSupportWarning,
SCons.Warnings.NoParallelSupportWarning,
SCons.Warnings.MisleadingKeywordsWarning, ]
diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py
index 2ea3f0d..04ed19a 100644
--- a/src/engine/SCons/Taskmaster.py
+++ b/src/engine/SCons/Taskmaster.py
@@ -546,10 +546,7 @@ class Taskmaster:
if node is None:
return None
- try:
- tlist = node.builder.targets(node)
- except AttributeError:
- tlist = [node]
+ tlist = node.get_executor().targets
task = self.tasker(self, tlist, node is self.current_top, node)
try:
@@ -580,10 +577,7 @@ class Taskmaster:
pass
def executed(self, node):
- try:
- tlist = node.builder.targets(node)
- except AttributeError:
- tlist = [node]
+ pass
def exception_raise(self, exception):
exc = exception[:]
diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py
index 4fefb9d..1803eee 100644
--- a/src/engine/SCons/TaskmasterTests.py
+++ b/src/engine/SCons/TaskmasterTests.py
@@ -162,6 +162,13 @@ class Node:
def postprocess(self):
self.postprocessed = 1
+ def get_executor(self):
+ class Executor:
+ pass
+ e = Executor()
+ e.targets = self.targets
+ return e
+
class OtherError(Exception):
pass
diff --git a/src/engine/SCons/Tool/bcc32.py b/src/engine/SCons/Tool/bcc32.py
index 826373f..86ca076 100644
--- a/src/engine/SCons/Tool/bcc32.py
+++ b/src/engine/SCons/Tool/bcc32.py
@@ -63,10 +63,12 @@ def generate(env):
env['CC'] = 'bcc32'
env['CCFLAGS'] = SCons.Util.CLVar('')
- env['CCCOM'] = '$CC -q $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o$TARGET $SOURCES'
+ env['CFLAGS'] = SCons.Util.CLVar('')
+ env['CCCOM'] = '$CC -q $CFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o$TARGET $SOURCES'
env['SHCC'] = '$CC'
env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
- env['SHCCCOM'] = '$SHCC -WD $SHCCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o$TARGET $SOURCES'
+ env['SHCFLAGS'] = SCons.Util.CLVar('$CFLAGS')
+ env['SHCCCOM'] = '$SHCC -WD $SHCFLAGS $SHCCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o$TARGET $SOURCES'
env['CPPDEFPREFIX'] = '-D'
env['CPPDEFSUFFIX'] = ''
env['INCPREFIX'] = '-I'
diff --git a/src/engine/SCons/Tool/cc.py b/src/engine/SCons/Tool/cc.py
index c4114b7..62b945f 100644
--- a/src/engine/SCons/Tool/cc.py
+++ b/src/engine/SCons/Tool/cc.py
@@ -63,10 +63,12 @@ def generate(env):
env['CC'] = 'cc'
env['CCFLAGS'] = SCons.Util.CLVar('')
- env['CCCOM'] = '$CC -o $TARGET -c $CCFLAGS $_CCCOMCOM $SOURCES'
+ env['CFLAGS'] = SCons.Util.CLVar('')
+ env['CCCOM'] = '$CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES'
env['SHCC'] = '$CC'
env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
- env['SHCCCOM'] = '$SHCC -o $TARGET -c $SHCCFLAGS $_CCCOMCOM $SOURCES'
+ env['SHCFLAGS'] = SCons.Util.CLVar('$CFLAGS')
+ env['SHCCCOM'] = '$SHCC -o $TARGET -c $SHCFLAGS $SHCCFLAGS $_CCCOMCOM $SOURCES'
env['CPPDEFPREFIX'] = '-D'
env['CPPDEFSUFFIX'] = ''
diff --git a/src/engine/SCons/Tool/cc.xml b/src/engine/SCons/Tool/cc.xml
index 84980db..0ebaf14 100644
--- a/src/engine/SCons/Tool/cc.xml
+++ b/src/engine/SCons/Tool/cc.xml
@@ -18,9 +18,10 @@ The C compiler.
<cvar name="CCCOM">
<summary>
-The command line used to compile a C source file to a (static) object file.
-Any options specified in the &cv-CCFLAGS; and &cv-CPPFLAGS; construction variables
-are included on this command line.
+The command line used to compile a C source file to a (static) object
+file. Any options specified in the &cv-CFLAGS;, &cv-CCFLAGS; and
+&cv-CPPFLAGS; construction variables are included on this command
+line.
</summary>
</cvar>
@@ -38,7 +39,13 @@ env = Environment(CCCOMSTR = "Compiling static object $TARGET")
<cvar name="CCFLAGS">
<summary>
-General options that are passed to the C compiler.
+General options that are passed to the C and C++ compilers.
+</summary>
+</cvar>
+
+<cvar name="CFLAGS">
+<summary>
+General options that are passed to the C compiler (C only; not C++).
</summary>
</cvar>
@@ -92,7 +99,7 @@ The C compiler used for generating shared-library objects.
<summary>
The command line used to compile a C source file
to a shared-library object file.
-Any options specified in the &cv-SHCCFLAGS; and &cv-CPPFLAGS; construction variables
+Any options specified in the &cv-SHCFLAGS;, &cv-SHCCFLAGS; and &cv-CPPFLAGS; construction variables
are included on this command line.
</summary>
</cvar>
@@ -111,7 +118,14 @@ env = Environment(SHCCCOMSTR = "Compiling shared object $TARGET")
<cvar name="SHCCFLAGS">
<summary>
-Options that are passed to the C compiler
+Options that are passed to the C and C++ compilers
+to generate shared-library objects.
+</summary>
+</cvar>
+
+<cvar name="SHCFLAGS">
+<summary>
+Options that are passed to the C compiler (only; not C++)
to generate shared-library objects.
</summary>
</cvar>
diff --git a/src/engine/SCons/Tool/f90.py b/src/engine/SCons/Tool/f90.py
index 2e2b5b1..cb450b6 100644
--- a/src/engine/SCons/Tool/f90.py
+++ b/src/engine/SCons/Tool/f90.py
@@ -119,6 +119,10 @@ def add_to_env(env):
def generate(env):
fortran.add_to_env(env)
+
+ import f77
+ f77.add_to_env(env)
+
add_to_env(env)
env['_FORTRAND'] = env.Detect(compilers) or 'f90'
diff --git a/src/engine/SCons/Tool/f95.py b/src/engine/SCons/Tool/f95.py
index 9cd2664..7adc80b 100644
--- a/src/engine/SCons/Tool/f95.py
+++ b/src/engine/SCons/Tool/f95.py
@@ -119,6 +119,13 @@ def add_to_env(env):
def generate(env):
fortran.add_to_env(env)
+
+ import f77
+ f77.add_to_env(env)
+
+ import f90
+ f90.add_to_env(env)
+
add_to_env(env)
env['_FORTRAND'] = env.Detect(compilers) or 'f95'
diff --git a/src/engine/SCons/Tool/icc.py b/src/engine/SCons/Tool/icc.py
index 20bf17c..90dece7 100644
--- a/src/engine/SCons/Tool/icc.py
+++ b/src/engine/SCons/Tool/icc.py
@@ -40,7 +40,7 @@ def generate(env):
cc.generate(env)
env['CC'] = 'icc'
- env['CCCOM'] = '$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET'
+ env['CCCOM'] = '$CC $CFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET'
env['CXXCOM'] = '$CXX $CXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET'
env['CPPDEFPREFIX'] = '/D'
env['CPPDEFSUFFIX'] = ''
diff --git a/src/engine/SCons/Tool/lex.py b/src/engine/SCons/Tool/lex.py
index 3331f6c..31f21a9 100644
--- a/src/engine/SCons/Tool/lex.py
+++ b/src/engine/SCons/Tool/lex.py
@@ -33,23 +33,60 @@ selection method.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+import os.path
+
+import string
+
import SCons.Action
import SCons.Tool
import SCons.Util
LexAction = SCons.Action.Action("$LEXCOM", "$LEXCOMSTR")
+def lexEmitter(target, source, env):
+ sourceBase, sourceExt = os.path.splitext(SCons.Util.to_String(source[0]))
+
+ if sourceExt == ".lm": # If using Objective-C
+ target = [sourceBase + ".m"] # the extension is ".m".
+
+ # This emitter essentially tries to add to the target all extra
+ # files generated by flex.
+
+ # Different options that are used to trigger the creation of extra files.
+ fileGenOptions = ["--header-file=", "--tables-file="]
+
+ for option in SCons.Util.CLVar(env.subst("$LEXFLAGS")):
+ for fileGenOption in fileGenOptions:
+ l = len(fileGenOption)
+ if option[:l] == fileGenOption:
+ # A file generating option is present, so add the
+ # file name to the target list.
+ fileName = string.strip(option[l:])
+ target.append(fileName)
+ return (target, source)
+
def generate(env):
"""Add Builders and construction variables for lex to an Environment."""
c_file, cxx_file = SCons.Tool.createCFileBuilders(env)
- c_file.add_action('.l', LexAction)
- c_file.add_action('.lex', LexAction)
- cxx_file.add_action('.ll', LexAction)
+ # C
+ c_file.add_action(".l", LexAction)
+ c_file.add_emitter(".l", lexEmitter)
+
+ c_file.add_action(".lex", LexAction)
+ c_file.add_emitter(".lex", lexEmitter)
+
+ # Objective-C
+ cxx_file.add_action(".lm", LexAction)
+ cxx_file.add_emitter(".lm", lexEmitter)
+
+ # C++
+ cxx_file.add_action(".ll", LexAction)
+ cxx_file.add_emitter(".ll", lexEmitter)
+
+ env["LEX"] = env.Detect("flex") or "lex"
+ env["LEXFLAGS"] = SCons.Util.CLVar("")
+ env["LEXCOM"] = "$LEX $LEXFLAGS -t $SOURCES > $TARGET"
- env['LEX'] = env.Detect('flex') or 'lex'
- env['LEXFLAGS'] = SCons.Util.CLVar('')
- env['LEXCOM'] = '$LEX $LEXFLAGS -t $SOURCES > $TARGET'
-
def exists(env):
- return env.Detect(['flex', 'lex'])
+ return env.Detect(["flex", "lex"])
diff --git a/src/engine/SCons/Tool/mingw.py b/src/engine/SCons/Tool/mingw.py
index d679b53..0639535 100644
--- a/src/engine/SCons/Tool/mingw.py
+++ b/src/engine/SCons/Tool/mingw.py
@@ -145,7 +145,7 @@ def generate(env):
env['RCINCFLAGS'] = '$( ${_concat(RCINCPREFIX, CPPPATH, RCINCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
env['RCINCPREFIX'] = '--include-dir '
env['RCINCSUFFIX'] = ''
- env['RCCOM'] = '$RC $_CPPDEFFLAGS $RCINCFLAGS ${RCINCPREFIX}${SOURCE.dir} $RCFLAGS -i $SOURCE -o $TARGET'
+ env['RCCOM'] = '$RC $_CPPDEFFLAGS $RCINCFLAGS ${RCINCPREFIX} ${SOURCE.dir} $RCFLAGS -i $SOURCE -o $TARGET'
env['BUILDERS']['RES'] = res_builder
# Some setting from the platform also have to be overridden:
diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py
index 80b5926..7e476f5 100644
--- a/src/engine/SCons/Tool/msvc.py
+++ b/src/engine/SCons/Tool/msvc.py
@@ -687,10 +687,12 @@ def generate(env):
env['CCCOMFLAGS'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET $CCPCHFLAGS $CCPDBFLAGS'
env['CC'] = 'cl'
env['CCFLAGS'] = SCons.Util.CLVar('/nologo')
- env['CCCOM'] = '$CC $CCFLAGS $CCCOMFLAGS'
+ env['CFLAGS'] = SCons.Util.CLVar('')
+ env['CCCOM'] = '$CC $CFLAGS $CCFLAGS $CCCOMFLAGS'
env['SHCC'] = '$CC'
env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
- env['SHCCCOM'] = '$SHCC $SHCCFLAGS $CCCOMFLAGS'
+ env['SHCFLAGS'] = SCons.Util.CLVar('$CFLAGS')
+ env['SHCCCOM'] = '$SHCC $SHCFLAGS $SHCCFLAGS $CCCOMFLAGS'
env['CXX'] = '$CC'
env['CXXFLAGS'] = SCons.Util.CLVar('$CCFLAGS $( /TP $)')
env['CXXCOM'] = '$CXX $CXXFLAGS $CCCOMFLAGS'
diff --git a/src/engine/SCons/Tool/mwcc.py b/src/engine/SCons/Tool/mwcc.py
index 52f55ee..a1ede44 100644
--- a/src/engine/SCons/Tool/mwcc.py
+++ b/src/engine/SCons/Tool/mwcc.py
@@ -171,14 +171,15 @@ def generate(env):
env['CCCOMFLAGS'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -nolink -o $TARGET $SOURCES'
env['CC'] = 'mwcc'
- env['CCCOM'] = '$CC $CCFLAGS $CCCOMFLAGS'
+ env['CCCOM'] = '$CC $CFLAGS $CCFLAGS $CCCOMFLAGS'
env['CXX'] = 'mwcc'
env['CXXCOM'] = '$CXX $CXXFLAGS $CCCOMFLAGS'
env['SHCC'] = '$CC'
env['SHCCFLAGS'] = '$CCFLAGS'
- env['SHCCCOM'] = '$SHCC $SHCCFLAGS $CCCOMFLAGS'
+ env['SHCFLAGS'] = '$CFLAGS'
+ env['SHCCCOM'] = '$SHCC $SHCFLAGS $SHCCFLAGS $CCCOMFLAGS'
env['SHCXX'] = '$CXX'
env['SHCXXFLAGS'] = '$CXXFLAGS'
diff --git a/src/engine/SCons/Tool/qt.py b/src/engine/SCons/Tool/qt.py
index 5077901..4d290c7 100644
--- a/src/engine/SCons/Tool/qt.py
+++ b/src/engine/SCons/Tool/qt.py
@@ -313,8 +313,8 @@ def generate(env):
env['BUILDERS']['Uic'] = uicBld
env['BUILDERS']['Moc'] = mocBld
static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
- static_obj.src_builder.append('Uic')
- shared_obj.src_builder.append('Uic')
+ static_obj.add_src_builder('Uic')
+ shared_obj.add_src_builder('Uic')
# We use the emitters of Program / StaticLibrary / SharedLibrary
# to scan for moc'able files
diff --git a/src/engine/SCons/Tool/yacc.py b/src/engine/SCons/Tool/yacc.py
index b8916ae..cbccb29 100644
--- a/src/engine/SCons/Tool/yacc.py
+++ b/src/engine/SCons/Tool/yacc.py
@@ -34,6 +34,7 @@ selection method.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os.path
+import string
import SCons.Defaults
import SCons.Tool
@@ -42,31 +43,64 @@ import SCons.Util
YaccAction = SCons.Action.Action("$YACCCOM", "$YACCCOMSTR")
def _yaccEmitter(target, source, env, ysuf, hsuf):
+ flags = SCons.Util.CLVar(env.subst("$YACCFLAGS"))
+ targetBase, targetExt = os.path.splitext(SCons.Util.to_String(target[0]))
+
+ if '.ym' in ysuf: # If using Objective-C
+ target = [targetBase + ".m"] # the extension is ".m".
+
+
# If -d is specified on the command line, yacc will emit a .h
- # or .hpp file as well as a .c or .cpp file, depending on whether
- # the input file is a .y or .yy, respectively.
- if len(source) and '-d' in SCons.Util.CLVar(env.subst("$YACCFLAGS")):
+ # or .hpp file with the same name as the .c or .cpp output file.
+ if '-d' in flags:
+ target.append(targetBase + env.subst(hsuf))
+
+ # If -g is specified on the command line, yacc will emit a .vcg
+ # file with the same base name as the .y, .yacc, .ym or .yy file.
+ if "-g" in flags:
base, ext = os.path.splitext(SCons.Util.to_String(source[0]))
- if ext in ysuf:
- base, ext = os.path.splitext(SCons.Util.to_String(target[0]))
- target.append(base + env.subst(hsuf))
+ target.append(base + env.subst("$YACCVCGFILESUFFIX"))
+
+ # With --defines and --graph, the name of the file is totally defined
+ # in the options.
+ fileGenOptions = ["--defines=", "--graph="]
+ for option in flags:
+ for fileGenOption in fileGenOptions:
+ l = len(fileGenOption)
+ if option[:l] == fileGenOption:
+ # A file generating option is present, so add the file
+ # name to the list of targets.
+ fileName = string.strip(option[l:])
+ target.append(fileName)
+
return (target, source)
def yEmitter(target, source, env):
return _yaccEmitter(target, source, env, ['.y', '.yacc'], '$YACCHFILESUFFIX')
+def ymEmitter(target, source, env):
+ return _yaccEmitter(target, source, env, ['.ym'], '$YACCHFILESUFFIX')
+
def yyEmitter(target, source, env):
return _yaccEmitter(target, source, env, ['.yy'], '$YACCHXXFILESUFFIX')
def generate(env):
"""Add Builders and construction variables for yacc to an Environment."""
c_file, cxx_file = SCons.Tool.createCFileBuilders(env)
-
+
+ # C
c_file.add_action('.y', YaccAction)
- c_file.add_action('.yacc', YaccAction)
- cxx_file.add_action('.yy', YaccAction)
c_file.add_emitter('.y', yEmitter)
+
+ c_file.add_action('.yacc', YaccAction)
c_file.add_emitter('.yacc', yEmitter)
+
+ # Objective-C
+ c_file.add_action('.ym', YaccAction)
+ c_file.add_emitter('.ym', ymEmitter)
+
+ # C++
+ cxx_file.add_action('.yy', YaccAction)
cxx_file.add_emitter('.yy', yyEmitter)
env['YACC'] = env.Detect('bison') or 'yacc'
@@ -74,6 +108,7 @@ def generate(env):
env['YACCCOM'] = '$YACC $YACCFLAGS -o $TARGET $SOURCES'
env['YACCHFILESUFFIX'] = '.h'
env['YACCHXXFILESUFFIX'] = '.hpp'
+ env['YACCVCGFILESUFFIX'] = '.vcg'
def exists(env):
return env.Detect(['bison', 'yacc'])
diff --git a/src/engine/SCons/Tool/yacc.xml b/src/engine/SCons/Tool/yacc.xml
index 48bb323..8a23d0b 100644
--- a/src/engine/SCons/Tool/yacc.xml
+++ b/src/engine/SCons/Tool/yacc.xml
@@ -79,3 +79,20 @@ The default value is
<filename>.hpp</filename>.
</summary>
</cvar>
+
+<cvar name="YACCVCGFILESUFFIX">
+<summary>
+The suffix of the file
+containing the VCG grammar automaton definition
+when the
+<option>--graph=</option>
+option is used.
+Note that setting this variable does not cause
+the parser generator to generate a VCG
+file with the specified suffix,
+it exists to allow you to specify
+what suffix the parser generator will use of its own accord.
+The default value is
+<filename>.vcg</filename>.
+</summary>
+</cvar>
diff --git a/src/engine/SCons/Warnings.py b/src/engine/SCons/Warnings.py
index 27614bf..1b13c96 100644
--- a/src/engine/SCons/Warnings.py
+++ b/src/engine/SCons/Warnings.py
@@ -54,6 +54,9 @@ class DuplicateEnvironmentWarning(Warning):
class MissingSConscriptWarning(Warning):
pass
+class NoMD5ModuleWarning(Warning):
+ pass
+
class NoMetaclassSupportWarning(Warning):
pass
diff --git a/src/script/scons-time.py b/src/script/scons-time.py
index 1867d44..b0feaab 100644
--- a/src/script/scons-time.py
+++ b/src/script/scons-time.py
@@ -31,6 +31,8 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import getopt
import glob
import os
diff --git a/src/test_copyrights.py b/src/test_copyrights.py
index ce78a8b..2bc951e 100644
--- a/src/test_copyrights.py
+++ b/src/test_copyrights.py
@@ -25,129 +25,188 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
-Verify that we have proper Copyright notices on all the right files
-in our distributions.
+Verify that we have proper strings like Copyright notices on all the
+right files in our distributions.
-Note that this is a packaging test, not a functional test, so the
-name of this script doesn't end in *Tests.py.
+Note that this is a source file and packaging test, not a functional test,
+so the name of this script doesn't end in *Tests.py.
"""
+import fnmatch
import os
import os.path
import re
import string
+import TestCmd
import TestSCons
-test = TestSCons.TestSCons()
+# Use TestCmd, not TestSCons, so we don't chdir to a temporary directory.
+test = TestCmd.TestCmd()
-try:
- cwd = os.environ['SCONS_CWD']
-except KeyError:
- cwd = os.getcwd()
+scons_version = TestSCons.SConsVersion
def build_path(*args):
- return apply(os.path.join, (cwd, 'build',)+args)
+ return apply(os.path.join, ('build',)+args)
build_scons = build_path('scons')
-build_local = build_path('scons-local', 'scons-local-'+test.scons_version)
+build_local = build_path('scons-local', 'scons-local-'+scons_version)
build_src = build_path('scons-src')
-class Collect:
- expression = re.compile('Copyright.*The SCons Foundation')
- def __init__(self, directory, remove_list):
- self.copyright = []
- self.no_copyright = []
- self.remove = {}
+class Checker:
+ def __init__(self, directory, search_list = [], remove_list=[]):
+ self.directory = directory
+ self.search_list = search_list
+ self.remove_dict = {}
for r in remove_list:
- self.remove[os.path.join(directory, r)] = 1
-
-def visit(collect, dirname, names):
- make_path_tuple = lambda n, d=dirname: (n, os.path.join(d, n))
- for name, path in map(make_path_tuple, names):
- if collect.remove.get(path):
- names.remove(name)
- elif os.path.isfile(path):
- if collect.expression.search(open(path, 'r').read()):
- collect.copyright.append(path)
- else:
- collect.no_copyright.append(path)
-
-# Map each directory to search (dictionary keys) to a list of its
-# subsidiary files and directories to exclude from copyright checks.
-check = {
- build_scons : [
- 'build',
- 'build-stamp',
- 'configure-stamp',
- 'debian',
- 'dist',
- 'engine/SCons/Conftest.py',
- 'engine/SCons/dblite.py',
- 'engine/SCons/Optik',
- 'MANIFEST',
- 'os_spawnv_fix.diff',
- 'setup.cfg',
- ],
- build_local : [
- 'SCons/Conftest.py',
- 'SCons/dblite.py',
- 'SCons/Optik',
- ],
- build_src : [
- 'bin',
- 'config',
- 'debian',
- 'doc/design',
- 'doc/MANIFEST',
- 'doc/python10',
- 'doc/reference',
- 'doc/man/MANIFEST',
- 'doc/user/cons.pl',
- 'doc/user/MANIFEST',
- 'doc/user/SCons-win32-install-1.jpg',
- 'doc/user/SCons-win32-install-2.jpg',
- 'doc/user/SCons-win32-install-3.jpg',
- 'doc/user/SCons-win32-install-4.jpg',
- 'gentoo',
- 'QMTest/classes.qmc',
- 'QMTest/configuration',
- 'QMTest/TestCmd.py',
- 'QMTest/TestCommon.py',
- 'QMTest/unittest.py',
- 'src/os_spawnv_fix.diff',
- 'src/MANIFEST.in',
- 'src/setup.cfg',
- 'src/engine/MANIFEST.in',
- 'src/engine/MANIFEST-xml.in',
- 'src/engine/setup.cfg',
- 'src/engine/SCons/Conftest.py',
- 'src/engine/SCons/dblite.py',
- 'src/engine/SCons/Optik',
- 'src/script/MANIFEST.in',
- 'src/script/setup.cfg',
- ],
-}
-
-no_copyright = []
-no_result = []
-
-for directory, remove_list in check.items():
- if os.path.exists(directory):
- c = Collect(directory, remove_list)
- os.path.walk(directory, visit, c)
- no_copyright.extend(c.no_copyright)
- else:
- no_result.append(directory)
-
-if no_copyright:
- print "Found the following files with no copyrights:"
- print "\t" + string.join(no_copyright, "\n\t")
+ self.remove_dict[os.path.join(directory, r)] = 1
+
+ def directory_exists(self):
+ return os.path.exists(self.directory)
+
+ def remove_path(self, path):
+ return self.remove_dict.get(path)
+
+ def search_this(self, path):
+ if self.search_list:
+ for pattern in self.search_list:
+ if fnmatch.fnmatch(path, pattern):
+ return 1
+ return None
+ else:
+ return os.path.isfile(path)
+
+ def visit(self, result, dirname, names):
+ make_path_tuple = lambda n, d=dirname: (n, os.path.join(d, n))
+ for name, path in map(make_path_tuple, names):
+ if self.remove_path(path):
+ names.remove(name)
+ elif self.search_this(path):
+ body = open(path, 'r').read()
+ for expr in self.expressions:
+ if not expr.search(body):
+ msg = '%s: missing %s' % (path, repr(expr.pattern))
+ result.append(msg)
+
+ def find_missing(self):
+ result = []
+ os.path.walk(self.directory, self.visit, result)
+ return result
+
+class CheckUnexpandedStrings(Checker):
+ expressions = [
+ re.compile('__COPYRIGHT__'),
+ re.compile('__FILE__ __REVISION__ __DATE__ __DEVELOPER__'),
+ ]
+ def must_be_built(self):
+ return None
+
+class CheckExpandedCopyright(Checker):
+ expressions = [
+ re.compile('Copyright.*The SCons Foundation'),
+ ]
+ def must_be_built(self):
+ return 1
+
+check_list = [
+
+ CheckUnexpandedStrings(
+ 'src',
+ search_list = [ '*.py' ],
+ remove_list = [
+ 'engine/SCons/Conftest.py',
+ 'engine/SCons/dblite.py',
+ 'engine/SCons/Optik',
+ ],
+ ),
+
+ CheckUnexpandedStrings(
+ 'test',
+ search_list = [ '*.py' ],
+ ),
+
+ CheckExpandedCopyright(
+ build_scons,
+ remove_list = [
+ 'build',
+ 'build-stamp',
+ 'configure-stamp',
+ 'debian',
+ 'dist',
+ 'engine/SCons/Conftest.py',
+ 'engine/SCons/dblite.py',
+ 'engine/SCons/Optik',
+ 'MANIFEST',
+ 'os_spawnv_fix.diff',
+ 'setup.cfg',
+ ],
+ ),
+
+ CheckExpandedCopyright(
+ build_local,
+ remove_list = [
+ 'SCons/Conftest.py',
+ 'SCons/dblite.py',
+ 'SCons/Optik',
+ ],
+ ),
+
+ CheckExpandedCopyright(
+ build_src,
+ remove_list = [
+ 'bin',
+ 'config',
+ 'debian',
+ 'doc/design',
+ 'doc/MANIFEST',
+ 'doc/python10',
+ 'doc/reference',
+ 'doc/man/MANIFEST',
+ 'doc/user/cons.pl',
+ 'doc/user/MANIFEST',
+ 'doc/user/SCons-win32-install-1.jpg',
+ 'doc/user/SCons-win32-install-2.jpg',
+ 'doc/user/SCons-win32-install-3.jpg',
+ 'doc/user/SCons-win32-install-4.jpg',
+ 'gentoo',
+ 'QMTest/classes.qmc',
+ 'QMTest/configuration',
+ 'QMTest/TestCmd.py',
+ 'QMTest/TestCommon.py',
+ 'QMTest/unittest.py',
+ 'src/os_spawnv_fix.diff',
+ 'src/MANIFEST.in',
+ 'src/setup.cfg',
+ 'src/engine/MANIFEST.in',
+ 'src/engine/MANIFEST-xml.in',
+ 'src/engine/setup.cfg',
+ 'src/engine/SCons/Conftest.py',
+ 'src/engine/SCons/dblite.py',
+ 'src/engine/SCons/Optik',
+ 'src/script/MANIFEST.in',
+ 'src/script/setup.cfg',
+ ],
+ ),
+
+]
+
+missing_strings = []
+not_built = []
+
+for collector in check_list:
+ if collector.directory_exists():
+ missing_strings.extend(collector.find_missing())
+ elif collector.must_be_built():
+ not_built.append(collector.directory)
+
+if missing_strings:
+ print "Found the following files with missing strings:"
+ print "\t" + string.join(missing_strings, "\n\t")
test.fail_test(1)
-if no_result:
- print "Cannot check copyrights, the following have apparently not been built:"
- print "\t" + string.join(no_result, "\n\t")
+if not_built:
+ print "Cannot check all strings, the following have apparently not been built:"
+ print "\t" + string.join(not_built, "\n\t")
test.no_result(1)
test.pass_test()