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.
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
# 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.
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
import SCons.Platform
import SCons.Tool
import SCons.Util
+import SCons.Sig
import os
import os.path
default_targets = []
print_help = 0
arguments = {}
+launch_dir = os.path.abspath(os.curdir)
# global exports set by Export():
global_exports = {}
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
globals['Split'] = SCons.Util.Split
globals['Tool'] = SCons.Tool.Tool
globals['WhereIs'] = SCons.Util.WhereIs
+ globals['GetLaunchDir'] = GetLaunchDir
+ globals['SetBuildSignatureType'] = SetBuildSignatureType
return globals
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:
#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:
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.
"""
# 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:
--- /dev/null
+#!/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()
BuildDir('sub2b', 'sub2')
SConscript('sub2b/SConscript')
Default(env.B(target = 'sub2/xxx.out', source = 'xxx.in'))
+SConscript('SConscript')
""" % python)
test.write(['sub2', 'SConscript'], """
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')))
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')))
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')))
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')))
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')))
import os
import sys
import TestSCons
+import string
if sys.platform == 'win32':
_exe = '.exe'
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()