Build targets in an associated BuildDir even if there are local targets in the source...
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 18 Sep 2004 18:30:35 +0000 (18:30 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 18 Sep 2004 18:30:35 +0000 (18:30 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@1084 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/CHANGES.txt
src/engine/SCons/Taskmaster.py
src/engine/SCons/TaskmasterTests.py
test/BuildDir.py
test/NodeOps.py
test/option-u.py

index 1965c6191bd1a138edcb6ab6b8e1f0049a57be88..d7b66937a2153750179f5724fab50dd82acd2630 100644 (file)
@@ -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
index 84eb08dcffafeab5bb8246b71646cf530d755ddb..6bd5e2132ecf100747cdde721364e2746e27b501 100644 (file)
@@ -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
index a908192821450fa80c392a93085fcf0bf5aaf637..cc4ba0cd91143b5be85078a6f674ecc037be878c 100644 (file)
@@ -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])
index 4e2871a2308aed7e836dbf93044f0aae3150ad5c..0877995d84fc6d08b947c26b4c5f40426c15390d 100644 (file)
@@ -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:
index e884400ccae60bf9455f930c6eafc8983e2a9534..ae9268c0f7d954e1470cbdf51762b4329326350d 100644 (file)
@@ -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()
index 28bab30d1372a04bdc7751bef26187b47dc03dc9..9b5e88cfcaabb9ff4360a0d6276ddc410872402c 100644 (file)
@@ -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'))