From 721c0b5439329cce1a68d44c0e58204a83d9d354 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Fri, 12 Jul 2002 06:17:59 +0000 Subject: Added --implicit-deps-unchanged option. Added GetLaunchDir() function. Added SetBuildSignatureType() function. (Anthony Roach) --- doc/man/scons.1 | 7 ++ src/CHANGES.txt | 6 ++ src/engine/SCons/Node/__init__.py | 5 +- src/engine/SCons/Script/SConscript.py | 15 +++++ src/engine/SCons/Script/__init__.py | 9 +++ src/engine/SCons/Sig/__init__.py | 13 +++- test/SetBuildSignatureType.py | 122 ++++++++++++++++++++++++++++++++++ test/option--U.py | 6 ++ test/option--implicit-cache.py | 31 +++++++++ 9 files changed, 210 insertions(+), 4 deletions(-) create mode 100644 test/SetBuildSignatureType.py diff --git a/doc/man/scons.1 b/doc/man/scons.1 index 8c02eff..8761335 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -400,6 +400,13 @@ dependency is added earlier in the implicit dependency search path (e.g. CPPPATH) than a current implicit dependency with the same name. .TP +--implicit-deps-unchanged +Force SCons to ignore changes in the implicit dependencies. +This causes cached implicit dependencies to always be used. +This implies +.BR --implicit-cache . + +.TP .RI -j " N" ", --jobs=" N Specifies the number of jobs (commands) to run simultaneously. If there is more than one diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 8cc8060..6b0c79c 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -135,6 +135,12 @@ RELEASE 0.08 - suffix computation, code cleanup in MultiStepBuilder.__call__(), and replicating some logic in scons_subst(). + - Add a --implicit-deps-unchanged option. + + - Add a GetLaunchDir() function. + + - Add a SetBuildSignatureType() function. + From Zed Shaw: - Add an Append() method to Environments, to append values to diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 1e23198..bc0539e 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -57,6 +57,9 @@ stack = 6 # nodes that are in the current Taskmaster execution stack # controls whether implicit depedencies are cached: implicit_cache = 0 +# controls whether implicit dep changes are ignored: +implicit_deps_unchanged = 0 + class Node: """The base Node class, for entities that we know how to build, or use to build other Nodes. @@ -203,7 +206,7 @@ class Node: implicit = map(self.builder.source_factory, implicit) self._add_child(self.implicit, implicit) calc = SCons.Sig.default_calc - if calc.current(self, calc.bsig(self)): + if implicit_deps_unchanged or calc.current(self, calc.bsig(self)): return else: # one of this node's sources has changed, so diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index 0f65732..48c4046 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -39,6 +39,7 @@ import SCons.Node.FS import SCons.Platform import SCons.Tool import SCons.Util +import SCons.Sig import os import os.path @@ -48,6 +49,7 @@ import sys default_targets = [] print_help = 0 arguments = {} +launch_dir = os.path.abspath(os.curdir) # global exports set by Export(): global_exports = {} @@ -243,6 +245,17 @@ def Import(*vars): except KeyError,x: raise SCons.Errors.UserError, "Import of non-existant variable '%s'"%x +def GetLaunchDir(): + return launch_dir + +def SetBuildSignatureType(type): + if type == 'build': + SCons.Sig.build_signature = 1 + elif type == 'content': + SCons.Sig.build_signature = 0 + else: + raise SCons.Errors.UserError, "Unknown build signature type '%s'"%type + def BuildDefaultGlobals(): """ Create a dictionary containing all the default globals for @@ -281,4 +294,6 @@ def BuildDefaultGlobals(): globals['Split'] = SCons.Util.Split globals['Tool'] = SCons.Tool.Tool globals['WhereIs'] = SCons.Util.WhereIs + globals['GetLaunchDir'] = GetLaunchDir + globals['SetBuildSignatureType'] = SetBuildSignatureType return globals diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 6f87353..1d53fed 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -550,6 +550,15 @@ def options_init(): long = ['implicit-cache'], help = "Cache implicit dependencies") + def opt_implicit_deps_unchanged(opt, arg): + import SCons.Node + SCons.Node.implicit_cache = 1 + SCons.Node.implicit_deps_unchanged = 1 + + Option(func = opt_implicit_deps_unchanged, + long = ['implicit-deps-unchanged'], + help = "Ignore changes in implicit deps.") + def opt_j(opt, arg): global num_jobs try: diff --git a/src/engine/SCons/Sig/__init__.py b/src/engine/SCons/Sig/__init__.py index 553c9ce..0e629fb 100644 --- a/src/engine/SCons/Sig/__init__.py +++ b/src/engine/SCons/Sig/__init__.py @@ -38,6 +38,10 @@ import time #XXX Get rid of the global array so this becomes re-entrant. sig_files = [] +# 1 means use build signature for derived source files +# 0 means use content signature for derived source files +build_signature = 1 + def write(): global sig_files for sig_file in sig_files: @@ -359,13 +363,13 @@ class Calculator: def get_signature(self, node): """ - Get the appropriate signature for a node. + Get the appropriate build signature for a node. node - the node returns - the signature or None if the signature could not be computed. - This method does not store the signature in the node and + This method does not store the signature in the node or in the .sconsign file. """ @@ -374,7 +378,10 @@ class Calculator: # directory) so bail right away. return None elif node.builder: - return self.bsig(node) + if build_signature: + return self.bsig(node) + else: + return self.csig(node) elif not node.exists(): return None else: diff --git a/test/SetBuildSignatureType.py b/test/SetBuildSignatureType.py new file mode 100644 index 0000000..39534dd --- /dev/null +++ b/test/SetBuildSignatureType.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python +# +# Copyright (c) 2001, 2002 Steven Knight +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +env = Environment() + +def copy1(env, source, target): + print 'copy %s -> %s'%(str(source[0]), str(target[0])) + open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) + +def copy2(env, source, target): + return copy1(env, source, target) + +env['BUILDERS']['Copy1'] = Builder(action=copy1) +env['BUILDERS']['Copy2'] = Builder(action=copy2) + +env.Copy2('foo.out', 'foo.in') +env.Copy1('foo.out.out', 'foo.out') + +SetBuildSignatureType('content') +""") + +test.write('foo.in', 'foo.in') + +test.run(arguments='foo.out.out', stdout='copy foo.in -> foo.out\ncopy foo.out -> foo.out.out\n') + +test.run(arguments='foo.out.out', stdout='scons: "foo.out.out" is up to date.\n') + +test.write('SConstruct', """ +env = Environment() + +def copy1(env, source, target): + print 'copy %s -> %s'%(str(source[0]), str(target[0])) + open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) + +def copy2(env, source, target): + # added this line + return copy1(env, source, target) + +env['BUILDERS']['Copy1'] = Builder(action=copy1) +env['BUILDERS']['Copy2'] = Builder(action=copy2) + +env.Copy2('foo.out', 'foo.in') +env.Copy1('foo.out.out', 'foo.out') + +SetBuildSignatureType('content') +""") + +test.run(arguments='foo.out.out', stdout='copy foo.in -> foo.out\nscons: "foo.out.out" is up to date.\n') + +test.write('SConstruct', """ +env = Environment() + +def copy1(env, source, target): + print 'copy %s -> %s'%(str(source[0]), str(target[0])) + open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) + +def copy2(env, source, target): + # added this line + return copy1(env, source, target) + +env['BUILDERS']['Copy1'] = Builder(action=copy1) +env['BUILDERS']['Copy2'] = Builder(action=copy2) + +env.Copy2('foo.out', 'foo.in') +env.Copy1('foo.out.out', 'foo.out') + +SetBuildSignatureType('build') +""") + +test.run(arguments='foo.out.out', stdout='copy foo.out -> foo.out.out\n') + +test.write('SConstruct', """ +env = Environment() + +def copy1(env, source, target): + print 'copy %s -> %s'%(str(source[0]), str(target[0])) + open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read()) + +def copy2(env, source, target): + return copy1(env, source, target) + +env['BUILDERS']['Copy1'] = Builder(action=copy1) +env['BUILDERS']['Copy2'] = Builder(action=copy2) + +env.Copy2('foo.out', 'foo.in') +env.Copy1('foo.out.out', 'foo.out') + +SetBuildSignatureType('build') +""") + +test.run(arguments='foo.out.out', stdout='copy foo.in -> foo.out\ncopy foo.out -> foo.out.out\n') + + +test.pass_test() diff --git a/test/option--U.py b/test/option--U.py index a683a8d..1facab8 100644 --- a/test/option--U.py +++ b/test/option--U.py @@ -54,6 +54,7 @@ Default(env.B(target = 'sub3/baz.out', source = 'sub3/baz.in')) BuildDir('sub2b', 'sub2') SConscript('sub2b/SConscript') Default(env.B(target = 'sub2/xxx.out', source = 'xxx.in')) +SConscript('SConscript') """ % python) test.write(['sub2', 'SConscript'], """ @@ -70,6 +71,7 @@ test.write(['sub2', 'bar.in'], "sub2/bar.in\n") test.write(['sub3', 'baz.in'], "sub3/baz.in\n") test.write('xxx.in', "xxx.in\n") +test.write('SConscript', """assert GetLaunchDir() == '%s'"""%test.workpath('sub1')) test.run(arguments = '-U foo.out', chdir = 'sub1') test.fail_test(not os.path.exists(test.workpath('sub1', 'foo.out'))) @@ -81,6 +83,7 @@ test.fail_test(os.path.exists(test.workpath('sub2/xxx.out'))) test.unlink(['sub1', 'foo.out']) +test.write('SConscript', """assert GetLaunchDir() == '%s'"""%test.workpath('sub1')) test.run(arguments = '-U', chdir = 'sub1') test.fail_test(os.path.exists(test.workpath('sub1', 'foo.out'))) test.fail_test(os.path.exists(test.workpath('sub2', 'bar.out'))) @@ -89,6 +92,7 @@ test.fail_test(os.path.exists(test.workpath('sub3', 'baz.out'))) test.fail_test(os.path.exists(test.workpath('bar.out'))) test.fail_test(os.path.exists(test.workpath('sub2/xxx.out'))) +test.write('SConscript', """assert GetLaunchDir() == '%s'"""%test.workpath('sub2')) test.run(chdir = 'sub2', arguments = '-U') test.fail_test(os.path.exists(test.workpath('sub1', 'foo.out'))) test.fail_test(not os.path.exists(test.workpath('sub2', 'bar.out'))) @@ -101,6 +105,7 @@ test.unlink(['sub2', 'bar.out']) test.unlink(['sub2b', 'bar.out']) test.unlink('bar.out') +test.write('SConscript', """assert GetLaunchDir() == '%s'"""%test.workpath()) test.run(arguments='-U') test.fail_test(not os.path.exists(test.workpath('sub1', 'foo.out'))) test.fail_test(os.path.exists(test.workpath('sub2', 'bar.out'))) @@ -113,6 +118,7 @@ test.unlink(['sub1', 'foo.out']) test.unlink(['sub3', 'baz.out']) test.unlink(['sub2', 'xxx.out']) +test.write('SConscript', """assert GetLaunchDir() == '%s'"""%test.workpath('sub3')) test.run(chdir = 'sub3', arguments='-U bar') test.fail_test(os.path.exists(test.workpath('sub1', 'foo.out'))) test.fail_test(not os.path.exists(test.workpath('sub2', 'bar.out'))) diff --git a/test/option--implicit-cache.py b/test/option--implicit-cache.py index 3460b2f..d6ca15c 100644 --- a/test/option--implicit-cache.py +++ b/test/option--implicit-cache.py @@ -27,6 +27,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import sys import TestSCons +import string if sys.platform == 'win32': _exe = '.exe' @@ -266,4 +267,34 @@ main(int argc, char *argv[]) test.run(arguments = "--implicit-cache one%s"%_obj) test.run(arguments = "--implicit-cache one%s"%_obj) +# Test forcing of implicit caching: +test.write(['include', 'foo.h'], +r""" +#define FOO_STRING "include/foo.h 3\n" +#include "bar.h" +""") + +test.run(arguments = "--implicit-cache " + args) + +test.write(['include', 'foo.h'], +r""" +#define FOO_STRING "include/foo.h 3\n" +#include "baz.h" +#include "bar.h" +""") + +test.run(arguments = "--implicit-deps-unchanged " + variant_prog) +assert string.find(test.stdout(), 'is up to date') == -1, test.stdout() + +test.write(['include', 'baz.h'], +r""" +#define BAZ_STRING "include/baz.h 2\n" +""") + +test.run(arguments = "--implicit-deps-unchanged " + variant_prog) +assert string.find(test.stdout(), 'is up to date') != -1, test.stdout() + +test.run(arguments = variant_prog) +assert string.find(test.stdout(), 'is up to date') == -1, test.stdout() + test.pass_test() -- cgit v0.12