Multi-level build dir with Object() and duplicate=0.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 9 Aug 2003 03:30:48 +0000 (03:30 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sat, 9 Aug 2003 03:30:48 +0000 (03:30 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@762 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/CHANGES.txt
src/engine/SCons/Builder.py
src/engine/SCons/BuilderTests.py
src/engine/SCons/Node/FS.py
src/engine/SCons/Node/FSTests.py
test/SConscript-build_dir.py

index 74b537c4866665c96225ab1a7eb67cec0019b63e..9e9e7747a172ef19659dc02a191f8ad143245e24 100644 (file)
@@ -86,6 +86,10 @@ RELEASE 0.XX - XXX
   - Make how we build .rpm packages not depend on the installation
     locations from the distutils being used.
 
+  - When deducing a target Node, create it directly from the first
+    source Node, not by trying to create the right string to pass to
+    arg2nodes().
+
   From Gary Oberbrunner:
 
   - Report the target being built in error messages when building
index b7bc1a30c24d6072b4de7117c5ed62db22af7237..be1608dd301ac21d0279857b2f849b4504c0f330 100644 (file)
@@ -349,19 +349,17 @@ class BuilderBase:
         src_suf = self.get_src_suffix(env)
 
         source = adjustixes(source, None, src_suf)
+        slist = SCons.Node.arg2nodes(source, self.source_factory)
+
         if target is None:
-            s = source[0]
-            if isinstance(s, SCons.Node.Node):
-                s = str(s)
-            dir, s = os.path.split(s)
-            target = pre + self.splitext(s)[0] + suf
-            if dir:
-                target = [ os.path.join(dir, target) ]
+            try:
+                t_from_s = slist[0].target_from_source
+            except AttributeError:
+                raise UserError("Do not know how to create a target from source `%s'" % slist[0])
+            tlist = [ t_from_s(pre, suf, self.splitext) ]
         else:
             target = adjustixes(target, pre, suf)
-
-        slist = SCons.Node.arg2nodes(source, self.source_factory)
-        tlist = SCons.Node.arg2nodes(target, self.target_factory)
+            tlist = SCons.Node.arg2nodes(target, self.target_factory)
 
         if self.emitter:
             # The emitter is going to do str(node), but because we're
index a7c2f12168623d3827f7ded2a446e1e7a8c9efb5..f8d22edee90c8d5ad15b2ebf3705e21a778c04a5 100644 (file)
@@ -111,7 +111,7 @@ class Environment:
     
 env = Environment()
 
-class MyNode:
+class MyNode_without_target_from_source:
     def __init__(self, name):
         self.name = name
         self.sources = []
@@ -140,6 +140,10 @@ class MyNode:
     def get_executor(self, create=1):
         return self.executor
 
+class MyNode(MyNode_without_target_from_source):
+    def target_from_source(self, prefix, suffix, stripext):
+        return MyNode(prefix + stripext(str(self))[0] + suffix)
+
 class BuilderTestCase(unittest.TestCase):
 
     def test__nonzero__(self):
@@ -215,6 +219,21 @@ class BuilderTestCase(unittest.TestCase):
         assert target.name == uni('n16 n17')
         assert target.sources[0].name == uni('n18 n19')
 
+        n20 = MyNode_without_target_from_source('n20')
+        flag = 0
+        try:
+            target = builder(env, source=n20)
+        except SCons.Errors.UserError, e:
+            flag = 1
+        assert flag, "UserError should be thrown if a source node can't create a target."
+
+        builder = SCons.Builder.Builder(action="foo",
+                                        node_factory=MyNode,
+                                        prefix='p-',
+                                        suffix='.s')
+        target = builder(env, source='n21')
+        assert target.name == 'p-n21.s', target
+
     def test_action(self):
         """Test Builder creation
 
index d12a504d7311d8c870885173190581186949eb9e..249c8c6ae3ed33729e6fd132e931c21c1667b29d 100644 (file)
@@ -1455,6 +1455,10 @@ class File(Base):
             return dir, os.path.join(dir, bsig)
         return None, None
 
+    def target_from_source(self, prefix, suffix, splitext=SCons.Util.splitext):
+        return self.dir.File(prefix + splitext(self.name)[0] + suffix)
+
+
 default_fs = FS()
 
 
index d651e1cf79872ca5c04f32958963616f04bfb641..17d037d225f6b95986d8556c5c87f84044f53fbb 100644 (file)
@@ -1074,6 +1074,18 @@ class FSTestCase(unittest.TestCase):
                f.get_string(0)
         assert f.get_string(1) == 'baz', f.get_string(1)
 
+        x = fs.File('x.c')
+        t = x.target_from_source('pre-', '-suf')
+        assert str(t) == 'pre-x-suf', str(t)
+
+        y = fs.File('dir/y')
+        t = y.target_from_source('pre-', '-suf')
+        assert str(t) == 'dir/pre-y-suf', str(t)
+
+        z = fs.File('zz')
+        t = z.target_from_source('pre-', '-suf', lambda x: x[:-1])
+        assert str(t) == 'pre-z-suf', str(t)
+
 class EntryTestCase(unittest.TestCase):
     def runTest(self):
         """Test methods specific to the Entry sub-class.
index 165619a1148a1c0adc7db089e213a4ed39eb1501..d67fdaca0e2339102549a4c2c678183a55e5415c 100644 (file)
@@ -197,4 +197,41 @@ test.fail_test(os.path.exists(test.workpath('build', 'var8', 'aaa.in')))
 test.fail_test(os.path.exists(test.workpath('build', 'var8', 'bbb.in')))
 test.fail_test(os.path.exists(test.workpath('build', 'var8', 'ccc.in')))
 
+###################
+test.subdir('test2')
+
+test.write(['test2', 'SConstruct'], """\
+SConscript('SConscript', build_dir='Build', src_dir='.', duplicate=0)
+""")
+
+test.write(['test2', 'SConscript'], """\
+env = Environment()
+foo_obj = env.Object('foo.c')
+env.Program('foo', [foo_obj, 'bar.c'])
+""")
+
+test.write(['test2', 'bar.c'], r"""
+void
+bar(void) {
+        printf("bar.c\n");
+}
+""")
+
+test.write(['test2', 'foo.c'], """\
+int
+main(int argc, char *argv[]) {
+        bar();
+        printf("foo.c\n");
+}
+""")
+
+test.run(chdir="test2")
+
+_obj = TestSCons._obj
+
+test.fail_test(os.path.exists(test.workpath('test2', 'foo' + _obj)))
+test.fail_test(os.path.exists(test.workpath('test2', 'bar' + _obj)))
+test.fail_test(not os.path.exists(test.workpath('test2', 'Build', 'foo' + _obj)))
+test.fail_test(not os.path.exists(test.workpath('test2', 'Build', 'bar' + _obj)))
+
 test.pass_test()