summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CHANGES.txt24
-rw-r--r--src/engine/MANIFEST.in7
-rw-r--r--src/engine/SCons/Executor.py8
-rw-r--r--src/engine/SCons/Job.py38
-rw-r--r--src/engine/SCons/Node/FS.py14
-rw-r--r--src/engine/SCons/Options/BoolOption.py35
-rw-r--r--src/engine/SCons/Options/EnumOption.py35
-rw-r--r--src/engine/SCons/Options/ListOption.py35
-rw-r--r--src/engine/SCons/Options/PackageOption.py35
-rw-r--r--src/engine/SCons/Options/PathOption.py35
-rw-r--r--src/engine/SCons/Options/__init__.py (renamed from src/engine/SCons/Options.py)12
-rw-r--r--src/engine/SCons/Taskmaster.py120
-rw-r--r--src/engine/SCons/TaskmasterTests.py25
-rw-r--r--src/engine/SCons/Tool/FortranCommon.py2
-rw-r--r--src/engine/SCons/Tool/c++.py2
-rw-r--r--src/engine/SCons/Tool/g++.py14
-rw-r--r--src/setup.py1
17 files changed, 337 insertions, 105 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 37422bc..8a3515f 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -8,6 +8,30 @@
+RELEASE XXX - XXX
+
+ From Greg Noel:
+
+ - Fix use of $CXXFLAGS when building C++ shared object files.
+
+ From Steven Knight:
+
+ - Fix a regression when a Builder's source_scanner doesn't select
+ a more specific scanner for the suffix of a specified source file.
+
+ - Fix the Options object backwards compatibility so people can still
+ "import SCons.Options.{Bool,Enum,List,Package,Path}Option" submodules.
+
+ - Fix searching for implicit dependencies when an Entry Node shows up
+ in the search path list.
+
+ From Stefano:
+
+ - Fix expansion of $FORTRANMODDIR in the default Fortran command line(s)
+ when it's set to something like ${TARGET.dir}.
+
+
+
RELEASE 0.98.2 - Sun, 20 Apr 2008 23:38:56 -0700
From Steven Knight:
diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in
index 4c8b7a7..f220946 100644
--- a/src/engine/MANIFEST.in
+++ b/src/engine/MANIFEST.in
@@ -28,7 +28,12 @@ SCons/Node/__init__.py
SCons/Node/Alias.py
SCons/Node/FS.py
SCons/Node/Python.py
-SCons/Options.py
+SCons/Options/__init__.py
+SCons/Options/BoolOption.py
+SCons/Options/EnumOption.py
+SCons/Options/ListOption.py
+SCons/Options/PackageOption.py
+SCons/Options/PathOption.py
SCons/PathList.py
SCons/Platform/__init__.py
SCons/Platform/aix.py
diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py
index a9417bc..435b54c 100644
--- a/src/engine/SCons/Executor.py
+++ b/src/engine/SCons/Executor.py
@@ -237,11 +237,11 @@ class Executor:
if scanner:
for node in node_list:
node.disambiguate()
- scanner = scanner.select(node)
- if not scanner:
+ s = scanner.select(node)
+ if not s:
continue
- path = self.get_build_scanner_path(scanner)
- deps.extend(node.get_implicit_deps(env, scanner, path))
+ path = self.get_build_scanner_path(s)
+ deps.extend(node.get_implicit_deps(env, s, path))
else:
kw = self.get_kw()
for node in node_list:
diff --git a/src/engine/SCons/Job.py b/src/engine/SCons/Job.py
index d93952c..545df98 100644
--- a/src/engine/SCons/Job.py
+++ b/src/engine/SCons/Job.py
@@ -49,6 +49,18 @@ default_stack_size = 256
interrupt_msg = 'Build interrupted.'
+
+class InterruptState:
+ def __init__(self):
+ self.interrupted = False
+
+ def set(self):
+ self.interrupted = True
+
+ def __call__(self):
+ return self.interrupted
+
+
class Jobs:
"""An instance of this class initializes N jobs, and provides
methods for starting, stopping, and waiting on all N jobs.
@@ -84,8 +96,6 @@ class Jobs:
self.job = Serial(taskmaster)
self.num_jobs = 1
- self.job.interrupted = False
-
def run(self, postfunc=lambda: None):
"""Run the jobs.
@@ -104,7 +114,7 @@ class Jobs:
def were_interrupted(self):
"""Returns whether the jobs were interrupted by a signal."""
- return self.job.interrupted
+ return self.job.interrupted()
def _setup_sig_handler(self):
"""Setup an interrupt handler so that SCons can shutdown cleanly in
@@ -127,10 +137,10 @@ class Jobs:
SCons forks before executing another process. In that case, we
want the child to exit immediately.
"""
- def handler(signum, stack, parentpid=os.getpid()):
+ def handler(signum, stack, self=self, parentpid=os.getpid()):
if os.getpid() == parentpid:
self.job.taskmaster.stop()
- self.job.interrupted = True
+ self.job.interrupted.set()
else:
os._exit(2)
@@ -170,6 +180,7 @@ class Serial:
execute (e.g. execute() raised an exception)."""
self.taskmaster = taskmaster
+ self.interrupted = InterruptState()
def start(self):
"""Start the job. This will begin pulling tasks from the taskmaster
@@ -188,7 +199,7 @@ class Serial:
if task.needs_execute():
task.execute()
except:
- if self.interrupted:
+ if self.interrupted():
try:
raise SCons.Errors.BuildError(
task.targets[0], errstr=interrupt_msg)
@@ -221,11 +232,12 @@ else:
dequeues the task, executes it, and posts a tuple including the task
and a boolean indicating whether the task executed successfully. """
- def __init__(self, requestQueue, resultsQueue):
+ def __init__(self, requestQueue, resultsQueue, interrupted):
threading.Thread.__init__(self)
self.setDaemon(1)
self.requestQueue = requestQueue
self.resultsQueue = resultsQueue
+ self.interrupted = interrupted
self.start()
def run(self):
@@ -239,6 +251,9 @@ else:
break
try:
+ if self.interrupted():
+ raise SCons.Errors.BuildError(
+ task.targets[0], errstr=interrupt_msg)
task.execute()
except:
task.exception_set()
@@ -251,7 +266,7 @@ else:
class ThreadPool:
"""This class is responsible for spawning and managing worker threads."""
- def __init__(self, num, stack_size):
+ def __init__(self, num, stack_size, interrupted):
"""Create the request and reply queues, and 'num' worker threads.
One must specify the stack size of the worker threads. The
@@ -277,7 +292,7 @@ else:
# Create worker threads
self.workers = []
for _ in range(num):
- worker = Worker(self.requestQueue, self.resultsQueue)
+ worker = Worker(self.requestQueue, self.resultsQueue, interrupted)
self.workers.append(worker)
# Once we drop Python 1.5 we can change the following to:
@@ -348,7 +363,8 @@ else:
multiple tasks simultaneously. """
self.taskmaster = taskmaster
- self.tp = ThreadPool(num, stack_size)
+ self.interrupted = InterruptState()
+ self.tp = ThreadPool(num, stack_size, self.interrupted)
self.maxjobs = num
@@ -395,7 +411,7 @@ else:
if ok:
task.executed()
else:
- if self.interrupted:
+ if self.interrupted():
try:
raise SCons.Errors.BuildError(
task.targets[0], errstr=interrupt_msg)
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 6ff3833..bd8b564 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -2873,9 +2873,10 @@ class FileFinder:
node = p.entries[norm_name]
except KeyError:
return p.dir_on_disk(name)
- # Once we move to Python 2.2 we can do:
- #if isinstance(node, (Dir, Entry)):
- if isinstance(node, Dir) or isinstance(node, Entry):
+ if isinstance(node, Dir):
+ return node
+ if isinstance(node, Entry):
+ node.must_be_same(Dir)
return node
return None
@@ -2944,8 +2945,11 @@ class FileFinder:
# node = p.entries[norm_name]
# except KeyError:
# return p.dir_on_disk(name)
- # # Once we move to Python 2.2 we can do:
- # #if isinstance(node, (Dir, Entry)):
+ # if isinstance(node, Dir):
+ # return node
+ # if isinstance(node, Entry):
+ # node.must_be_same(Dir)
+ # return node
# if isinstance(node, Dir) or isinstance(node, Entry):
# return node
# return None
diff --git a/src/engine/SCons/Options/BoolOption.py b/src/engine/SCons/Options/BoolOption.py
new file mode 100644
index 0000000..c3b50b3
--- /dev/null
+++ b/src/engine/SCons/Options/BoolOption.py
@@ -0,0 +1,35 @@
+#
+# __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__"
+
+__doc__ = """Place-holder for the old SCons.Options module hierarchy
+
+This is for backwards compatibility. The new equivalent is the Variables/
+class hierarchy. These will have deprecation warnings added (some day),
+and will then be removed entirely (some day).
+"""
+
+import SCons.Variables
+
+BoolOption = SCons.Variables.BoolVariable
diff --git a/src/engine/SCons/Options/EnumOption.py b/src/engine/SCons/Options/EnumOption.py
new file mode 100644
index 0000000..24ccf28
--- /dev/null
+++ b/src/engine/SCons/Options/EnumOption.py
@@ -0,0 +1,35 @@
+#
+# __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__"
+
+__doc__ = """Place-holder for the old SCons.Options module hierarchy
+
+This is for backwards compatibility. The new equivalent is the Variables/
+class hierarchy. These will have deprecation warnings added (some day),
+and will then be removed entirely (some day).
+"""
+
+import SCons.Variables
+
+EnumOption = SCons.Variables.EnumVariable
diff --git a/src/engine/SCons/Options/ListOption.py b/src/engine/SCons/Options/ListOption.py
new file mode 100644
index 0000000..1a56806
--- /dev/null
+++ b/src/engine/SCons/Options/ListOption.py
@@ -0,0 +1,35 @@
+#
+# __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__"
+
+__doc__ = """Place-holder for the old SCons.Options module hierarchy
+
+This is for backwards compatibility. The new equivalent is the Variables/
+class hierarchy. These will have deprecation warnings added (some day),
+and will then be removed entirely (some day).
+"""
+
+import SCons.Variables
+
+ListOption = SCons.Variables.ListVariable
diff --git a/src/engine/SCons/Options/PackageOption.py b/src/engine/SCons/Options/PackageOption.py
new file mode 100644
index 0000000..479a8a2
--- /dev/null
+++ b/src/engine/SCons/Options/PackageOption.py
@@ -0,0 +1,35 @@
+#
+# __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__"
+
+__doc__ = """Place-holder for the old SCons.Options module hierarchy
+
+This is for backwards compatibility. The new equivalent is the Variables/
+class hierarchy. These will have deprecation warnings added (some day),
+and will then be removed entirely (some day).
+"""
+
+import SCons.Variables
+
+PackageOption = SCons.Variables.PackageVariable
diff --git a/src/engine/SCons/Options/PathOption.py b/src/engine/SCons/Options/PathOption.py
new file mode 100644
index 0000000..e694127
--- /dev/null
+++ b/src/engine/SCons/Options/PathOption.py
@@ -0,0 +1,35 @@
+#
+# __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__"
+
+__doc__ = """Place-holder for the old SCons.Options module hierarchy
+
+This is for backwards compatibility. The new equivalent is the Variables/
+class hierarchy. These will have deprecation warnings added (some day),
+and will then be removed entirely (some day).
+"""
+
+import SCons.Variables
+
+PathOption = SCons.Variables.PathVariable
diff --git a/src/engine/SCons/Options.py b/src/engine/SCons/Options/__init__.py
index 0f2fde1..5cc09a7 100644
--- a/src/engine/SCons/Options.py
+++ b/src/engine/SCons/Options/__init__.py
@@ -32,6 +32,12 @@ and will then be removed entirely (some day).
import SCons.Variables
+from BoolOption import BoolOption # okay
+from EnumOption import EnumOption # okay
+from ListOption import ListOption # naja
+from PackageOption import PackageOption # naja
+from PathOption import PathOption # okay
+
class Options(SCons.Variables.Variables):
def AddOptions(self, *args, **kw):
@@ -48,9 +54,3 @@ class Options(SCons.Variables.Variables):
return apply(SCons.Variables.Variables.FormatVariableHelpText,
(self,) + args,
kw)
-
-BoolOption = SCons.Variables.BoolVariable
-EnumOption = SCons.Variables.EnumVariable
-ListOption = SCons.Variables.ListVariable
-PackageOption = SCons.Variables.PackageVariable
-PathOption = SCons.Variables.PathVariable
diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py
index 8a0fcf7..6f93ca7 100644
--- a/src/engine/SCons/Taskmaster.py
+++ b/src/engine/SCons/Taskmaster.py
@@ -277,9 +277,9 @@ class Task:
Explicit stop-the-build failure.
"""
- # Invoke fail_continue() to clean-up the pending children
+ # Invoke will_not_build() to clean-up the pending children
# list.
- self.fail_continue()
+ self.tm.will_not_build(self.targets)
# Tell the taskmaster to not start any new tasks
self.tm.stop()
@@ -297,44 +297,8 @@ class Task:
This sets failure status on the target nodes and all of
their dependent parent nodes.
"""
+ self.tm.will_not_build(self.targets)
- pending_children = self.tm.pending_children
-
- to_visit = set()
- for t in self.targets:
- # Set failure state on all of the parents that were dependent
- # on this failed build.
- if t.state != NODE_FAILED:
- t.state = NODE_FAILED
- parents = t.waiting_parents
- to_visit = to_visit | parents
- pending_children = pending_children - parents
-
- try:
- while 1:
- try:
- node = to_visit.pop()
- except AttributeError:
- # Python 1.5.2
- if len(to_visit):
- node = to_visit[0]
- to_visit.remove(node)
- else:
- break
- if node.state != NODE_FAILED:
- node.state = NODE_FAILED
- parents = node.waiting_parents
- to_visit = to_visit | parents
- pending_children = pending_children - parents
- except KeyError:
- # The container to_visit has been emptied.
- pass
-
- # We have the stick back the pending_children list into the
- # task master because the python 1.5.2 compatibility does not
- # allow us to use in-place updates
- self.tm.pending_children = pending_children
-
def make_ready_all(self):
"""
Marks all targets in a task ready for execution.
@@ -557,7 +521,15 @@ class Taskmaster:
def no_next_candidate(self):
"""
Stops Taskmaster processing by not returning a next candidate.
- """
+
+ Note that we have to clean-up the Taskmaster candidate list
+ because the cycle detection depends on the fact all nodes have
+ been processed somehow.
+ """
+ while self.candidates:
+ candidates = self.candidates
+ self.candidates = []
+ self.will_not_build(candidates)
return None
def _find_next_ready_node(self):
@@ -604,9 +576,9 @@ class Taskmaster:
S.considered = S.considered + 1
else:
S = None
-
- if T: T.write('Taskmaster: Considering node <%-10s %s> and its children:\n' %
- (StateString[node.get_state()], repr(str(node))))
+
+ if T: T.write('Taskmaster: Considering node <%-10s %-3s %s> and its children:\n' %
+ (StateString[node.get_state()], node.ref_count, repr(str(node))))
if state == NODE_NO_STATE:
# Mark this node as being on the execution stack:
@@ -643,8 +615,8 @@ class Taskmaster:
for child in chain(children,node.prerequisites):
childstate = child.get_state()
- if T: T.write('Taskmaster: <%-10s %s>\n' %
- (StateString[childstate], repr(str(child))))
+ if T: T.write('Taskmaster: <%-10s %-3s %s>\n' %
+ (StateString[childstate], child.ref_count, repr(str(child))))
if childstate == NODE_NO_STATE:
children_not_visited.append(child)
@@ -685,8 +657,8 @@ class Taskmaster:
node.set_state(NODE_FAILED)
if S: S.child_failed = S.child_failed + 1
- if T: T.write('Taskmaster:****** <%-10s %s>\n' %
- (StateString[node.get_state()], repr(str(node))))
+ if T: T.write('Taskmaster:****** <%-10s %-3s %s>\n' %
+ (StateString[node.get_state()], node.ref_count, repr(str(node))))
continue
if children_not_ready:
@@ -700,6 +672,8 @@ class Taskmaster:
# count so we can be put back on the list for
# re-evaluation when they've all finished.
node.ref_count = node.ref_count + child.add_to_waiting_parents(node)
+ if T: T.write('Taskmaster: adjusting ref count: <%-10s %-3s %s>\n' %
+ (StateString[node.get_state()], node.ref_count, repr(str(node))))
self.pending_children = self.pending_children | children_pending
@@ -720,8 +694,8 @@ class Taskmaster:
# The default when we've gotten through all of the checks above:
# this node is ready to be built.
if S: S.build = S.build + 1
- if T: T.write('Taskmaster: Evaluating <%-10s %s>\n' %
- (StateString[node.get_state()], repr(str(node))))
+ if T: T.write('Taskmaster: Evaluating <%-10s %-3s %s>\n' %
+ (StateString[node.get_state()], node.ref_count, repr(str(node))))
return node
return None
@@ -757,6 +731,48 @@ class Taskmaster:
return task
+ def will_not_build(self, nodes):
+ """
+ Perform clean-up about nodes that will never be built.
+ """
+
+ pending_children = self.pending_children
+
+ to_visit = set()
+ for node in nodes:
+ # Set failure state on all of the parents that were dependent
+ # on this failed build.
+ if node.state != NODE_FAILED:
+ node.state = NODE_FAILED
+ parents = node.waiting_parents
+ to_visit = to_visit | parents
+ pending_children = pending_children - parents
+
+ try:
+ while 1:
+ try:
+ node = to_visit.pop()
+ except AttributeError:
+ # Python 1.5.2
+ if len(to_visit):
+ node = to_visit[0]
+ to_visit.remove(node)
+ else:
+ break
+ if node.state != NODE_FAILED:
+ node.state = NODE_FAILED
+ parents = node.waiting_parents
+ to_visit = to_visit | parents
+ pending_children = pending_children - parents
+ except KeyError:
+ # The container to_visit has been emptied.
+ pass
+
+ # We have the stick back the pending_children list into the
+ # task master because the python 1.5.2 compatibility does not
+ # allow us to use in-place updates
+ self.pending_children = pending_children
+
def stop(self):
"""
Stops the current build completely.
@@ -774,6 +790,8 @@ class Taskmaster:
if cycle:
desc = desc + " " + string.join(map(str, cycle), " -> ") + "\n"
else:
- desc = desc + " Internal Error: no cycle found for node %s (%s)\n" % \
- (node, repr(node))
+ desc = desc + \
+ " Internal Error: no cycle found for node %s (%s) in state %s\n" % \
+ (node, repr(node), StateString[node.get_state()])
+
raise SCons.Errors.UserError, desc
diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py
index 88d3078..9324581 100644
--- a/src/engine/SCons/TaskmasterTests.py
+++ b/src/engine/SCons/TaskmasterTests.py
@@ -1053,23 +1053,24 @@ class TaskmasterTestCase(unittest.TestCase):
expect = """\
Taskmaster: Looking for a node to evaluate
-Taskmaster: Considering node <no_state 'n1'> and its children:
-Taskmaster: Evaluating <pending 'n1'>
+Taskmaster: Considering node <no_state 0 'n1'> and its children:
+Taskmaster: Evaluating <pending 0 'n1'>
Taskmaster: Looking for a node to evaluate
-Taskmaster: Considering node <executed 'n1'> and its children:
+Taskmaster: Considering node <executed 0 'n1'> and its children:
Taskmaster: already handled (executed)
-Taskmaster: Considering node <no_state 'n3'> and its children:
-Taskmaster: <executed 'n1'>
-Taskmaster: <no_state 'n2'>
-Taskmaster: Considering node <no_state 'n2'> and its children:
-Taskmaster: Evaluating <pending 'n2'>
+Taskmaster: Considering node <no_state 0 'n3'> and its children:
+Taskmaster: <executed 0 'n1'>
+Taskmaster: <no_state 0 'n2'>
+Taskmaster: adjusting ref count: <pending 1 'n3'>
+Taskmaster: Considering node <no_state 0 'n2'> and its children:
+Taskmaster: Evaluating <pending 0 'n2'>
Taskmaster: Looking for a node to evaluate
-Taskmaster: Considering node <pending 'n3'> and its children:
-Taskmaster: <executed 'n1'>
-Taskmaster: <executed 'n2'>
-Taskmaster: Evaluating <pending 'n3'>
+Taskmaster: Considering node <pending 0 'n3'> and its children:
+Taskmaster: <executed 0 'n1'>
+Taskmaster: <executed 0 'n2'>
+Taskmaster: Evaluating <pending 0 'n3'>
Taskmaster: Looking for a node to evaluate
Taskmaster: No candidate anymore.
diff --git a/src/engine/SCons/Tool/FortranCommon.py b/src/engine/SCons/Tool/FortranCommon.py
index 82a5a6c..825cbe5 100644
--- a/src/engine/SCons/Tool/FortranCommon.py
+++ b/src/engine/SCons/Tool/FortranCommon.py
@@ -183,7 +183,7 @@ def add_fortran_to_env(env):
env['FORTRANMODDIR'] = '' # where the compiler should place .mod files
env['FORTRANMODDIRPREFIX'] = '' # some prefix to $FORTRANMODDIR - similar to $INCPREFIX
env['FORTRANMODDIRSUFFIX'] = '' # some suffix to $FORTRANMODDIR - similar to $INCSUFFIX
- env['_FORTRANMODFLAG'] = '$( ${_concat(FORTRANMODDIRPREFIX, FORTRANMODDIR, FORTRANMODDIRSUFFIX, __env__, RDirs)} $)'
+ env['_FORTRANMODFLAG'] = '$( ${_concat(FORTRANMODDIRPREFIX, FORTRANMODDIR, FORTRANMODDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
def add_f77_to_env(env):
"""Add Builders and construction variables for f77 to an Environment."""
diff --git a/src/engine/SCons/Tool/c++.py b/src/engine/SCons/Tool/c++.py
index a4375c0..f360ed8 100644
--- a/src/engine/SCons/Tool/c++.py
+++ b/src/engine/SCons/Tool/c++.py
@@ -76,7 +76,7 @@ def generate(env):
env['CXXFLAGS'] = SCons.Util.CLVar('')
env['CXXCOM'] = '$CXX -o $TARGET -c $CXXFLAGS $CCFLAGS $_CCCOMCOM $SOURCES'
env['SHCXX'] = '$CXX'
- env['SHCXXFLAGS'] = SCons.Util.CLVar('')
+ env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
env['SHCXXCOM'] = '$SHCXX -o $TARGET -c $SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM $SOURCES'
env['CPPDEFPREFIX'] = '-D'
diff --git a/src/engine/SCons/Tool/g++.py b/src/engine/SCons/Tool/g++.py
index 9c7e477..917229f 100644
--- a/src/engine/SCons/Tool/g++.py
+++ b/src/engine/SCons/Tool/g++.py
@@ -53,26 +53,14 @@ def generate(env):
env['CXX'] = env.Detect(compilers)
# platform specific settings
- if env['PLATFORM'] == 'cygwin':
- env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
- elif env['PLATFORM'] == 'aix':
- # Original line from Christian Engel added -DPIC:
- #env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -DPIC -mminimal-toc')
+ if env['PLATFORM'] == 'aix':
env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -mminimal-toc')
env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
env['SHOBJSUFFIX'] = '$OBJSUFFIX'
elif env['PLATFORM'] == 'hpux':
- # Original line from Christian Engel added -DPIC:
- #env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -DPIC')
env['SHOBJSUFFIX'] = '.pic.o'
elif env['PLATFORM'] == 'sunos':
- # Original line from Christian Engel added -DPIC:
- #env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -DPIC')
env['SHOBJSUFFIX'] = '.pic.o'
- else:
- # Original line from Christian Engel added -DPIC:
- #env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -DPIC')
- pass
# determine compiler version
if env['CXX']:
line = os.popen(env['CXX'] + ' --version').readline()
diff --git a/src/setup.py b/src/setup.py
index 281a69c..5b2212c 100644
--- a/src/setup.py
+++ b/src/setup.py
@@ -376,6 +376,7 @@ arguments = {
'packages' : ["SCons",
"SCons.compat",
"SCons.Node",
+ "SCons.Options",
"SCons.Platform",
"SCons.Scanner",
"SCons.Script",