summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2003-08-09 03:30:48 (GMT)
committerSteven Knight <knight@baldmt.com>2003-08-09 03:30:48 (GMT)
commitef6d3c2883fc43048e4eb5418eeb082d58b9d6cb (patch)
tree6b82fbae7e677011698bc39debd81d1572ff5c8c
parent2e861a0422e5330249e360b5098b3ad00d26b5e9 (diff)
downloadSCons-ef6d3c2883fc43048e4eb5418eeb082d58b9d6cb.zip
SCons-ef6d3c2883fc43048e4eb5418eeb082d58b9d6cb.tar.gz
SCons-ef6d3c2883fc43048e4eb5418eeb082d58b9d6cb.tar.bz2
Multi-level build dir with Object() and duplicate=0.
-rw-r--r--src/CHANGES.txt4
-rw-r--r--src/engine/SCons/Builder.py18
-rw-r--r--src/engine/SCons/BuilderTests.py21
-rw-r--r--src/engine/SCons/Node/FS.py4
-rw-r--r--src/engine/SCons/Node/FSTests.py12
-rw-r--r--test/SConscript-build_dir.py37
6 files changed, 85 insertions, 11 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 74b537c..9e9e774 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -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
diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py
index b7bc1a3..be1608d 100644
--- a/src/engine/SCons/Builder.py
+++ b/src/engine/SCons/Builder.py
@@ -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
diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py
index a7c2f12..f8d22ed 100644
--- a/src/engine/SCons/BuilderTests.py
+++ b/src/engine/SCons/BuilderTests.py
@@ -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
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index d12a504..249c8c6 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -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()
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index d651e1c..17d037d 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -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.
diff --git a/test/SConscript-build_dir.py b/test/SConscript-build_dir.py
index 165619a..d67fdac 100644
--- a/test/SConscript-build_dir.py
+++ b/test/SConscript-build_dir.py
@@ -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()