Added --implicit-deps-unchanged option. Added GetLaunchDir() function. Added SetBuild...
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Fri, 12 Jul 2002 06:17:59 +0000 (06:17 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Fri, 12 Jul 2002 06:17:59 +0000 (06:17 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@411 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/man/scons.1
src/CHANGES.txt
src/engine/SCons/Node/__init__.py
src/engine/SCons/Script/SConscript.py
src/engine/SCons/Script/__init__.py
src/engine/SCons/Sig/__init__.py
test/SetBuildSignatureType.py [new file with mode: 0644]
test/option--U.py
test/option--implicit-cache.py

index 8c02eff6bd60a4177a87367efb9067ea756501ad..8761335c44cca2ad8ed5180cac1086085aa60f7c 100644 (file)
@@ -399,6 +399,13 @@ to miss changes in the implicit dependencies in cases where a new implicit
 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.
index 8cc8060ffa1e016f79e67c2b8d1d534a90f4e771..6b0c79c901265e1fe17eb22aced71b5ecebfe226 100644 (file)
@@ -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
index 1e231989df977747a0acf12a0490af88c5290b2f..bc0539e317bf10fe4971bb20c1479d1f61d65e46 100644 (file)
@@ -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 
index 0f65732329e1fcf925db7d20de6cdb51916a583a..48c4046dc05ad4ca522def211344ab138ee8bb2f 100644 (file)
@@ -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
index 6f87353911f339fd656c3727c57dcd737966892c..1d53fed706d2fdaa98108310760681cff827e53d 100644 (file)
@@ -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:
index 553c9cea812dd432ac27aa1f53e2216501e83f15..0e629fb40d8269daef3949ccff2c5ecde31c1f95 100644 (file)
@@ -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 (file)
index 0000000..39534dd
--- /dev/null
@@ -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()
index a683a8d07e24e97e29e58318536d17b9199b78fa..1facab8fe24879649a6b0839b0e5c0cdad86a242 100644 (file)
@@ -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')))
index 3460b2f61ff4ca8854ba51bfb10b2324028aa4e7..d6ca15cf71f26de9b99b90a5cb7000d6d267bc05 100644 (file)
@@ -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()