summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/CHANGES.txt5
-rw-r--r--src/engine/SCons/Node/FS.py40
-rw-r--r--src/engine/SCons/Node/FSTests.py7
-rw-r--r--src/engine/SCons/Node/NodeTests.py60
-rw-r--r--src/engine/SCons/Node/__init__.py23
-rw-r--r--src/engine/SCons/Taskmaster.py5
-rw-r--r--src/engine/SCons/TaskmasterTests.py11
-rw-r--r--test/Alias.py11
-rw-r--r--test/Options.py4
9 files changed, 138 insertions, 28 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index c73a6b1..14db4fb 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -100,6 +100,11 @@ RELEASE 0.12 - XXX
- Avoid partial copies of built files in a CacheDir() by copying
to a temporary file and renaming.
+ From Anthony Roach:
+
+ - Fix incorrect dependency-cycle errors when an Aliased source doesn't
+ exist.
+
RELEASE 0.11 - Tue, 11 Feb 2003 05:24:33 -0600
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index d6b7b53..0afc3d8 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -892,6 +892,9 @@ class Dir(Entry):
"""Return a fixed "contents" value of a directory."""
return ''
+ def prepare(self):
+ pass
+
def current(self, calc):
"""If all of our children were up-to-date, then this
directory was up-to-date, too."""
@@ -971,7 +974,6 @@ class File(Entry):
def _morph(self):
"""Turn a file system node into a File object."""
- self.linked = 0
self.scanner_paths = {}
self.found_includes = {}
if not hasattr(self, '_local'):
@@ -1196,28 +1198,24 @@ class File(Entry):
def prepare(self):
"""Prepare for this file to be created."""
- def missing(node):
- return not node.has_builder() and not node.linked and not node.rexists() and not node.has_src_builder()
- missing_sources = filter(missing, self.children())
- if missing_sources:
- desc = "No Builder for target `%s', needed by `%s'." % (missing_sources[0], self)
- raise SCons.Errors.StopError, desc
+ SCons.Node.Node.prepare(self)
- if self.exists():
- if self.has_builder() and not self.precious:
+ if self.get_state() != SCons.Node.up_to_date:
+ if self.exists():
+ if self.has_builder() and not self.precious:
+ try:
+ Unlink(self, None, None)
+ except OSError, e:
+ raise SCons.Errors.BuildError(node = self,
+ errstr = e.strerror)
+ if hasattr(self, '_exists'):
+ delattr(self, '_exists')
+ else:
try:
- Unlink(self, None, None)
- except OSError, e:
- raise SCons.Errors.BuildError(node = self,
- errstr = e.strerror)
- if hasattr(self, '_exists'):
- delattr(self, '_exists')
- else:
- try:
- self._createDir()
- except SCons.Errors.StopError, drive:
- desc = "No drive `%s' for target `%s'." % (drive, self)
- raise SCons.Errors.StopError, desc
+ self._createDir()
+ except SCons.Errors.StopError, drive:
+ desc = "No drive `%s' for target `%s'." % (drive, self)
+ raise SCons.Errors.StopError, desc
def remove(self):
"""Remove this file."""
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index 11146eb..dd04fe4 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -1267,11 +1267,18 @@ class prepareTestCase(unittest.TestCase):
file = fs.File(os.path.join("new_dir", "xyz"))
try:
+ file.set_state(SCons.Node.up_to_date)
+ file.prepare()
+ assert dir_made == [], dir_made
+ file.set_state(0)
file.prepare()
assert dir_made[0].path == "new_dir", dir_made[0].path
finally:
SCons.Node.FS.Mkdir = save_Mkdir
+ dir = fs.Dir("dir")
+ dir.prepare()
+
class get_actionsTestCase(unittest.TestCase):
def runTest(self):
"""Test the Dir's get_action() method"""
diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py
index f282860..9da74d3 100644
--- a/src/engine/SCons/Node/NodeTests.py
+++ b/src/engine/SCons/Node/NodeTests.py
@@ -377,6 +377,66 @@ class NodeTestCase(unittest.TestCase):
node.set_precious(7)
assert node.precious == 7
+ def test_exists(self):
+ """Test evaluating whether a Node exists.
+ """
+ node = SCons.Node.Node()
+ e = node.exists()
+ assert e == 1, e
+
+ def test_exists(self):
+ """Test evaluating whether a Node exists locally or in a repository.
+ """
+ node = SCons.Node.Node()
+ e = node.rexists()
+ assert e == 1, e
+
+ class MyNode(SCons.Node.Node):
+ def exists(self):
+ return 'xyz'
+
+ node = MyNode()
+ e = node.rexists()
+ assert e == 'xyz', e
+
+ def test_prepare(self):
+ """Test preparing a node to be built
+ """
+ node = SCons.Node.Node()
+
+ n1 = SCons.Node.Node()
+ n1.builder_set(Builder())
+ node.implicit = []
+ node._add_child(node.implicit, [n1])
+
+ node.prepare() # should not throw an exception
+
+ n2 = SCons.Node.Node()
+ n2.linked = 1
+ node.implicit = []
+ node._add_child(node.implicit, [n2])
+
+ node.prepare() # should not throw an exception
+
+ n3 = SCons.Node.Node()
+ node.implicit = []
+ node._add_child(node.implicit, [n3])
+
+ node.prepare() # should not throw an exception
+
+ class MyNode(SCons.Node.Node):
+ def rexists(self):
+ return None
+ n4 = MyNode()
+ node.implicit = []
+ node._add_child(node.implicit, [n4])
+ exc_caught = 0
+ try:
+ node.prepare()
+ except SCons.Errors.StopError:
+ exc_caught = 1
+ assert exc_caught, "did not catch expected StopError"
+
def test_add_dependency(self):
"""Test adding dependencies to a Node's list.
"""
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index 222cd1f..c458026 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -115,6 +115,7 @@ class Node:
self.side_effects = [] # the side effects of building this target
self.pre_actions = []
self.post_actions = []
+ self.linked = 0 # is this node linked to the build directory?
# Let the interface in which the build engine is embedded
# annotate this Node with its own info (like a description of
@@ -451,9 +452,27 @@ class Node:
"""Set the Node's precious value."""
self.precious = precious
+ def exists(self):
+ """Does this node exists?"""
+ # All node exist by default:
+ return 1
+
+ def rexists(self):
+ """Does this node exist locally or in a repositiory?"""
+ # There are no repositories by default:
+ return self.exists()
+
def prepare(self):
- """Prepare for this Node to be created: no-op by default."""
- pass
+ """Prepare for this Node to be created.
+ The default implemenation checks that all children either exist
+ or are derived.
+ """
+ def missing(node):
+ return not node.is_derived() and not node.linked and not node.rexists()
+ missing_sources = filter(missing, self.children())
+ if missing_sources:
+ desc = "No Builder for target `%s', needed by `%s'." % (missing_sources[0], self)
+ raise SCons.Errors.StopError, desc
def remove(self):
"""Remove this Node: no-op by default."""
diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py
index bc53024..b58e09f 100644
--- a/src/engine/SCons/Taskmaster.py
+++ b/src/engine/SCons/Taskmaster.py
@@ -78,9 +78,8 @@ class Task:
self.display(self.tm.message)
self.tm.message = None
- if self.targets[0].get_state() != SCons.Node.up_to_date:
- for t in self.targets:
- t.prepare()
+ for t in self.targets:
+ t.prepare()
def execute(self):
"""Called to execute the task.
diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py
index 89c53c7..3616370 100644
--- a/src/engine/SCons/TaskmasterTests.py
+++ b/src/engine/SCons/TaskmasterTests.py
@@ -551,6 +551,17 @@ class TaskmasterTestCase(unittest.TestCase):
assert n1.prepared
assert n2.prepared
+ n3 = Node("n3")
+ n4 = Node("n4")
+ tm = SCons.Taskmaster.Taskmaster([n3, n4])
+ t = tm.next_task()
+ # More bogus reaching in and setting the targets.
+ n3.set_state(SCons.Node.up_to_date)
+ t.targets = [n3, n4]
+ t.prepare()
+ assert n3.prepared
+ assert n4.prepared
+
# If the Node has had an exception recorded while it was getting
# prepared, then prepare() should raise that exception.
class MyException(Exception):
diff --git a/test/Alias.py b/test/Alias.py
index c966933..f965071 100644
--- a/test/Alias.py
+++ b/test/Alias.py
@@ -155,5 +155,16 @@ test.run(arguments = 'f1.out',
test.up_to_date(arguments = 'f1.out')
+test.write('SConstruct', """
+env=Environment()
+SetBuildSignatureType('content')
+env.Alias('C', 'D')
+env.Alias('B', 'C')
+env.Alias('A', 'B')
+""")
+
+test.run(arguments='A',
+ stderr="scons: \\*\\*\\* No Builder for target `D', needed by `C'. Stop.\n",
+ status=2)
test.pass_test()
diff --git a/test/Options.py b/test/Options.py
index a34e5ca..4f979df 100644
--- a/test/Options.py
+++ b/test/Options.py
@@ -33,7 +33,7 @@ test.write('SConstruct', """
env = Environment()
print env['CC']
print env['CCFLAGS']
-Default(env.Alias('dummy'))
+Default(env.Alias('dummy', None))
""")
test.run()
cc, ccflags = string.split(test.stdout(), '\n')[1:3]
@@ -87,7 +87,7 @@ opts = Options()
opts.Update(env)
assert env['RELEASE_BUILD'] == r
-Default(env.Alias('dummy'))
+Default(env.Alias('dummy', None))
""")