summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2004-09-18 18:30:35 (GMT)
committerSteven Knight <knight@baldmt.com>2004-09-18 18:30:35 (GMT)
commitaeb8fd273afe8db3b98ad991d6afb94a6007c293 (patch)
tree0f9c43b8b55625dca1c3d9c27459af1fc2a97f5f
parent40f1769edcc4b9bfab72472899507a173d69e2a4 (diff)
downloadSCons-aeb8fd273afe8db3b98ad991d6afb94a6007c293.zip
SCons-aeb8fd273afe8db3b98ad991d6afb94a6007c293.tar.gz
SCons-aeb8fd273afe8db3b98ad991d6afb94a6007c293.tar.bz2
Build targets in an associated BuildDir even if there are local targets in the source directory. (Kevin Quick)
-rw-r--r--src/CHANGES.txt3
-rw-r--r--src/engine/SCons/Taskmaster.py11
-rw-r--r--src/engine/SCons/TaskmasterTests.py3
-rw-r--r--test/BuildDir.py11
-rw-r--r--test/NodeOps.py172
-rw-r--r--test/option-u.py7
6 files changed, 152 insertions, 55 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 1965c61..d7b6693 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -109,6 +109,9 @@ RELEASE 0.97 - XXX
- Fix problems with Parallel Task Exception handling.
+ - Build targets in an associated BuildDir even if there are targets
+ or subdirectories locally in the source directory.
+
From Christoph Wiedemann:
- Add an Environment.SetDefault() method that only sets values if
diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py
index 84eb08d..6bd5e21 100644
--- a/src/engine/SCons/Taskmaster.py
+++ b/src/engine/SCons/Taskmaster.py
@@ -253,6 +253,7 @@ class Taskmaster:
self.ready = None # the next task that is ready to be executed
self.order = order
self.message = None
+ self.altered = []
def _find_next_ready_node(self):
"""Find the next node that is ready to be built"""
@@ -331,15 +332,15 @@ class Taskmaster:
self.ready = node
break
- # If there aren't any children with builders and this
- # was a top-level argument, then see if we can find any
+ # If this was a top-level argument and we haven't already
+ # done so, see if we can alter the target list to find any
# corresponding targets in linked build directories:
- if not derived and node in self.targets:
+ if node in self.targets and node not in self.altered:
alt, message = node.alter_targets()
if alt:
self.message = message
- self.candidates.pop()
- self.candidates.extend(alt)
+ self.candidates.extend(self.order(alt))
+ self.altered.append(node)
continue
# Add derived files that have not been built
diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py
index a908192..cc4ba0c 100644
--- a/src/engine/SCons/TaskmasterTests.py
+++ b/src/engine/SCons/TaskmasterTests.py
@@ -421,6 +421,9 @@ class TaskmasterTestCase(unittest.TestCase):
t = tm.next_task()
assert t.get_target() == n7
t.executed()
+ t = tm.next_task()
+ assert t.get_target() == n6
+ t.executed()
n1 = Node("n1")
n2 = Node("n2", [n1])
diff --git a/test/BuildDir.py b/test/BuildDir.py
index 4e2871a..0877995 100644
--- a/test/BuildDir.py
+++ b/test/BuildDir.py
@@ -355,7 +355,11 @@ test.run(chdir='work2', arguments='.', stderr=None)
test.fail_test(not blank_output(test.stderr()))
-test.up_to_date(chdir='work2', arguments='.')
+test.run(chdir='work2', arguments='.',
+ stdout=test.wrap_stdout("""\
+scons: building associated BuildDir targets: build
+scons: `.' is up to date.
+"""))
test.write( ['work3', 'SConstruct'], """\
SConscriptChdir(0)
@@ -377,7 +381,10 @@ test.write( ['work3', 'existing.h'], """\
""")
test.run(chdir='work3',
- stdout=test.wrap_stdout("scons: `.' is up to date.\n"),
+ stdout=test.wrap_stdout("""\
+scons: building associated BuildDir targets: build
+scons: `.' is up to date.
+"""),
stderr="""\
existing.h:/* a header file */
non_existing.h:
diff --git a/test/NodeOps.py b/test/NodeOps.py
index e884400..ae9268c 100644
--- a/test/NodeOps.py
+++ b/test/NodeOps.py
@@ -57,7 +57,7 @@ if string.find(sys.platform, 'irix') > -1:
test = TestSCons.TestSCons()
-test.subdir('bld', 'src')
+test.subdir('bld', 'src', ['src', 'subsrcdir'])
sconstruct = r"""
foo = Environment(SHCXXFLAGS = '%(fooflags)s', WIN32_INSERT_DEF=1)
@@ -126,49 +126,75 @@ doIt()
}
""")
-test.write(['src', 'SConscript'], r"""
+sconscript = r"""
import os
Import('*')
-# Interoperability with old Python versions.
-True, False = 1, 0
+import __builtin__
+try:
+ __builtin__.True
+except AttributeError:
+ __builtin__.True = 1
+ __builtin__.False = 0
def mycopy(env, source, target):
open(str(target[0]),'w').write(open(str(source[0]),'r').read())
+
+def exists_test(node):
+ before = os.path.exists(str(node)) # doesn't exist yet in BuildDir
+ via_node = node.exists() # side effect causes copy from src
+ after = os.path.exists(str(node))
+ node.is_derived()
+ node.is_pseudo_derived()
+ import SCons.Script
+ if SCons.Script.options.noexec:
+ if (before,via_node,after) != (False,False,False):
+ import sys
+ sys.stderr.write('BuildDir exits() populated during dryrun!\n')
+ sys.exit(-2)
+ else:
+ if (before,via_node,after) != (False,True,True):
+ import sys
+ sys.stderr.write('BuildDir exists() population did not occur! (%%s:%%s,%%s,%%s)\n'%%(str(node),before,via_node,after))
+ sys.exit(-2)
goo = Environment(CPPFLAGS = '%(fooflags)s')
-Nodes.append(File('goof.in'))
-before = os.path.exists('goof.in') # doesn't exist yet in BuildDir
-via_node = Nodes[-1].exists() # side effect causes copy from src
-after = os.path.exists('goof.in')
-import SCons.Script
-if SCons.Script.options.noexec:
- if (before,via_node,after) != (False,False,False):
- import sys
- sys.stderr.write('BuildDir exits() populated during dryrun!\n')
- sys.exit(-2)
-else:
- if (before,via_node,after) != (False,True,True):
- import sys
- sys.stderr.write('BuildDir exists() population did not occur!\n'%%(before,via_node,after))
- sys.exit(-2)
+goof_in = File('goof.in')
+if %(_E)s:
+ exists_test(goof_in)
+Nodes.append(goof_in)
Nodes.extend(goo.Command(target='goof.c', source='goof.in', action=mycopy))
+boo_src = File('subsrcdir/boo.c')
+if %(_E)s:
+ exists_test(boo_src)
+boo_objs = goo.Object(target='subsrcdir/boo%(_obj)s', source = boo_src)
+Nodes.extend(boo_objs)
Nodes.extend(goo.Object(target='goo%(_obj)s',source='goof.c'))
-goo.Library(target = 'goo', source = 'goo%(_obj)s')
-""" % locals() )
+goo.Library(target = 'goo', source = ['goo%(_obj)s'] + boo_objs)
+"""
test.write(['src', 'goof.in'], r"""
#include <stdio.h>
+extern char *boo_sub();
+
void
doIt()
{
#ifdef FOO
- printf("prog.cpp: GOO\n");
+ printf("prog.cpp: %s\n", boo_sub());
#endif
}
""")
+test.write(['src', 'subsrcdir', 'boo.c'], r"""
+char *
+boo_sub()
+{
+ return "GOO";
+}
+""")
+
test.write('main.c', r"""
void doIt();
@@ -181,23 +207,42 @@ main(int argc, char* argv[])
}
""")
+builddir_srcnodes = [ os.path.join('bld', 'goof.in'),
+ os.path.join('bld', 'subsrcdir', 'boo.c'),
+ ]
+
+sub_build_nodes = [ os.path.join('bld','subsrcdir','boo.o'),
+ os.path.join('bld','goo.o'),
+ os.path.join('bld','goof.c'),
+ os.path.join('bld','libgoo.a'),
+]
+
build_nodes = ['fooprog', 'libfoo.so', 'foo.o',
'barprog', 'libbar.so', 'bar.o',
'gooprog',
- os.path.join('bld','goo.o'),
- os.path.join('bld','goof.c'),
- os.path.join('bld','goof.in'),
- ]
+ ] + builddir_srcnodes + sub_build_nodes
+
+def cleanup_test():
+ "cleanup after running a test"
+ for F in builddir_srcnodes:
+ test.unlink(F) # will be repopulated during clean operation
+ test.run(arguments = '-c')
+ for F in builddir_srcnodes:
+ test.unlink(F)
+ for name in build_nodes:
+ test.must_not_exist(test.workpath(name))
+
### First pass, make sure everything goes quietly
for name in build_nodes:
- test.fail_test(os.path.exists(test.workpath(name)))
+ test.must_not_exist(test.workpath(name))
_E=0
test.write('SConstruct', sconstruct % locals() )
+test.write(['src', 'SConscript'], sconscript % locals() )
test.run(arguments = '.',
stderr=TestSCons.noisy_ar,
@@ -208,22 +253,19 @@ test.run(program = test.workpath('barprog'), stdout = "prog.cpp: BAR\n")
test.run(program = test.workpath('gooprog'), stdout = "prog.cpp: GOO\n")
for name in build_nodes:
- test.fail_test(not os.path.exists(test.workpath(name)))
+ test.must_exist(test.workpath(name))
-test.unlink('bld/goof.in') # will be repopulated during clean operation
-test.run(arguments = '-c')
-test.unlink('bld/goof.in')
-for name in build_nodes:
- test.fail_test(os.path.exists(test.workpath(name)))
+cleanup_test()
### Next pass: add internal Node ops that may have side effects to
### ensure that those side-effects don't interfere with building
for name in build_nodes:
- test.fail_test(os.path.exists(test.workpath(name)))
+ test.must_not_exist(test.workpath(name))
_E=1
test.write('SConstruct', sconstruct % locals() )
+test.write(['src', 'SConscript'], sconscript % locals() )
test.run(arguments = '.',
stderr=TestSCons.noisy_ar,
@@ -234,29 +276,26 @@ test.run(program = test.workpath('barprog'), stdout = "prog.cpp: BAR\n")
test.run(program = test.workpath('gooprog'), stdout = "prog.cpp: GOO\n")
for name in build_nodes:
- test.fail_test(not os.path.exists(test.workpath(name)))
+ test.must_exist(test.workpath(name))
-test.unlink('bld/goof.in') # will be repopulated during clean operation
-test.run(arguments = '-c')
-test.unlink('bld/goof.in')
-for name in build_nodes:
- test.fail_test(os.path.exists(test.workpath(name)))
+cleanup_test()
### Next pass: try a dry-run first and verify that it doesn't change
### the buildability.
for name in build_nodes:
- test.fail_test(os.path.exists(test.workpath(name)))
+ test.must_not_exist(test.workpath(name))
_E=1
test.write('SConstruct', sconstruct % locals() )
+test.write(['src', 'SConscript'], sconscript % locals() )
test.run(arguments = '-n .',
stderr=TestSCons.noisy_ar,
match=TestSCons.match_re_dotall)
for name in build_nodes:
- test.fail_test(os.path.exists(test.workpath(name)))
+ test.must_not_exist(test.workpath(name))
test.run(arguments = '.',
stderr=TestSCons.noisy_ar,
@@ -267,13 +306,52 @@ test.run(program = test.workpath('barprog'), stdout = "prog.cpp: BAR\n")
test.run(program = test.workpath('gooprog'), stdout = "prog.cpp: GOO\n")
for name in build_nodes:
- test.fail_test(not os.path.exists(test.workpath(name)))
+ test.must_exist(test.workpath(name))
+
+cleanup_test()
+
+### Next pass: do an up-build from a BuildDir src
+
+
+for name in build_nodes:
+ test.must_not_exist(test.workpath(name))
+
+_E=0
+test.write('SConstruct', sconstruct % locals() )
+test.write(['src', 'SConscript'], sconscript % locals() )
+
+test.run(chdir='src', arguments = '-u',
+ stderr=TestSCons.noisy_ar,
+ match=TestSCons.match_re_dotall)
+
+for name in build_nodes:
+ if name in sub_build_nodes or name in builddir_srcnodes:
+ test.must_exist(test.workpath(name))
+ else:
+ test.must_not_exist(test.workpath(name))
+
+cleanup_test()
+
+### Next pass: do an up-build from a BuildDir src with Node Ops
+### side-effects
+
+for name in build_nodes:
+ test.must_not_exist(test.workpath(name))
+
+_E=1
+test.write('SConstruct', sconstruct % locals() )
+test.write(['src', 'SConscript'], sconscript % locals() )
+
+test.run(chdir='src', arguments = '-u',
+ stderr=TestSCons.noisy_ar,
+ match=TestSCons.match_re_dotall)
-test.unlink('bld/goof.in') # will be repopulated during clean operation
-test.run(arguments = '-c')
-test.unlink('bld/goof.in')
for name in build_nodes:
- test.fail_test(os.path.exists(test.workpath(name)))
+ if name in sub_build_nodes or name in builddir_srcnodes:
+ test.must_exist(test.workpath(name))
+ else:
+ test.must_not_exist(test.workpath(name))
+cleanup_test()
test.pass_test()
diff --git a/test/option-u.py b/test/option-u.py
index 28bab30..9b5e88c 100644
--- a/test/option-u.py
+++ b/test/option-u.py
@@ -70,7 +70,11 @@ env.Cat(target = 'dir/f2b.out', source = 'dir/f2b.in')
test.write(['sub4', 'SConscript'], """
Import('env')
env.Cat(target = 'f4a.out', source = 'f4a.in')
-env.Cat(target = 'dir/f4b.out', source = 'dir/f4b.in')
+f4b_in = File('dir/f4b.in')
+f4b_in.exists()
+f4b_in.is_derived()
+f4b_in.is_pseudo_derived()
+env.Cat(target = 'dir/f4b.out', source = f4b_in)
""")
test.write(['sub1', 'f1a.in'], "sub1/f1a.in")
@@ -128,6 +132,7 @@ test.run(chdir = 'sub4',
scons: building associated BuildDir targets: build
cat(["%s"], ["%s"])
cat(["%s"], ["%s"])
+scons: `sub4' is up to date.
""" % (f4b_out, f4b_in, f4a_out, f4a_in)))
test.must_not_exist(test.workpath('sub1', 'sub1/f1b.out'))