summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Node
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2004-06-25 04:10:24 (GMT)
committerSteven Knight <knight@baldmt.com>2004-06-25 04:10:24 (GMT)
commitc2bb425dcb2907f50a485469b69e83884fed6fb4 (patch)
treeeec003c4e6e332651cf70c8896612b17b7acb290 /src/engine/SCons/Node
parent5f1ca10deda557947d8669098fdce1852b38b81f (diff)
downloadSCons-c2bb425dcb2907f50a485469b69e83884fed6fb4.zip
SCons-c2bb425dcb2907f50a485469b69e83884fed6fb4.tar.gz
SCons-c2bb425dcb2907f50a485469b69e83884fed6fb4.tar.bz2
Officially support target_factory and source_factory when creating a Builder.
Diffstat (limited to 'src/engine/SCons/Node')
-rw-r--r--src/engine/SCons/Node/FS.py48
-rw-r--r--src/engine/SCons/Node/FSTests.py82
-rw-r--r--src/engine/SCons/Node/NodeTests.py8
-rw-r--r--src/engine/SCons/Node/__init__.py2
4 files changed, 85 insertions, 55 deletions
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 2f115c9..52a75ce 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -176,10 +176,24 @@ Unlink = SCons.Action.Action(UnlinkFunc, None)
def MkdirFunc(target, source, env):
t = target[0]
- t.fs.mkdir(t.path)
+ if not t.fs.exists(t.path):
+ t.fs.mkdir(t.path)
return 0
-Mkdir = SCons.Action.Action(MkdirFunc, None)
+Mkdir = SCons.Action.Action(MkdirFunc, None, presub=None)
+
+MkdirBuilder = None
+
+def get_MkdirBuilder():
+ global MkdirBuilder
+ if MkdirBuilder is None:
+ import SCons.Builder
+ import SCons.Defaults
+ env = SCons.Defaults.DefaultEnvironment()
+ MkdirBuilder = SCons.Builder.Builder(action = Mkdir,
+ env = env,
+ explain = None)
+ return MkdirBuilder
def CacheRetrieveFunc(target, source, env):
t = target[0]
@@ -1118,7 +1132,7 @@ class Dir(Base):
self.entries['.'] = self
self.entries['..'] = self.dir
self.cwd = self
- self.builder = 1
+ self.builder = get_MkdirBuilder()
self.searched = 0
self._sconsign = None
self.build_dirs = []
@@ -1238,7 +1252,13 @@ class Dir(Base):
def build(self, **kw):
"""A null "builder" for directories."""
- pass
+ global MkdirBuilder
+ if not self.builder is MkdirBuilder:
+ apply(SCons.Node.Node.build, [self,], kw)
+
+ def multiple_side_effect_has_builder(self):
+ global MkdirBuilder
+ return not self.builder is MkdirBuilder and self.has_builder()
def alter_targets(self):
"""Return any corresponding targets in a build directory.
@@ -1262,6 +1282,8 @@ class Dir(Base):
def current(self, calc=None):
"""If all of our children were up-to-date, then this
directory was up-to-date, too."""
+ if not self.builder is MkdirBuilder and not self.exists():
+ return 0
state = 0
for kid in self.children():
s = kid.get_state()
@@ -1299,16 +1321,6 @@ class Dir(Base):
return self.srcdir
return Base.srcnode(self)
- def get_executor(self, create=1):
- """Fetch the action executor for this node. Create one if
- there isn't already one, and requested to do so."""
- try:
- executor = self.executor
- except AttributeError:
- executor = DummyExecutor()
- self.executor = executor
- return executor
-
def get_timestamp(self):
"""Return the latest timestamp from among our children"""
stamp = 0
@@ -1482,8 +1494,12 @@ class File(Base):
listDirs.reverse()
for dirnode in listDirs:
try:
- Mkdir(dirnode, [], None)
- # The Mkdir() action may or may not have actually
+ # Don't call dirnode.build(), call the base Node method
+ # directly because we definitely *must* create this
+ # directory. The dirnode.build() method will suppress
+ # the build if it's the default builder.
+ SCons.Node.Node.build(dirnode)
+ # The build() action may or may not have actually
# created the directory, depending on whether the -n
# option was used or not. Delete the _exists and
# _rexists attributes so they can be reevaluated.
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index d4137c1..bbc64ef 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -281,8 +281,33 @@ class BuildDirTestCase(unittest.TestCase):
f8.rfile().path
# Verify the Mkdir and Link actions are called
+ d9 = fs.Dir('build/var2/new_dir')
f9 = fs.File('build/var2/new_dir/test9.out')
+ class MkdirAction(Action):
+ def __init__(self, dir_made):
+ self.dir_made = dir_made
+ def __call__(self, target, source, env, errfunc):
+ self.dir_made.extend(target)
+
+ save_Link = SCons.Node.FS.Link
+ link_made = []
+ def link_func(target, source, env, link_made=link_made):
+ link_made.append(target)
+ SCons.Node.FS.Link = link_func
+
+ try:
+ dir_made = []
+ d9.builder = Builder(fs.Dir, action=MkdirAction(dir_made))
+ f9.exists()
+ expect = os.path.join('build', 'var2', 'new_dir')
+ assert dir_made[0].path == expect, dir_made[0].path
+ expect = os.path.join('build', 'var2', 'new_dir', 'test9.out')
+ assert link_made[0].path == expect, link_made[0].path
+ assert f9.linked
+ finally:
+ SCons.Node.FS.Link = save_Link
+
# Test for an interesting pathological case...we have a source
# file in a build path, but not in a source path. This can
# happen if you switch from duplicate=1 to duplicate=0, then
@@ -312,29 +337,6 @@ class BuildDirTestCase(unittest.TestCase):
var2_new_dir = os.path.normpath('build/var2/new_dir')
assert bdt == [var1_new_dir, var2_new_dir], bdt
- save_Mkdir = SCons.Node.FS.Mkdir
- dir_made = []
- def mkdir_func(target, source, env, dir_made=dir_made):
- dir_made.append(target)
- SCons.Node.FS.Mkdir = mkdir_func
-
- save_Link = SCons.Node.FS.Link
- link_made = []
- def link_func(target, source, env, link_made=link_made):
- link_made.append(target)
- SCons.Node.FS.Link = link_func
-
- try:
- f9.exists()
- expect = os.path.join('build', 'var2', 'new_dir')
- assert dir_made[0].path == expect, dir_made[0].path
- expect = os.path.join('build', 'var2', 'new_dir', 'test9.out')
- assert link_made[0].path == expect, link_made[0].path
- assert f9.linked
- finally:
- SCons.Node.FS.Mkdir = save_Mkdir
- SCons.Node.FS.Link = save_Link
-
# Test that an IOError trying to Link a src file
# into a BuildDir ends up throwing a StopError.
fIO = fs.File("build/var2/IOError")
@@ -754,7 +756,7 @@ class FSTestCase(unittest.TestCase):
d1.builder_set(Builder(fs.File))
d1.env_set(Environment())
d1.build()
- assert not built_it
+ assert built_it
built_it = None
assert not built_it
@@ -1497,22 +1499,24 @@ class prepareTestCase(unittest.TestCase):
exc_caught = 1
assert exc_caught, "Should have caught a StopError."
- save_Mkdir = SCons.Node.FS.Mkdir
- dir_made = []
- def mkdir_func(target, source, env, dir_made=dir_made):
- dir_made.append(target)
- SCons.Node.FS.Mkdir = mkdir_func
+ class MkdirAction(Action):
+ def __init__(self, dir_made):
+ self.dir_made = dir_made
+ def __call__(self, target, source, env, errfunc):
+ self.dir_made.extend(target)
- 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_made = []
+ new_dir = fs.Dir("new_dir")
+ new_dir.builder = Builder(fs.Dir, action=MkdirAction(dir_made))
+ xyz = fs.File(os.path.join("new_dir", "xyz"))
+
+ xyz.set_state(SCons.Node.up_to_date)
+ xyz.prepare()
+ assert dir_made == [], dir_made
+ xyz.set_state(0)
+ xyz.prepare()
+ print "dir_made[0] =", dir_made[0]
+ assert dir_made[0].path == "new_dir", dir_made[0]
dir = fs.Dir("dir")
dir.prepare()
diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py
index cd7aa18..72ddd74 100644
--- a/src/engine/SCons/Node/NodeTests.py
+++ b/src/engine/SCons/Node/NodeTests.py
@@ -304,6 +304,14 @@ class NodeTestCase(unittest.TestCase):
n1.builder_set(Builder())
assert n1.has_builder() == 1
+ def test_multiple_side_effect_has_builder(self):
+ """Test the multiple_side_effect_has_builder() method
+ """
+ n1 = SCons.Node.Node()
+ assert n1.multiple_side_effect_has_builder() == 0
+ n1.builder_set(Builder())
+ assert n1.multiple_side_effect_has_builder() == 1
+
def test_is_derived(self):
"""Test the is_derived() method
"""
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index 51e6628..603762e 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -299,6 +299,8 @@ class Node:
b = self.builder
return not b is None
+ multiple_side_effect_has_builder = has_builder
+
def is_derived(self):
"""
Returns true iff this node is derived (i.e. built).