diff options
author | Steven Knight <knight@baldmt.com> | 2008-04-30 05:39:46 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2008-04-30 05:39:46 (GMT) |
commit | 889dc735eb173180dd92b0263bf5dbe697129881 (patch) | |
tree | f3178f3f085f178e22d840046acc862e23422870 /src | |
parent | d9cca1c6bba7446bc13d90daa949fce4b364da7f (diff) | |
download | SCons-889dc735eb173180dd92b0263bf5dbe697129881.zip SCons-889dc735eb173180dd92b0263bf5dbe697129881.tar.gz SCons-889dc735eb173180dd92b0263bf5dbe697129881.tar.bz2 |
Merged revisions 2898-2901,2903-2927 via svnmerge from
http://scons.tigris.org/svn/scons/branches/core
........
r2903 | stevenknight | 2008-04-22 08:23:52 -0700 (Tue, 22 Apr 2008) | 3 lines
Issue 2019: don't blow up when a "dictionary" source_scanner doesn't
have a more-specific scanner entry for a specified source file's suffix.
........
r2904 | stevenknight | 2008-04-23 11:13:19 -0700 (Wed, 23 Apr 2008) | 3 lines
Fix regression in use of $CXXFLAGS by the default $SHCXXFLAGS setting.
(Greg Noel)
........
r2905 | stevenknight | 2008-04-23 11:23:12 -0700 (Wed, 23 Apr 2008) | 3 lines
Update the test/CXX/SHCXXFLAGS.py with some more modern idioms copied
from test/CXX/CXXFLAGS.py.
........
r2921 | belley | 2008-04-28 08:52:13 -0700 (Mon, 28 Apr 2008) | 98 lines
Candidate list must be flushed when stopping the taskmaster.
============================================================
The taskmaster's candidate list must be flushed when the taskmaster is stopped,
either because of a build error or a keyboard interrupt. This involves failing
each candidates along with their waiting parents. This is necessary because the
waiting parents might be in the pending_children set() that is used by the
taskmaster to determine if cycles exist in the dependency graph. Failure to do
so leads to confusing error messages such as:
scons: *** Found dependency cycle(s):
Internal Error: no cycle found for node
/bld/vmkernel-main/scons/build/vmodl/obj/generic/Vmodl/Vmomi/DynamicProperty.h
(<SCons.Node.FS.File instance at 0x95d230c>)
Internal Error: no cycle found for node
/bld/vmkernel-main/scons/build/vmodl/obj/generic/Vmodl/Vmomi/Fault/NotSupported.h
(<SCons.Node.FS.File instance at 0x960634c>)
Internal Error: no cycle found for node
/bld/vmkernel-main/scons/build/vmodl/obj/generic/Vmodl/Vmomi/Fault/InvalidRequest.h
(<SCons.Node.FS.File instance at 0x95d2bac>)
Internal Error: no cycle found for node
/bld/vmkernel-main/scons/build/vmodl/obj/generic/Vmodl/Vmomi/Fault/RequestCanceled.h
(<SCons.Node.FS.File instance at 0x960648c>)
Internal Error: no cycle found for node
/bld/vmkernel-main/scons/build/vmodl/obj/generic/Vmodl/Vmomi/Fault/InvalidType.h
(<SCons.Node.FS.File instance at 0x95d2cec>)
Internal Error: no cycle found for node
/bld/vmkernel-main/scons/build/vmodl/obj/generic/Vmodl/Vmomi/Core/InvalidProperty.h
(<SCons.Node.FS.File instance at 0x9606d2c>)
Internal Error: no cycle found for node
/bld/vmkernel-main/scons/build/vmodl/obj/generic/Vmodl/Vmomi/Fault/SecurityError.h
(<SCons.Node.FS.File instance at 0x96065cc>)
Internal Error: no cycle found for node
/bld/vmkernel-main/scons/build/vmodl/obj/generic/Vmodl/Vmomi/Core/PropertyCollector.h
(<SCons.Node.FS.File instance at 0x9606e6c>)
Internal Error: no cycle found for node
/bld/vmkernel-main/scons/build/vmodl/obj/generic/Vmodl/Vmomi/Fault/InvalidArgument.h
(<SCons.Node.FS.File instance at 0x95d2a6c>)
Internal Error: no cycle found for node
/bld/vmkernel-main/scons/build/vmodl/obj/generic/Vmodl/Vmomi/DynamicData.h
(<SCons.Node.FS.File instance at 0x95d21cc>)
Changes made:
Job.py:
------
o Implemented an InterruptState object that allows the sharing of the
interrupt state between the Jobs, the Serial/Parallel and the Worker
thread object. This allows for somewhat faster interruption when
Ctrl-C is pressed because the Worker thread will not start any new
task, i.e. the ones siting in the request queue.
Taskmaster.py:
--------------
o Moved the code contained the function Task.fail_continue() to the
function Taskmaster.will_not_build(). This function perform the
clean-up for nodes that will never be built. This includes failing
these nodes along with their waiting parents and removing them from
the list of pending children.
o Improved the taskmaster tracing so that the pending children ref
counts of nodes is also printed.
o When stopping the taskmaster, no_next_candidate() now calls
will_not_build() repetitively to make sure that all candidate nodes
that will never be build are properly cleaned-up.
test/Parallel/multiple-parents.py
---------------------------------
Improved the test to also exercise the following functionality:
o Nodes with multiple targets (not just aliases as it was before).
o SideEffect()
o Interrupting the build.
Submitted against changeset 2920.
All tests pass with both Python 2.5.1 and 1.5.2
Benoit
........
r2922 | stevenknight | 2008-04-28 11:50:10 -0700 (Mon, 28 Apr 2008) | 26 lines
Issue 2024: http://scons.tigris.org/issues/show_bug.cgi?id=2024
Some public packages were importing specific SCons.Options.*Option
submodules directly, instead of using the SCons.Options package
itself (which actually exposed all the SCons.Options.*Option variable
names directly, but what they hey). Our scripts didn't test for
direct importing of the submodules, so this broke when I implemented
backwards comptability with a SCons/Options.py module, instead of a full
SCons/Options/*.py package.
This restores the SCons/Options/*.py package files with stub modules that
provide backwards compatibility (by referring to the new SCons.Variables
functions and classes) and allow for importing all of
The test/Deprecated/Options/*Option.py scripts have had specific submodule
imports added. To make sure this corresponding "feature" continues to
work in the future, I'll be following this with another checkin that
adds submodule imports for the SCons.Variables.*Variable modules.
I ran this with the SCons/Options.py file in place, and also with
a compiled SCons/Options.pyc file in place, to try to make sure it
works regardless. We've seen issues on Debian where their packaging
doesn't clean up old *.pyc files when a Python *.py module is removed.
It looks like this should work regardless of whether the Options.pyc
file is there or not.
........
r2923 | stevenknight | 2008-04-28 11:52:52 -0700 (Mon, 28 Apr 2008) | 3 lines
Update the test/Variables/*Variable.py scripts to verify that importing
SCons.Variables.*Variable submodules continues to work in the future.
........
r2924 | belley | 2008-04-28 14:06:54 -0700 (Mon, 28 Apr 2008) | 6 lines
Fixed a test that my morning change broke. The taskmaster tracing now
includes the pending children ref count.
Benoit
........
r2925 | stevenknight | 2008-04-28 18:00:25 -0700 (Mon, 28 Apr 2008) | 4 lines
Issue 2028: Make sure already-existing Entry Nodes that we find
are converted to Dir Nodes when searching a *PATH list for implicit
dependencies.
........
r2926 | stevenknight | 2008-04-29 08:11:40 -0700 (Tue, 29 Apr 2008) | 3 lines
Issue 2034: Fix $FORTRANMODDIR values like ${TARGET.dir} in the
default $_FORTANMODFLAG expansion. (Stefano)
........
r2927 | stevenknight | 2008-04-29 11:34:02 -0700 (Tue, 29 Apr 2008) | 3 lines
Restore the SCons.Options package (maintains backwards compatibility of
importing submodules) to setup.py.
........
Diffstat (limited to 'src')
-rw-r--r-- | src/CHANGES.txt | 24 | ||||
-rw-r--r-- | src/engine/MANIFEST.in | 7 | ||||
-rw-r--r-- | src/engine/SCons/Executor.py | 8 | ||||
-rw-r--r-- | src/engine/SCons/Job.py | 38 | ||||
-rw-r--r-- | src/engine/SCons/Node/FS.py | 14 | ||||
-rw-r--r-- | src/engine/SCons/Options/BoolOption.py | 35 | ||||
-rw-r--r-- | src/engine/SCons/Options/EnumOption.py | 35 | ||||
-rw-r--r-- | src/engine/SCons/Options/ListOption.py | 35 | ||||
-rw-r--r-- | src/engine/SCons/Options/PackageOption.py | 35 | ||||
-rw-r--r-- | src/engine/SCons/Options/PathOption.py | 35 | ||||
-rw-r--r-- | src/engine/SCons/Options/__init__.py (renamed from src/engine/SCons/Options.py) | 12 | ||||
-rw-r--r-- | src/engine/SCons/Taskmaster.py | 120 | ||||
-rw-r--r-- | src/engine/SCons/TaskmasterTests.py | 25 | ||||
-rw-r--r-- | src/engine/SCons/Tool/FortranCommon.py | 2 | ||||
-rw-r--r-- | src/engine/SCons/Tool/c++.py | 2 | ||||
-rw-r--r-- | src/engine/SCons/Tool/g++.py | 14 | ||||
-rw-r--r-- | src/setup.py | 1 |
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", |