diff options
35 files changed, 1020 insertions, 218 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", diff --git a/test/CXX/CXXFLAGS.py b/test/CXX/CXXFLAGS.py new file mode 100644 index 0000000..86f14f0 --- /dev/null +++ b/test/CXX/CXXFLAGS.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that $CXXFLAGS settings are used to build both static +and shared object files. +""" + +import os +import string +import sys + +import TestSCons + +_obj = TestSCons._obj + +if os.name == 'posix': + os.environ['LD_LIBRARY_PATH'] = '.' +if string.find(sys.platform, 'irix') > -1: + os.environ['LD_LIBRARYN32_PATH'] = '.' + +test = TestSCons.TestSCons() + +e = test.Environment() + +test.write('SConstruct', """ +foo = Environment(WINDOWS_INSERT_DEF=1) +foo.Append(CXXFLAGS = '-DFOO') +bar = Environment(WINDOWS_INSERT_DEF=1) +bar.Append(CXXFLAGS = '-DBAR') +foo_obj = foo.SharedObject(target = 'fooshared%(_obj)s', source = 'doIt.cpp') +bar_obj = bar.SharedObject(target = 'barshared%(_obj)s', source = 'doIt.cpp') +foo.SharedLibrary(target = 'foo', source = foo_obj) +bar.SharedLibrary(target = 'bar', source = bar_obj) + +fooMain = foo.Clone(LIBS='foo', LIBPATH='.') +foo_obj = fooMain.Object(target='foomain', source='main.c') +fooMain.Program(target='fooprog', source=foo_obj) + +barMain = bar.Clone(LIBS='bar', LIBPATH='.') +bar_obj = barMain.Object(target='barmain', source='main.c') +barMain.Program(target='barprog', source=bar_obj) + +foo_obj = foo.Object(target = 'foostatic', source = 'prog.cpp') +bar_obj = bar.Object(target = 'barstatic', source = 'prog.cpp') +foo.Program(target = 'foo', source = foo_obj) +bar.Program(target = 'bar', source = bar_obj) +""" % locals()) + +test.write('foo.def', r""" +LIBRARY "foo" +DESCRIPTION "Foo Shared Library" + +EXPORTS + doIt +""") + +test.write('bar.def', r""" +LIBRARY "bar" +DESCRIPTION "Bar Shared Library" + +EXPORTS + doIt +""") + +test.write('doIt.cpp', r""" +#include <stdio.h> + +extern "C" void +doIt() +{ +#ifdef FOO + printf("doIt.cpp: FOO\n"); +#endif +#ifdef BAR + printf("doIt.cpp: BAR\n"); +#endif +} +""") + +test.write('main.c', r""" + +void doIt(); + +int +main(int argc, char* argv[]) +{ + doIt(); + return 0; +} +""") + +test.write('prog.cpp', r""" +#include <stdio.h> +#include <stdlib.h> + +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; +#ifdef FOO + printf("prog.c: FOO\n"); +#endif +#ifdef BAR + printf("prog.c: BAR\n"); +#endif + exit (0); +} +""") + +test.run(arguments = '.') + +test.run(program = test.workpath('fooprog'), stdout = "doIt.cpp: FOO\n") +test.run(program = test.workpath('barprog'), stdout = "doIt.cpp: BAR\n") +test.run(program = test.workpath('foo'), stdout = "prog.c: FOO\n") +test.run(program = test.workpath('bar'), stdout = "prog.c: BAR\n") + + + +test.write('SConstruct', """ +bar = Environment(WINDOWS_INSERT_DEF=1) +bar.Append(CXXFLAGS = '-DBAR') +foo_obj = bar.SharedObject(target = 'foo%(_obj)s', source = 'doIt.cpp') +bar_obj = bar.SharedObject(target = 'bar%(_obj)s', source = 'doIt.cpp') +bar.SharedLibrary(target = 'foo', source = foo_obj) +bar.SharedLibrary(target = 'bar', source = bar_obj) + +barMain = bar.Clone(LIBS='bar', LIBPATH='.') +foo_obj = barMain.Object(target='foomain', source='main.c') +bar_obj = barMain.Object(target='barmain', source='main.c') +barMain.Program(target='barprog', source=foo_obj) +barMain.Program(target='fooprog', source=bar_obj) +""" % locals()) + +test.run(arguments = '.') + +test.run(program = test.workpath('fooprog'), stdout = "doIt.cpp: BAR\n") +test.run(program = test.workpath('barprog'), stdout = "doIt.cpp: BAR\n") + + + +test.pass_test() diff --git a/test/CXX/SHCXXFLAGS.py b/test/CXX/SHCXXFLAGS.py index bfe1a79..0ce2b15 100644 --- a/test/CXX/SHCXXFLAGS.py +++ b/test/CXX/SHCXXFLAGS.py @@ -24,10 +24,15 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import sys -import TestSCons +""" +Verify that $SHCXXFLAGS settings are used to build shared object files. +""" + import os import string +import sys + +import TestSCons _obj = TestSCons._obj @@ -39,16 +44,16 @@ if string.find(sys.platform, 'irix') > -1: test = TestSCons.TestSCons() e = test.Environment() -fooflags = e['SHCXXFLAGS'] + ' -DFOO' -barflags = e['SHCXXFLAGS'] + ' -DBAR' test.write('SConstruct', """ -foo = Environment(SHCXXFLAGS = '%s', WINDOWS_INSERT_DEF=1) -bar = Environment(SHCXXFLAGS = '%s', WINDOWS_INSERT_DEF=1) -foo.SharedObject(target = 'foo%s', source = 'prog.cpp') -bar.SharedObject(target = 'bar%s', source = 'prog.cpp') -foo.SharedLibrary(target = 'foo', source = 'foo%s') -bar.SharedLibrary(target = 'bar', source = 'bar%s') +foo = Environment(WINDOWS_INSERT_DEF=1) +foo.Append(SHCXXFLAGS = '-DFOO') +bar = Environment(WINDOWS_INSERT_DEF=1) +bar.Append(SHCXXFLAGS = '-DBAR') +foo_obj = foo.SharedObject(target = 'foo%(_obj)s', source = 'prog.cpp') +bar_obj = bar.SharedObject(target = 'bar%(_obj)s', source = 'prog.cpp') +foo.SharedLibrary(target = 'foo', source = foo_obj) +bar.SharedLibrary(target = 'bar', source = bar_obj) fooMain = foo.Clone(LIBS='foo', LIBPATH='.') foo_obj = fooMain.Object(target='foomain', source='main.c') @@ -57,7 +62,7 @@ fooMain.Program(target='fooprog', source=foo_obj) barMain = bar.Clone(LIBS='bar', LIBPATH='.') bar_obj = barMain.Object(target='barmain', source='main.c') barMain.Program(target='barprog', source=bar_obj) -""" % (fooflags, barflags, _obj, _obj, _obj, _obj)) +""" % locals()) test.write('foo.def', r""" LIBRARY "foo" @@ -108,18 +113,19 @@ test.run(program = test.workpath('fooprog'), stdout = "prog.cpp: FOO\n") test.run(program = test.workpath('barprog'), stdout = "prog.cpp: BAR\n") test.write('SConstruct', """ -bar = Environment(SHCXXFLAGS = '%s', WINDOWS_INSERT_DEF=1) -bar.SharedObject(target = 'foo%s', source = 'prog.cpp') -bar.SharedObject(target = 'bar%s', source = 'prog.cpp') -bar.SharedLibrary(target = 'foo', source = 'foo%s') -bar.SharedLibrary(target = 'bar', source = 'bar%s') +bar = Environment(WINDOWS_INSERT_DEF=1) +bar.Append(SHCXXFLAGS = '-DBAR') +foo_obj = bar.SharedObject(target = 'foo%(_obj)s', source = 'prog.cpp') +bar_obj = bar.SharedObject(target = 'bar%(_obj)s', source = 'prog.cpp') +bar.SharedLibrary(target = 'foo', source = foo_obj) +bar.SharedLibrary(target = 'bar', source = bar_obj) barMain = bar.Clone(LIBS='bar', LIBPATH='.') foo_obj = barMain.Object(target='foomain', source='main.c') bar_obj = barMain.Object(target='barmain', source='main.c') barMain.Program(target='barprog', source=foo_obj) barMain.Program(target='fooprog', source=bar_obj) -""" % (barflags, _obj, _obj, _obj, _obj)) +""" % locals()) test.run(arguments = '.') diff --git a/test/Deprecated/Options/BoolOption.py b/test/Deprecated/Options/BoolOption.py index 38b30d5..d45ad1b 100644 --- a/test/Deprecated/Options/BoolOption.py +++ b/test/Deprecated/Options/BoolOption.py @@ -50,12 +50,15 @@ def check(expect): test.write(SConstruct_path, """\ +from SCons.Options.BoolOption import BoolOption +BO = BoolOption + from SCons.Options import BoolOption opts = Options(args=ARGUMENTS) opts.AddOptions( BoolOption('warnings', 'compilation with -Wall and similiar', 1), - BoolOption('profile', 'create profiling informations', 0), + BO('profile', 'create profiling informations', 0), ) env = Environment(options=opts) @@ -78,7 +81,7 @@ check([str(False), str(True)]) expect_stderr = """ scons: *** Error converting option: warnings Invalid value for boolean option: irgendwas -""" + test.python_file_line(SConstruct_path, 9) +""" + test.python_file_line(SConstruct_path, 12) test.run(arguments='warnings=irgendwas', stderr = expect_stderr, status=2) diff --git a/test/Deprecated/Options/EnumOption.py b/test/Deprecated/Options/EnumOption.py index 610a485..29724f3 100644 --- a/test/Deprecated/Options/EnumOption.py +++ b/test/Deprecated/Options/EnumOption.py @@ -44,6 +44,9 @@ def check(expect): test.write(SConstruct_path, """\ +from SCons.Options.EnumOption import EnumOption +EO = EnumOption + from SCons.Options import EnumOption list_of_libs = Split('x11 gl qt ical') @@ -56,9 +59,9 @@ opts.AddOptions( EnumOption('guilib', 'gui lib to use', 'gtk', allowed_values=('motif', 'gtk', 'kde'), map={}, ignorecase=1), # case insensitive - EnumOption('some', 'some option', 'xaver', - allowed_values=('xaver', 'eins'), - map={}, ignorecase=2), # make lowercase + EO('some', 'some option', 'xaver', + allowed_values=('xaver', 'eins'), + map={}, ignorecase=2), # make lowercase ) env = Environment(options=opts) @@ -82,19 +85,19 @@ check(['full', 'KdE', 'eins']) expect_stderr = """ scons: *** Invalid value for option debug: FULL -""" + test.python_file_line(SConstruct_path, 18) +""" + test.python_file_line(SConstruct_path, 21) test.run(arguments='debug=FULL', stderr=expect_stderr, status=2) expect_stderr = """ scons: *** Invalid value for option guilib: irgendwas -""" + test.python_file_line(SConstruct_path, 18) +""" + test.python_file_line(SConstruct_path, 21) test.run(arguments='guilib=IrGeNdwas', stderr=expect_stderr, status=2) expect_stderr = """ scons: *** Invalid value for option some: irgendwas -""" + test.python_file_line(SConstruct_path, 18) +""" + test.python_file_line(SConstruct_path, 21) test.run(arguments='some=IrGeNdwas', stderr=expect_stderr, status=2) diff --git a/test/Deprecated/Options/ListOption.py b/test/Deprecated/Options/ListOption.py index 1ce20a2..7e7b18f 100644 --- a/test/Deprecated/Options/ListOption.py +++ b/test/Deprecated/Options/ListOption.py @@ -47,6 +47,9 @@ def check(expect): test.write(SConstruct_path, """\ +from SCons.Options.ListOption import ListOption +LO = ListOption + from SCons.Options import ListOption list_of_libs = Split('x11 gl qt ical') @@ -59,6 +62,7 @@ opts.AddOptions( 'all', names = list_of_libs, map = {'GL':'gl', 'QT':'qt'}), + LO('listvariable', 'listvariable help', 'all', names=['l1', 'l2', 'l3']) ) env = Environment(options=opts) @@ -81,7 +85,8 @@ test.run() check(['all', '1', 'gl ical qt x11', 'gl ical qt x11', "['gl ical qt x11']"]) -test.must_match(test.workpath('scons.options'), "shared = 'all'"+os.linesep) +expect = "shared = 'all'"+os.linesep+"listvariable = 'all'"+os.linesep +test.must_match(test.workpath('scons.options'), expect) check(['all', '1', 'gl ical qt x11', 'gl ical qt x11', "['gl ical qt x11']"]) @@ -110,7 +115,7 @@ check(['gl,qt', '0', 'gl qt', 'gl qt', "['gl qt']"]) expect_stderr = """ scons: *** Error converting option: shared Invalid value(s) for option: foo -""" + test.python_file_line(SConstruct_path, 15) +""" + test.python_file_line(SConstruct_path, 19) test.run(arguments='shared=foo', stderr=expect_stderr, status=2) @@ -119,28 +124,28 @@ test.run(arguments='shared=foo', stderr=expect_stderr, status=2) expect_stderr = """ scons: *** Error converting option: shared Invalid value(s) for option: foo -""" + test.python_file_line(SConstruct_path, 15) +""" + test.python_file_line(SConstruct_path, 19) test.run(arguments='shared=foo,ical', stderr=expect_stderr, status=2) expect_stderr = """ scons: *** Error converting option: shared Invalid value(s) for option: foo -""" + test.python_file_line(SConstruct_path, 15) +""" + test.python_file_line(SConstruct_path, 19) test.run(arguments='shared=ical,foo', stderr=expect_stderr, status=2) expect_stderr = """ scons: *** Error converting option: shared Invalid value(s) for option: foo -""" + test.python_file_line(SConstruct_path, 15) +""" + test.python_file_line(SConstruct_path, 19) test.run(arguments='shared=ical,foo,x11', stderr=expect_stderr, status=2) expect_stderr = """ scons: *** Error converting option: shared Invalid value(s) for option: foo,bar -""" + test.python_file_line(SConstruct_path, 15) +""" + test.python_file_line(SConstruct_path, 19) test.run(arguments='shared=foo,x11,,,bar', stderr=expect_stderr, status=2) diff --git a/test/Deprecated/Options/PackageOption.py b/test/Deprecated/Options/PackageOption.py index 79d4dda..b7dbc71 100644 --- a/test/Deprecated/Options/PackageOption.py +++ b/test/Deprecated/Options/PackageOption.py @@ -50,6 +50,9 @@ def check(expect): test.write(SConstruct_path, """\ +from SCons.Options.PackageOption import PackageOption +PO = PackageOption + from SCons.Options import PackageOption opts = Options(args=ARGUMENTS) @@ -57,6 +60,7 @@ opts.AddOptions( PackageOption('x11', 'use X11 installed here (yes = search some places', 'yes'), + PO('package', 'help for package', 'yes'), ) env = Environment(options=opts) @@ -80,7 +84,7 @@ check([test.workpath()]) expect_stderr = """ scons: *** Path does not exist for option x11: /non/existing/path/ -""" + test.python_file_line(SConstruct_path, 10) +""" + test.python_file_line(SConstruct_path, 14) test.run(arguments='x11=/non/existing/path/', stderr=expect_stderr, status=2) diff --git a/test/Deprecated/Options/PathOption.py b/test/Deprecated/Options/PathOption.py index 23fec6e..3fa7e81 100644 --- a/test/Deprecated/Options/PathOption.py +++ b/test/Deprecated/Options/PathOption.py @@ -49,6 +49,9 @@ workpath = test.workpath() libpath = os.path.join(workpath, 'lib') test.write(SConstruct_path, """\ +from SCons.Options.PathOption import PathOption +PO = PathOption + from SCons.Options import PathOption qtdir = r'%s' @@ -56,7 +59,7 @@ qtdir = r'%s' opts = Options(args=ARGUMENTS) opts.AddOptions( PathOption('qtdir', 'where the root of Qt is installed', qtdir), - PathOption('qt_libraries', 'where the Qt library is installed', r'%s'), + PO('qt_libraries', 'where the Qt library is installed', r'%s'), ) env = Environment(options=opts) @@ -90,7 +93,7 @@ test.run(arguments=['qtdir=%s' % qtpath, 'qt_libraries=%s' % libpath]) check([qtpath, libpath, libpath]) qtpath = os.path.join(workpath, 'non', 'existing', 'path') -SConstruct_file_line = test.python_file_line(test.workpath('SConstruct'), 11)[:-1] +SConstruct_file_line = test.python_file_line(test.workpath('SConstruct'), 14)[:-1] expect_stderr = """ scons: *** Path for option qtdir does not exist: %(qtpath)s diff --git a/test/Fortran/FORTRANMODDIR.py b/test/Fortran/FORTRANMODDIR.py index a81439a..c0e158d 100644 --- a/test/Fortran/FORTRANMODDIR.py +++ b/test/Fortran/FORTRANMODDIR.py @@ -54,7 +54,10 @@ test.write('SConstruct', """ env = Environment(FORTRANCOM = r'%(_python_)s myfortran.py $FORTRANMODDIR $SOURCE $TARGET', FORTRANMODDIR = 'modules') env.Object(target = 'test1.obj', source = 'test1.f') -env.Object(target = 'sub/test2.obj', source = 'test1.f', +env.Object(target = 'sub2/test2.obj', source = 'test1.f', + FORTRANMODDIR='${TARGET.dir}') +env.Object(target = 'sub3/test3.obj', source = 'test1.f', + FORTRANCOM = r'%(_python_)s myfortran.py $_FORTRANMODFLAG $SOURCE $TARGET', FORTRANMODDIR='${TARGET.dir}') """ % locals()) @@ -88,8 +91,11 @@ test.must_match('test1.obj', "myfortran.py wrote test1.obj\n") test.must_match(['modules', 'mod_foo.mod'], "myfortran.py wrote mod_foo.mod\n") test.must_not_exist(['modules', 'mod_bar.mod']) -test.must_match(['sub', 'test2.obj'], "myfortran.py wrote test2.obj\n") -test.must_match(['sub', 'mod_foo.mod'], "myfortran.py wrote mod_foo.mod\n") +test.must_match(['sub2', 'test2.obj'], "myfortran.py wrote test2.obj\n") +test.must_match(['sub2', 'mod_foo.mod'], "myfortran.py wrote mod_foo.mod\n") + +test.must_match(['sub3', 'test3.obj'], "myfortran.py wrote test3.obj\n") +test.must_match(['sub3', 'mod_foo.mod'], "myfortran.py wrote mod_foo.mod\n") test.up_to_date(arguments = '.') diff --git a/test/Interactive/taskmastertrace.py b/test/Interactive/taskmastertrace.py index f0ff81f..e78bdfa 100644 --- a/test/Interactive/taskmastertrace.py +++ b/test/Interactive/taskmastertrace.py @@ -56,6 +56,8 @@ test.write('foo.in', "foo.in 2\n") scons.send("build --taskmastertrace=- foo.out\n") +test.wait_for(test.workpath('foo.out')) + scons.send("build 2\n") test.wait_for(test.workpath('2')) @@ -71,15 +73,16 @@ scons>>> Copy("foo.out", "foo.in") Touch("1") scons>>> Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node <no_state 'foo.out'> and its children: -Taskmaster: <no_state 'foo.in'> -Taskmaster: Considering node <no_state 'foo.in'> and its children: -Taskmaster: Evaluating <pending 'foo.in'> +Taskmaster: Considering node <no_state 0 'foo.out'> and its children: +Taskmaster: <no_state 0 'foo.in'> +Taskmaster: adjusting ref count: <pending 1 'foo.out'> +Taskmaster: Considering node <no_state 0 'foo.in'> and its children: +Taskmaster: Evaluating <pending 0 'foo.in'> Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node <pending 'foo.out'> and its children: -Taskmaster: <up_to_date 'foo.in'> -Taskmaster: Evaluating <pending 'foo.out'> +Taskmaster: Considering node <pending 0 'foo.out'> and its children: +Taskmaster: <up_to_date 0 'foo.in'> +Taskmaster: Evaluating <pending 0 'foo.out'> Copy("foo.out", "foo.in") Taskmaster: Looking for a node to evaluate diff --git a/test/Parallel/multiple-parents.py b/test/Parallel/multiple-parents.py index f81adf5..d9c414f 100644 --- a/test/Parallel/multiple-parents.py +++ b/test/Parallel/multiple-parents.py @@ -50,34 +50,69 @@ test = TestSCons.TestSCons() # c) Some targets succeed building # d) Some children are ignored # e) Some children are pre-requesites -# f) Some sources are missing +# f) Some children have side-effects +# g) Some sources are missing +# h) Builds that are interrupted test.write('SConstruct', """ +opts = Options() +opts.Add( BoolOption('interrupt', 'Interrupt the build.', 0 ) ) +optEnv = Environment(options=opts) + def fail_action(target = None, source = None, env = None): return 2 +def simulate_keyboard_interrupt(target = None, source = None, env = None): + # Directly invoked the SIGINT handler to simulate a + # KeyboardInterrupt. This hack is necessary because there is no + # easy way to get access to the current Job/Taskmaster object. + import signal + handler = signal.getsignal(signal.SIGINT) + handler(signal.SIGINT, None) + return 0 + +interrupt = Command(target='interrupt', source='', action=simulate_keyboard_interrupt) + + failed0 = Command(target='failed00', source='', action=fail_action) -ok0 = Command(target='ok00', source='', action=Touch('${TARGET}')) +ok0 = Command(target=['ok00a', 'ok00b', 'ok00c'], + source='', + action=[Touch('${TARGETS[0]}'), Touch('${TARGETS[1]}'), Touch('${TARGETS[2]}')]) prereq0 = Command(target='prereq00', source='', action=Touch('${TARGET}')) ignore0 = Command(target='ignore00', source='', action=Touch('${TARGET}')) igreq0 = Command(target='igreq00', source='', action=Touch('${TARGET}')) missing0 = Command(target='missing00', source='MissingSrc', action=Touch('${TARGET}')) +withSE0 = Command(target=['withSE00a', 'withSE00b', 'withSE00c'], + source='', + action=[Touch('${TARGETS[0]}'), Touch('${TARGETS[1]}'), Touch('${TARGETS[2]}'), + Touch('side_effect')]) +SideEffect('side_effect', withSE0) -prev_level = failed0 + ok0 + ignore0 +prev_level = failed0 + ok0 + ignore0 + missing0 + withSE0 prev_prereq = prereq0 prev_ignore = ignore0 prev_igreq = igreq0 +if optEnv['interrupt']: + prev_level = prev_level + interrupt + for i in range(1,20): failed = Command(target='failed%02d' % i, source='', action=fail_action) - ok = Command(target='ok%02d' % i, source='', action=Touch('${TARGET}')) + ok = Command(target=['ok%02da' % i, 'ok%02db' % i, 'ok%02dc' % i], + source='', + action=[Touch('${TARGETS[0]}'), Touch('${TARGETS[1]}'), Touch('${TARGETS[2]}')]) prereq = Command(target='prereq%02d' % i, source='', action=Touch('${TARGET}')) ignore = Command(target='ignore%02d' % i, source='', action=Touch('${TARGET}')) igreq = Command(target='igreq%02d' % i, source='', action=Touch('${TARGET}')) missing = Command(target='missing%02d' %i, source='MissingSrc', action=Touch('${TARGET}')) + withSE = Command(target=['withSE%02da' % i, 'withSE%02db' % i, 'withSE%02dc' % i], + source='', + action=[Touch('${TARGETS[0]}'), Touch('${TARGETS[1]}'), Touch('${TARGETS[2]}'), + Touch('side_effect')]) + SideEffect('side_effect', withSE) - next_level = failed + ok + ignore + igreq + missing + next_level = failed + ok + ignore + igreq + missing + withSE for j in range(1,10): a = Alias('a%02d%02d' % (i,j), prev_level) @@ -108,7 +143,8 @@ Default(all) re_error = """\ (scons: \\*\\*\\* \\[failed\\d+] Error 2\\n)|\ -(scons: \\*\\*\\* Source `MissingSrc' not found, needed by target `missing\\d+'\\.( Stop\\.)?\\n)\ +(scons: \\*\\*\\* Source `MissingSrc' not found, needed by target `missing\\d+'\\.( Stop\\.)?\\n)|\ +(scons: \\*\\*\\* \\[\\w+] Build interrupted\.\\n)\ """ re_errors = "(" + re_error + ")+" @@ -116,7 +152,17 @@ re_errors = "(" + re_error + ")+" test.run(arguments = 'all', status = 2, stderr = "scons: *** [failed19] Error 2\n") -test.must_not_exist(test.workpath('ok')) +test.must_not_exist(test.workpath('side_effect')) +for i in range(20): + test.must_not_exist(test.workpath('ok%02da' % i)) + test.must_not_exist(test.workpath('ok%02db' % i)) + test.must_not_exist(test.workpath('ok%02dc' % i)) + test.must_not_exist(test.workpath('prereq%02d' % i)) + test.must_not_exist(test.workpath('ignore%02d' % i)) + test.must_not_exist(test.workpath('igreq%02d' % i)) + test.must_not_exist(test.workpath('withSE%02da' % i)) + test.must_not_exist(test.workpath('withSE%02db' % i)) + test.must_not_exist(test.workpath('withSE%02dc' % i)) for i in range(5): @@ -135,11 +181,17 @@ for i in range(5): status = 2, stderr = re_errors, match=TestSCons.match_re_dotall) + test.must_exist(test.workpath('side_effect')) for i in range(20): - test.must_exist(test.workpath('ok%02d' % i)) + test.must_exist(test.workpath('ok%02da' % i)) + test.must_exist(test.workpath('ok%02db' % i)) + test.must_exist(test.workpath('ok%02dc' % i)) test.must_exist(test.workpath('prereq%02d' % i)) test.must_not_exist(test.workpath('ignore%02d' % i)) test.must_exist(test.workpath('igreq%02d' % i)) + test.must_exist(test.workpath('withSE%02da' % i)) + test.must_exist(test.workpath('withSE%02db' % i)) + test.must_exist(test.workpath('withSE%02dc' % i)) for i in range(5): @@ -147,7 +199,7 @@ for i in range(5): status = 2, stderr = re_errors, match=TestSCons.match_re_dotall) - test.must_not_exist(test.workpath('ok')) + for i in range(5): test.run(arguments = '-c all') @@ -157,6 +209,7 @@ for i in range(5): stderr = re_errors, match=TestSCons.match_re_dotall) + for i in range(5): test.run(arguments = '-c all') @@ -164,10 +217,26 @@ for i in range(5): status = 2, stderr = re_errors, match=TestSCons.match_re_dotall) + test.must_exist(test.workpath('side_effect')) for i in range(20): - test.must_exist(test.workpath('ok%02d' % i)) + test.must_exist(test.workpath('ok%02da' % i)) + test.must_exist(test.workpath('ok%02db' % i)) + test.must_exist(test.workpath('ok%02dc' % i)) test.must_exist(test.workpath('prereq%02d' % i)) test.must_not_exist(test.workpath('ignore%02d' % i)) test.must_exist(test.workpath('igreq%02d' % i)) + test.must_exist(test.workpath('withSE%02da' % i)) + test.must_exist(test.workpath('withSE%02db' % i)) + test.must_exist(test.workpath('withSE%02dc' % i)) + + +for i in range(5): + test.run(arguments = '-c all') + + test.run(arguments = '-j 8 -k --random interrupt=yes all', + status = 2, + stderr = re_errors, + match=TestSCons.match_re_dotall) + test.pass_test() diff --git a/test/Scanner/Entry-to-Dir.py b/test/Scanner/Entry-to-Dir.py new file mode 100644 index 0000000..0b5dbd7 --- /dev/null +++ b/test/Scanner/Entry-to-Dir.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that an implicit dependency search for a directory for which +we have an Entry Node works as expected, converting the Entry into a +Dir Node. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +env = Environment() +tc = env.Program('testcase', 'testcase.cpp') +foo = env.Entry('foo') +tc[0].all_children()[0].all_children() +""") + +test.write('testcase.cpp', """\ +#if 0 +#include "foo/bar/widget.h" +#endif +int main(int argc, char *argv[]) +{ + return 0; +} +""") + +test.run(arguments = '.') + +# In 0.98.2, re-running failed with a stack trace. +test.run(arguments = '.') + +test.pass_test() diff --git a/test/Scanner/source_scanner-dict.py b/test/Scanner/source_scanner-dict.py new file mode 100644 index 0000000..1ac15a8 --- /dev/null +++ b/test/Scanner/source_scanner-dict.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that a source_scanner that uses a dictionary to select more +specific scanners for source file suffixes works correctly, even +when it's handed a file suffix that it doesn't know how to scan +(i.e., for which it doesn't have a specific scanner in its dictionary). +""" + +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +test.write('build.py', r""" +import sys +output = open(sys.argv[1], 'wb') +for infile in sys.argv[2:]: + input = open(infile, 'rb') + + include_prefix = 'include%s ' % infile[-1] + + def process(infp, outfp, include_prefix=include_prefix): + for line in infp.readlines(): + if line[:len(include_prefix)] == include_prefix: + file = line[len(include_prefix):-1] + process(open(file, 'rb'), outfp) + else: + outfp.write(line) + + process(input, output) + +sys.exit(0) +""") + +# Execute a subsidiary SConscript just to make sure we can +# get at the Scanner keyword from there. + +test.write('SConstruct', """ +SConscript('SConscript') +""") + +test.write('SConscript', """ +import re + +include1_re = re.compile(r'^include1\s+(\S+)$', re.M) +include2_re = re.compile(r'^include2\s+(\S+)$', re.M) +include3_re = re.compile(r'^include3\s+(\S+)$', re.M) + +def k1_scan(node, env, scanpaths, arg=None): + contents = node.get_contents() + includes = include1_re.findall(contents) + return includes + +def k2_scan(node, env, scanpaths, arg=None): + contents = node.get_contents() + includes = include2_re.findall(contents) + return includes + +def k3_scan(node, env, scanpaths, arg=None): + contents = node.get_contents() + includes = include3_re.findall(contents) + return includes + +kscanner = Scanner({'.k1' : Scanner(k1_scan), '.k2': Scanner(k2_scan)}) + +b = Builder(action=r'%(_python_)s build.py $TARGET $SOURCES', + source_scanner=kscanner) +env = Environment(BUILDERS={'Build':b}) + +kscanner.add_scanner('.k3', Scanner(k3_scan)) + +env.Build('aaa', 'aaa.k1') +env.Build('bbb', 'bbb.k2') +env.Build('ccc', 'ccc.k3') +env.Build('ddd', ['ddd.k4', 'aaa.k1', 'bbb.k2', 'ccc.k3']) +""" % locals()) + +test.write('aaa.k1', +"""aaa.k1 1 +line 2 +include1 xxx +include2 yyy +include3 zzz +line 6 +""") + +test.write('bbb.k2', +"""bbb.k2 1 +line 2 +include1 xxx +include2 yyy +include3 zzz +line 6 +""") + +test.write('ccc.k3', +"""ccc.k3 1 +line 2 +include1 xxx +include2 yyy +include3 zzz +line 6 +""") + +test.write('ddd.k4', +"""ddd.k4 1 +line 2 +line 3 +""") + +test.write('xxx', "xxx 1\n") +test.write('yyy', "yyy 1\n") +test.write('zzz', "zzz 1\n") + + + + +expect = test.wrap_stdout("""\ +%(_python_)s build.py aaa aaa.k1 +%(_python_)s build.py bbb bbb.k2 +%(_python_)s build.py ccc ccc.k3 +%(_python_)s build.py ddd ddd.k4 aaa.k1 bbb.k2 ccc.k3 +""" % locals()) + +test.run(stdout=expect) + +expect_aaa = 'aaa.k1 1\nline 2\nxxx 1\ninclude2 yyy\ninclude3 zzz\nline 6\n' +expect_bbb = 'bbb.k2 1\nline 2\ninclude1 xxx\nyyy 1\ninclude3 zzz\nline 6\n' +expect_ccc = 'ccc.k3 1\nline 2\ninclude1 xxx\ninclude2 yyy\nzzz 1\nline 6\n' +expect_ddd = 'ddd.k4 1\nline 2\nline 3\n' + expect_aaa + expect_bbb + expect_ccc + +test.must_match('aaa', expect_aaa) +test.must_match('bbb', expect_bbb) +test.must_match('ccc', expect_ccc) +test.must_match('ddd', expect_ddd) + +test.up_to_date(arguments = '.') + + + +test.write('zzz', "zzz 2\n") + +expect = test.wrap_stdout("""\ +%(_python_)s build.py ccc ccc.k3 +%(_python_)s build.py ddd ddd.k4 aaa.k1 bbb.k2 ccc.k3 +""" % locals()) + +test.run(stdout=expect) + +expect_ccc = 'ccc.k3 1\nline 2\ninclude1 xxx\ninclude2 yyy\nzzz 2\nline 6\n' +expect_ddd = 'ddd.k4 1\nline 2\nline 3\n' + expect_aaa + expect_bbb + expect_ccc + +test.must_match('bbb', expect_bbb) +test.must_match('ddd', expect_ddd) + + + +test.write('yyy', "yyy 2\n") + +expect = test.wrap_stdout("""\ +%(_python_)s build.py bbb bbb.k2 +%(_python_)s build.py ddd ddd.k4 aaa.k1 bbb.k2 ccc.k3 +""" % locals()) + +test.run(stdout=expect) + +expect_bbb = 'bbb.k2 1\nline 2\ninclude1 xxx\nyyy 2\ninclude3 zzz\nline 6\n' +expect_ddd = 'ddd.k4 1\nline 2\nline 3\n' + expect_aaa + expect_bbb + expect_ccc + +test.must_match('bbb', expect_bbb) +test.must_match('ddd', expect_ddd) + + + +test.write('xxx', "xxx 2\n") + +expect = test.wrap_stdout("""\ +%(_python_)s build.py aaa aaa.k1 +%(_python_)s build.py ddd ddd.k4 aaa.k1 bbb.k2 ccc.k3 +""" % locals()) + +test.run(stdout=expect) + +expect_aaa = 'aaa.k1 1\nline 2\nxxx 2\ninclude2 yyy\ninclude3 zzz\nline 6\n' +expect_ddd = 'ddd.k4 1\nline 2\nline 3\n' + expect_aaa + expect_bbb + expect_ccc + +test.must_match('aaa', expect_aaa) +test.must_match('ddd', expect_ddd) + + + +test.pass_test() diff --git a/test/Variables/BoolVariable.py b/test/Variables/BoolVariable.py index 1bda19b..2ebe707 100644 --- a/test/Variables/BoolVariable.py +++ b/test/Variables/BoolVariable.py @@ -50,12 +50,15 @@ def check(expect): test.write(SConstruct_path, """\ +from SCons.Variables.BoolVariable import BoolVariable +BV = BoolVariable + from SCons.Variables import BoolVariable opts = Variables(args=ARGUMENTS) opts.AddVariables( BoolVariable('warnings', 'compilation with -Wall and similiar', 1), - BoolVariable('profile', 'create profiling informations', 0), + BV('profile', 'create profiling informations', 0), ) env = Environment(variables=opts) @@ -78,7 +81,7 @@ check([str(False), str(True)]) expect_stderr = """ scons: *** Error converting option: warnings Invalid value for boolean option: irgendwas -""" + test.python_file_line(SConstruct_path, 9) +""" + test.python_file_line(SConstruct_path, 12) test.run(arguments='warnings=irgendwas', stderr = expect_stderr, status=2) diff --git a/test/Variables/EnumVariable.py b/test/Variables/EnumVariable.py index 6966509..4d09587 100644 --- a/test/Variables/EnumVariable.py +++ b/test/Variables/EnumVariable.py @@ -44,6 +44,9 @@ def check(expect): test.write(SConstruct_path, """\ +from SCons.Variables.EnumVariable import EnumVariable +EV = EnumVariable + from SCons.Variables import EnumVariable list_of_libs = Split('x11 gl qt ical') @@ -56,9 +59,9 @@ opts.AddVariables( EnumVariable('guilib', 'gui lib to use', 'gtk', allowed_values=('motif', 'gtk', 'kde'), map={}, ignorecase=1), # case insensitive - EnumVariable('some', 'some option', 'xaver', - allowed_values=('xaver', 'eins'), - map={}, ignorecase=2), # make lowercase + EV('some', 'some option', 'xaver', + allowed_values=('xaver', 'eins'), + map={}, ignorecase=2), # make lowercase ) env = Environment(variables=opts) @@ -82,19 +85,19 @@ check(['full', 'KdE', 'eins']) expect_stderr = """ scons: *** Invalid value for option debug: FULL -""" + test.python_file_line(SConstruct_path, 18) +""" + test.python_file_line(SConstruct_path, 21) test.run(arguments='debug=FULL', stderr=expect_stderr, status=2) expect_stderr = """ scons: *** Invalid value for option guilib: irgendwas -""" + test.python_file_line(SConstruct_path, 18) +""" + test.python_file_line(SConstruct_path, 21) test.run(arguments='guilib=IrGeNdwas', stderr=expect_stderr, status=2) expect_stderr = """ scons: *** Invalid value for option some: irgendwas -""" + test.python_file_line(SConstruct_path, 18) +""" + test.python_file_line(SConstruct_path, 21) test.run(arguments='some=IrGeNdwas', stderr=expect_stderr, status=2) diff --git a/test/Variables/ListVariable.py b/test/Variables/ListVariable.py index 90d80ed..740698b 100644 --- a/test/Variables/ListVariable.py +++ b/test/Variables/ListVariable.py @@ -46,6 +46,9 @@ def check(expect): test.write(SConstruct_path, """\ +from SCons.Variables.ListVariable import ListVariable +LV = ListVariable + from SCons.Variables import ListVariable list_of_libs = Split('x11 gl qt ical') @@ -58,6 +61,7 @@ opts.AddVariables( 'all', names = list_of_libs, map = {'GL':'gl', 'QT':'qt'}), + LV('listvariable', 'listvariable help', 'all', names=['l1', 'l2', 'l3']) ) env = Environment(variables=opts) @@ -80,7 +84,8 @@ test.run() check(['all', '1', 'gl ical qt x11', 'gl ical qt x11', "['gl ical qt x11']"]) -test.must_match(test.workpath('scons.variables'), "shared = 'all'"+os.linesep) +expect = "shared = 'all'"+os.linesep+"listvariable = 'all'"+os.linesep +test.must_match(test.workpath('scons.variables'), expect) check(['all', '1', 'gl ical qt x11', 'gl ical qt x11', "['gl ical qt x11']"]) @@ -109,7 +114,7 @@ check(['gl,qt', '0', 'gl qt', 'gl qt', "['gl qt']"]) expect_stderr = """ scons: *** Error converting option: shared Invalid value(s) for option: foo -""" + test.python_file_line(SConstruct_path, 15) +""" + test.python_file_line(SConstruct_path, 19) test.run(arguments='shared=foo', stderr=expect_stderr, status=2) @@ -118,28 +123,28 @@ test.run(arguments='shared=foo', stderr=expect_stderr, status=2) expect_stderr = """ scons: *** Error converting option: shared Invalid value(s) for option: foo -""" + test.python_file_line(SConstruct_path, 15) +""" + test.python_file_line(SConstruct_path, 19) test.run(arguments='shared=foo,ical', stderr=expect_stderr, status=2) expect_stderr = """ scons: *** Error converting option: shared Invalid value(s) for option: foo -""" + test.python_file_line(SConstruct_path, 15) +""" + test.python_file_line(SConstruct_path, 19) test.run(arguments='shared=ical,foo', stderr=expect_stderr, status=2) expect_stderr = """ scons: *** Error converting option: shared Invalid value(s) for option: foo -""" + test.python_file_line(SConstruct_path, 15) +""" + test.python_file_line(SConstruct_path, 19) test.run(arguments='shared=ical,foo,x11', stderr=expect_stderr, status=2) expect_stderr = """ scons: *** Error converting option: shared Invalid value(s) for option: foo,bar -""" + test.python_file_line(SConstruct_path, 15) +""" + test.python_file_line(SConstruct_path, 19) test.run(arguments='shared=foo,x11,,,bar', stderr=expect_stderr, status=2) diff --git a/test/Variables/PackageVariable.py b/test/Variables/PackageVariable.py index 4d36252..4338449 100644 --- a/test/Variables/PackageVariable.py +++ b/test/Variables/PackageVariable.py @@ -50,6 +50,9 @@ def check(expect): test.write(SConstruct_path, """\ +from SCons.Variables.PackageVariable import PackageVariable +PV = PackageVariable + from SCons.Variables import PackageVariable opts = Variables(args=ARGUMENTS) @@ -57,6 +60,7 @@ opts.AddVariables( PackageVariable('x11', 'use X11 installed here (yes = search some places', 'yes'), + PV('package', 'help for package', 'yes'), ) env = Environment(variables=opts) @@ -80,7 +84,7 @@ check([test.workpath()]) expect_stderr = """ scons: *** Path does not exist for option x11: /non/existing/path/ -""" + test.python_file_line(SConstruct_path, 10) +""" + test.python_file_line(SConstruct_path, 14) test.run(arguments='x11=/non/existing/path/', stderr=expect_stderr, status=2) diff --git a/test/Variables/PathVariable.py b/test/Variables/PathVariable.py index a2f96a7..96da82f 100644 --- a/test/Variables/PathVariable.py +++ b/test/Variables/PathVariable.py @@ -49,6 +49,9 @@ workpath = test.workpath() libpath = os.path.join(workpath, 'lib') test.write(SConstruct_path, """\ +from SCons.Variables.PathVariable import PathVariable +PV = PathVariable + from SCons.Variables import PathVariable qtdir = r'%s' @@ -56,7 +59,7 @@ qtdir = r'%s' opts = Variables(args=ARGUMENTS) opts.AddVariables( PathVariable('qtdir', 'where the root of Qt is installed', qtdir), - PathVariable('qt_libraries', 'where the Qt library is installed', r'%s'), + PV('qt_libraries', 'where the Qt library is installed', r'%s'), ) env = Environment(variables=opts) @@ -90,7 +93,7 @@ test.run(arguments=['qtdir=%s' % qtpath, 'qt_libraries=%s' % libpath]) check([qtpath, libpath, libpath]) qtpath = os.path.join(workpath, 'non', 'existing', 'path') -SConstruct_file_line = test.python_file_line(test.workpath('SConstruct'), 11)[:-1] +SConstruct_file_line = test.python_file_line(test.workpath('SConstruct'), 14)[:-1] expect_stderr = """ scons: *** Path for option qtdir does not exist: %(qtpath)s diff --git a/test/option/taskmastertrace.py b/test/option/taskmastertrace.py index 30e15aa..a7d583e 100644 --- a/test/option/taskmastertrace.py +++ b/test/option/taskmastertrace.py @@ -48,37 +48,41 @@ test.write('Tfile.in', "Tfile.in\n") expect_stdout = test.wrap_stdout("""\ Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node <no_state '.'> and its children: -Taskmaster: <no_state 'SConstruct'> -Taskmaster: <no_state 'Tfile.in'> -Taskmaster: <no_state 'Tfile.mid'> -Taskmaster: <no_state 'Tfile.out'> -Taskmaster: Considering node <no_state 'SConstruct'> and its children: -Taskmaster: Evaluating <pending 'SConstruct'> +Taskmaster: Considering node <no_state 0 '.'> and its children: +Taskmaster: <no_state 0 'SConstruct'> +Taskmaster: <no_state 0 'Tfile.in'> +Taskmaster: <no_state 0 'Tfile.mid'> +Taskmaster: <no_state 0 'Tfile.out'> +Taskmaster: adjusting ref count: <pending 1 '.'> +Taskmaster: adjusting ref count: <pending 2 '.'> +Taskmaster: adjusting ref count: <pending 3 '.'> +Taskmaster: adjusting ref count: <pending 4 '.'> +Taskmaster: Considering node <no_state 0 'SConstruct'> and its children: +Taskmaster: Evaluating <pending 0 'SConstruct'> Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node <no_state 'Tfile.in'> and its children: -Taskmaster: Evaluating <pending 'Tfile.in'> +Taskmaster: Considering node <no_state 0 'Tfile.in'> and its children: +Taskmaster: Evaluating <pending 0 'Tfile.in'> Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node <no_state 'Tfile.mid'> and its children: -Taskmaster: <up_to_date 'Tfile.in'> -Taskmaster: Evaluating <pending 'Tfile.mid'> +Taskmaster: Considering node <no_state 0 'Tfile.mid'> and its children: +Taskmaster: <up_to_date 0 'Tfile.in'> +Taskmaster: Evaluating <pending 0 'Tfile.mid'> Copy("Tfile.mid", "Tfile.in") Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node <no_state 'Tfile.out'> and its children: -Taskmaster: <executed 'Tfile.mid'> -Taskmaster: Evaluating <pending 'Tfile.out'> +Taskmaster: Considering node <no_state 0 'Tfile.out'> and its children: +Taskmaster: <executed 0 'Tfile.mid'> +Taskmaster: Evaluating <pending 0 'Tfile.out'> Copy("Tfile.out", "Tfile.mid") Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node <pending '.'> and its children: -Taskmaster: <up_to_date 'SConstruct'> -Taskmaster: <up_to_date 'Tfile.in'> -Taskmaster: <executed 'Tfile.mid'> -Taskmaster: <executed 'Tfile.out'> -Taskmaster: Evaluating <pending '.'> +Taskmaster: Considering node <pending 0 '.'> and its children: +Taskmaster: <up_to_date 0 'SConstruct'> +Taskmaster: <up_to_date 0 'Tfile.in'> +Taskmaster: <executed 0 'Tfile.mid'> +Taskmaster: <executed 0 'Tfile.out'> +Taskmaster: Evaluating <pending 0 '.'> Taskmaster: Looking for a node to evaluate Taskmaster: No candidate anymore. @@ -103,35 +107,39 @@ test.run(arguments='--taskmastertrace=trace.out .', stdout=expect_stdout) expect_trace = """\ Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node <no_state '.'> and its children: -Taskmaster: <no_state 'SConstruct'> -Taskmaster: <no_state 'Tfile.in'> -Taskmaster: <no_state 'Tfile.mid'> -Taskmaster: <no_state 'Tfile.out'> -Taskmaster: Considering node <no_state 'SConstruct'> and its children: -Taskmaster: Evaluating <pending 'SConstruct'> +Taskmaster: Considering node <no_state 0 '.'> and its children: +Taskmaster: <no_state 0 'SConstruct'> +Taskmaster: <no_state 0 'Tfile.in'> +Taskmaster: <no_state 0 'Tfile.mid'> +Taskmaster: <no_state 0 'Tfile.out'> +Taskmaster: adjusting ref count: <pending 1 '.'> +Taskmaster: adjusting ref count: <pending 2 '.'> +Taskmaster: adjusting ref count: <pending 3 '.'> +Taskmaster: adjusting ref count: <pending 4 '.'> +Taskmaster: Considering node <no_state 0 'SConstruct'> and its children: +Taskmaster: Evaluating <pending 0 'SConstruct'> Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node <no_state 'Tfile.in'> and its children: -Taskmaster: Evaluating <pending 'Tfile.in'> +Taskmaster: Considering node <no_state 0 'Tfile.in'> and its children: +Taskmaster: Evaluating <pending 0 'Tfile.in'> Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node <no_state 'Tfile.mid'> and its children: -Taskmaster: <up_to_date 'Tfile.in'> -Taskmaster: Evaluating <pending 'Tfile.mid'> +Taskmaster: Considering node <no_state 0 'Tfile.mid'> and its children: +Taskmaster: <up_to_date 0 'Tfile.in'> +Taskmaster: Evaluating <pending 0 'Tfile.mid'> Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node <no_state 'Tfile.out'> and its children: -Taskmaster: <executed 'Tfile.mid'> -Taskmaster: Evaluating <pending 'Tfile.out'> +Taskmaster: Considering node <no_state 0 'Tfile.out'> and its children: +Taskmaster: <executed 0 'Tfile.mid'> +Taskmaster: Evaluating <pending 0 'Tfile.out'> Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node <pending '.'> and its children: -Taskmaster: <up_to_date 'SConstruct'> -Taskmaster: <up_to_date 'Tfile.in'> -Taskmaster: <executed 'Tfile.mid'> -Taskmaster: <executed 'Tfile.out'> -Taskmaster: Evaluating <pending '.'> +Taskmaster: Considering node <pending 0 '.'> and its children: +Taskmaster: <up_to_date 0 'SConstruct'> +Taskmaster: <up_to_date 0 'Tfile.in'> +Taskmaster: <executed 0 'Tfile.mid'> +Taskmaster: <executed 0 'Tfile.out'> +Taskmaster: Evaluating <pending 0 '.'> Taskmaster: Looking for a node to evaluate Taskmaster: No candidate anymore. |