From 813976940844198600a08144299f85a792480211 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Sat, 1 May 2004 19:21:11 +0000 Subject: Fix use of timestamps with --implicit-cache. (Anthony Roach) --- doc/man/scons.1 | 5 +- src/CHANGES.txt | 4 ++ src/RELEASE.txt | 10 ++- src/engine/SCons/Node/__init__.py | 6 +- src/engine/SCons/Scanner/ScannerTests.py | 9 ++- src/engine/SCons/Scanner/__init__.py | 6 +- src/engine/SCons/Sig/__init__.py | 3 + test/SourceSignatures.py | 114 +++++++++++++++++++++++++++++++ test/scan-once.py | 2 +- 9 files changed, 144 insertions(+), 15 deletions(-) diff --git a/doc/man/scons.1 b/doc/man/scons.1 index ba4e690..bb0bbd3 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -7156,8 +7156,9 @@ and turn it into the appropriate class of Node to be returned by this Scanner object. .IP scan_check -An optional Python function that takes a Node (file) -as an argument and returns whether the +An optional Python function that takes two arguments, +a Node (file) and a construction environment, +and returns whether the Node should, in fact, be scanned for dependencies. This check can be used to eliminate unnecessary diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 1d54390..3e7fa91 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -120,6 +120,10 @@ RELEASE 0.96 - XXX - Fix a bug introduced in building shared libraries under MinGW. + From Anthony Roach: + + - Fix use of the --implicit-cache option with timestamp signatures. + From sam th: - Allow SConf.CheckLib() to search a list of libraries, like the diff --git a/src/RELEASE.txt b/src/RELEASE.txt index c7b46fd..e651afb 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -37,9 +37,13 @@ RELEASE 0.96 - XXX import anydbm SConsignFile('.sconsign_file_name', anydbm) - - The internal Scanner.add_skey() method longer works for the default - scanners, which now use construction variables to hold their lists - of suffixes. If you had a custom Tool specification that was + - The scan_check function that can be supplied to a custom Scanner now + must take two arguments, the Node to be checked and a construction + environment. It previously only used the Node as an argument. + + - The internal Scanner.add_skey() method no longer works for the + default scanners, which now use construction variables to hold their + lists of suffixes. If you had a custom Tool specification that was reaching into the internals in this way to add a suffix to one of the following scanner, you must now add the suffix to a construction environment through which you plan to call the scanner, as follows: diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index ceac5ca..9897d1a 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -390,12 +390,14 @@ class Node: if not self.has_builder(): return + build_env = self.get_build_env() + if implicit_cache and not implicit_deps_changed: implicit = self.get_stored_implicit() if implicit is not None: implicit = map(self.implicit_factory, implicit) self._add_child(self.implicit, self.implicit_dict, implicit) - calc = SCons.Sig.default_calc + calc = build_env.get_calculator() if implicit_deps_unchanged or calc.current(self, calc.bsig(self)): return else: @@ -407,8 +409,6 @@ class Node: self._children_reset() self.del_binfo() - build_env = self.get_build_env() - for child in self.children(scan=0): scanner = child.source_scanner if scanner: diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py index 91a0f8c..4e662a2 100644 --- a/src/engine/SCons/Scanner/ScannerTests.py +++ b/src/engine/SCons/Scanner/ScannerTests.py @@ -26,6 +26,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import sys import unittest import UserDict +import SCons.Sig import SCons.Scanner @@ -45,6 +46,8 @@ class DummyEnvironment(UserDict.UserDict): if type(path) != type([]): path = [path] return map(self.subst, path) + def get_calculator(self): + return SCons.Sig.default_calc class FindPathDirsTestCase(unittest.TestCase): def test_FindPathDirs(self): @@ -61,7 +64,7 @@ class FindPathDirsTestCase(unittest.TestCase): assert result == ('xxx', 'foo'), result class ScannerTestCase(unittest.TestCase): - + def func(self, filename, env, target, *args): self.filename = filename self.env = env @@ -69,7 +72,7 @@ class ScannerTestCase(unittest.TestCase): if len(args) > 0: self.arg = args[0] - + return self.deps def test(self, scanner, env, filename, deps, *args): @@ -148,7 +151,7 @@ class ScannerTestCase(unittest.TestCase): """Test the Scanner.Base class scan_check() method""" def my_scan(filename, env, target, *args): return [] - def check(node, s=self): + def check(node, env, s=self): s.checked[node] = 1 return 1 env = DummyEnvironment() diff --git a/src/engine/SCons/Scanner/__init__.py b/src/engine/SCons/Scanner/__init__.py index 102849d..8f6c9e6 100644 --- a/src/engine/SCons/Scanner/__init__.py +++ b/src/engine/SCons/Scanner/__init__.py @@ -158,7 +158,7 @@ class Base: environment that will be passed to the scanner function. A list of direct dependency nodes for the specified node will be returned. """ - if self.scan_check and not self.scan_check(node): + if self.scan_check and not self.scan_check(node, env): return [] if not self.argument is _null: @@ -199,8 +199,8 @@ class Current(Base): """ def __init__(self, *args, **kw): - def current_check(node): - c = not node.has_builder() or node.current(SCons.Sig.default_calc) + def current_check(node, env): + c = not node.has_builder() or node.current(env.get_calculator()) return c kw['scan_check'] = current_check apply(Base.__init__, (self,) + args, kw) diff --git a/src/engine/SCons/Sig/__init__.py b/src/engine/SCons/Sig/__init__.py index 6bdfe09..dac3f6c 100644 --- a/src/engine/SCons/Sig/__init__.py +++ b/src/engine/SCons/Sig/__init__.py @@ -458,6 +458,9 @@ class Calculator: oldtime, oldbsig, oldcsig = node.get_prevsiginfo() + if type(newsig) != type(oldbsig): + return 0 + if not node.has_builder() and node.get_timestamp() == oldtime: return 1 diff --git a/test/SourceSignatures.py b/test/SourceSignatures.py index e982fbe..10dfb29 100644 --- a/test/SourceSignatures.py +++ b/test/SourceSignatures.py @@ -27,6 +27,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import imp import os import os.path +import time import TestSCons @@ -172,4 +173,117 @@ scons: `f8.out' is up to date. test.up_to_date(arguments = 'f5.out f6.out f7.out f8.out') +# Ensure that switching signature types causes a rebuild: +test.write('SConstruct', """ +SourceSignatures('MD5') + +def build(env, target, source): + open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) +B = Builder(action = build) +env = Environment(BUILDERS = { 'B' : B }) +env.B(target = 'switch.out', source = 'switch.in') +""") + +test.write('switch.in', "switch.in\n") + +test.run(arguments = 'switch.out', + stdout = test.wrap_stdout("""\ +build("switch.out", "switch.in") +""")) + +test.up_to_date(arguments = 'switch.out') + +test.write('SConstruct', """ +SourceSignatures('timestamp') + +def build(env, target, source): + open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) +B = Builder(action = build) +env = Environment(BUILDERS = { 'B' : B }) +env.B(target = 'switch.out', source = 'switch.in') +""") + +test.run(arguments = 'switch.out', + stdout = test.wrap_stdout("""\ +build("switch.out", "switch.in") +""")) + +test.up_to_date(arguments = 'switch.out') + +test.write('SConstruct', """ +SourceSignatures('MD5') + +def build(env, target, source): + open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) +B = Builder(action = build) +env = Environment(BUILDERS = { 'B' : B }) +env.B(target = 'switch.out', source = 'switch.in') +""") + +test.run(arguments = 'switch.out', + stdout = test.wrap_stdout("""\ +build("switch.out", "switch.in") +""")) + +test.up_to_date(arguments = 'switch.out') + +test.write('switch.in', "switch.in 2\n") + +test.run(arguments = 'switch.out', + stdout = test.wrap_stdout("""\ +build("switch.out", "switch.in") +""")) + + +# Test both implicit_cache and timestamp signatures at the same time: +test.write('SConstruct', """ +SetOption('implicit_cache', 1) +SourceSignatures('timestamp') + +def build(env, target, source): + open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read()) +B = Builder(action = build) +env = Environment(BUILDERS = { 'B' : B }) +env.B(target = 'both.out', source = 'both.in') +""") + +test.write('both.in', "both.in 1\n") + +test.run(arguments = 'both.out', + stdout = test.wrap_stdout("""\ +build("both.out", "both.in") +""")) + +time.sleep(2) + +test.write('both.in', "both.in 2\n") + +test.run(arguments = 'both.out', + stdout = test.wrap_stdout("""\ +build("both.out", "both.in") +""")) + +time.sleep(2) + +test.write('both.in', "both.in 3\n") + +test.run(arguments = 'both.out', + stdout = test.wrap_stdout("""\ +build("both.out", "both.in") +""")) + +time.sleep(2) + +test.write('both.in', "both.in 4\n") + +test.run(arguments = 'both.out', + stdout = test.wrap_stdout("""\ +build("both.out", "both.in") +""")) + +time.sleep(2) + + +test.up_to_date(arguments = 'both.out') + test.pass_test() diff --git a/test/scan-once.py b/test/scan-once.py index cfc4a25..52b4505 100644 --- a/test/scan-once.py +++ b/test/scan-once.py @@ -62,7 +62,7 @@ def scan(node, env, envkey, arg): print 'XScanner: node =', os.path.split(str(node))[1] return [] -def exists_check(node): +def exists_check(node, env): return os.path.exists(str(node)) XScanner = Scanner(name = 'XScanner', -- cgit v0.12