summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Node
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/SCons/Node')
-rw-r--r--src/engine/SCons/Node/FS.py28
-rw-r--r--src/engine/SCons/Node/FSTests.py43
-rw-r--r--src/engine/SCons/Node/NodeTests.py6
-rw-r--r--src/engine/SCons/Node/__init__.py11
4 files changed, 60 insertions, 28 deletions
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 7c4b383..46d72d7 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -48,6 +48,7 @@ import SCons.Action
import SCons.Errors
import SCons.Node
import SCons.Util
+import SCons.Sig.MD5
import SCons.Warnings
#
@@ -1311,20 +1312,18 @@ class File(Base):
except OSError:
pass
- def build(self):
- """Actually build the file.
-
- This overrides the base class build() method to check for the
- existence of derived files in a CacheDir before going ahead and
- building them.
+ def retrieve_from_cache(self):
+ """Try to retrieve the node's content from a cache
This method is called from multiple threads in a parallel build,
so only do thread safe stuff here. Do thread unsafe stuff in
built().
+
+ Returns true iff the node was successfully retrieved.
"""
b = self.is_derived()
if not b and not self.has_src_builder():
- return
+ return None
if b and self.fs.CachePath:
if self.fs.cache_show:
if CacheRetrieveSilent(self, None, None) == 0:
@@ -1336,10 +1335,10 @@ class File(Base):
for a in al:
action.show(a)
self._for_each_action(do_print)
- return
+ return 1
elif CacheRetrieve(self, None, None) == 0:
- return
- SCons.Node.Node.build(self)
+ return 1
+ return None
def built(self):
"""Called just after this node is sucessfully built."""
@@ -1509,10 +1508,13 @@ class File(Base):
bsig = self.get_bsig()
if bsig is None:
raise SCons.Errors.InternalError, "cachepath(%s) found a bsig of None" % self.path
- bsig = str(bsig)
- subdir = string.upper(bsig[0])
+ # Add the path to the cache signature, because multiple
+ # targets built by the same action will all have the same
+ # build signature, and we have to differentiate them somehow.
+ cache_sig = SCons.Sig.MD5.collect([bsig, self.path])
+ subdir = string.upper(cache_sig[0])
dir = os.path.join(self.fs.CachePath, subdir)
- return dir, os.path.join(dir, bsig)
+ return dir, os.path.join(dir, cache_sig)
return None, None
def target_from_source(self, prefix, suffix, splitext=SCons.Util.splitext):
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index 739d4e9..132e8f6 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -1528,7 +1528,8 @@ class CacheDirTestCase(unittest.TestCase):
self.retrieved = []
built_it = None
- f1.build()
+ r = f1.retrieve_from_cache()
+ assert r == 1, r
assert self.retrieved == [f1], self.retrieved
assert built_it is None, built_it
@@ -1536,9 +1537,10 @@ class CacheDirTestCase(unittest.TestCase):
self.retrieved = []
built_it = None
- f1.build()
+ r = f1.retrieve_from_cache()
+ assert r is None, r
assert self.retrieved == [f1], self.retrieved
- assert built_it, built_it
+ assert built_it is None, built_it
finally:
SCons.Node.FS.CacheRetrieve = save_CacheRetrieve
@@ -1554,7 +1556,8 @@ class CacheDirTestCase(unittest.TestCase):
self.retrieved = []
built_it = None
- f2.build()
+ r = f2.retrieve_from_cache()
+ assert r == 1, r
assert self.retrieved == [f2], self.retrieved
assert built_it is None, built_it
@@ -1562,9 +1565,10 @@ class CacheDirTestCase(unittest.TestCase):
self.retrieved = []
built_it = None
- f2.build()
+ r = f2.retrieve_from_cache()
+ assert r is None, r
assert self.retrieved == [f2], self.retrieved
- assert built_it, built_it
+ assert built_it is None, built_it
finally:
SCons.Node.FS.CacheRetrieveSilent = save_CacheRetrieveSilent
@@ -1602,12 +1606,19 @@ class CacheDirTestCase(unittest.TestCase):
# Verify how the cachepath() method determines the name
# of the file in cache.
- f5 = fs.File("cd.f5")
- f5.set_bsig('a_fake_bsig')
- cp = f5.cachepath()
- dirname = os.path.join('cache', 'A')
- filename = os.path.join(dirname, 'a_fake_bsig')
- assert cp == (dirname, filename), cp
+ def my_collect(list):
+ return list[0]
+ save_collect = SCons.Sig.MD5.collect
+ SCons.Sig.MD5.collect = my_collect
+ try:
+ f5 = fs.File("cd.f5")
+ f5.set_bsig('a_fake_bsig')
+ cp = f5.cachepath()
+ dirname = os.path.join('cache', 'A')
+ filename = os.path.join(dirname, 'a_fake_bsig')
+ assert cp == (dirname, filename), cp
+ finally:
+ SCons.Sig.MD5.collect = save_collect
# Verify that no bsig raises an InternalERror
f6 = fs.File("cd.f6")
@@ -1661,7 +1672,8 @@ class CacheDirTestCase(unittest.TestCase):
self.retrieved = []
built_it = None
- f8.build()
+ r = f8.retrieve_from_cache()
+ assert r == 1, r
assert self.retrieved == [f8], self.retrieved
assert built_it is None, built_it
@@ -1669,9 +1681,10 @@ class CacheDirTestCase(unittest.TestCase):
self.retrieved = []
built_it = None
- f8.build()
+ r = f8.retrieve_from_cache()
+ assert r is None, r
assert self.retrieved == [f8], self.retrieved
- assert built_it, built_it
+ assert built_it is None, built_it
finally:
SCons.Node.FS.CacheRetrieveSilent = save_CacheRetrieveSilent
diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py
index 08e4260..6b8c8ae 100644
--- a/src/engine/SCons/Node/NodeTests.py
+++ b/src/engine/SCons/Node/NodeTests.py
@@ -253,6 +253,12 @@ class NodeTestCase(unittest.TestCase):
assert str(act.built_target[0]) == "xxx", str(act.built_target[0])
assert act.built_source == ["yyy", "zzz"], act.built_source
+ def test_retrieve_from_cache(self):
+ """Test the base retrieve_from_cache() method"""
+ n = SCons.Node.Node()
+ r = n.retrieve_from_cache()
+ assert r == 0, r
+
def test_visited(self):
"""Test the base visited() method
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index 28264ce..0e453d2 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -176,6 +176,17 @@ class Node:
executor = self.get_executor()
executor(self, func)
+ def retrieve_from_cache(self):
+ """Try to retrieve the node's content from a cache
+
+ This method is called from multiple threads in a parallel build,
+ so only do thread safe stuff here. Do thread unsafe stuff in
+ built().
+
+ Returns true iff the node was successfully retrieved.
+ """
+ return 0
+
def build(self):
"""Actually build the node.