Fix for long-line LINKCOM signatures on WIN32; add a for_signature argument to comman...
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 2 May 2002 12:16:24 +0000 (12:16 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 2 May 2002 12:16:24 +0000 (12:16 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@354 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/man/scons.1
src/CHANGES.txt
src/RELEASE.txt
src/engine/SCons/Action.py
src/engine/SCons/ActionTests.py
src/engine/SCons/Defaults.py
test/CommandGenerator.py
test/long-lines.py

index afd4c16643199fc38631718e1f877e9648f1e7f9..3fcfc8053fc917420c223eb4b9a35eb2bd0720a1 100644 (file)
@@ -1737,16 +1737,22 @@ can be converted into an Action object
 (see the next section).
 
 The generator function
-takes 3 arguments:
+takes four arguments:
 .I source 
 - a list of source nodes, 
 .I target
 - a list of target nodes,
 .I env
-- the construction environment. Example:
+- the construction environment.
+.I for_signature
+- a Boolean value that specifies
+whether the generator is being called
+for generating a build signature
+(as opposed to actually executing the command).
+Example:
 
 .ES
-def g(source, target, env):
+def g(source, target, env, for_signature):
     return [["gcc", "-c", "-o"] + target + source] 
 
 b = Builder(name="Object", generator=g)
index 28375d24b0c25f25b1db2a489e283564d54f04af..f152670b5832694d2dc2bb24c95478d05a4d0b82 100644 (file)
@@ -78,6 +78,10 @@ RELEASE 0.07 - Thu, 25 Apr 2002 06:24:50 -0500
   - Fix for relative CPPPATH directories in subsidiary SConscript files
     (broken in 0.06).
 
+  - Add a for_signature argument to command generators, so that
+    generators that need to can return distinct values for the
+    command signature and for executing the command.
+
   From Alex Jacques:
 
   - Create a better scons.bat file from a py2bat.py script on the Python
index 8a79ffcf707a39f4d57798216a58a972e1ecd2d3..1d0a5a9232f2f90a0429e4672ce147740beec632 100644 (file)
@@ -50,6 +50,10 @@ RELEASE 0.07 - Thu, 25 Apr 2002 06:24:50 -0500
       is an optional SCons.Node.FS.FS object.  You will need to update
       the interfaces of any local Scanner functions you have defined.
 
+    - Command generator functions now take a fourth argument,
+      for_signature.  You will need to add this argument to any
+      generator functions you have defined.
+
   Please note the following important changes since release 0.05:
 
     - Python functions as Builder actions now take Node objects, not
index 1941e1a38714fb27ef028b7493bef3c0c1f801fa..94af6bdfa6056e5c6ae1b28521699a7ca3364d3f 100644 (file)
@@ -395,13 +395,14 @@ class CommandGeneratorAction(ActionBase):
     def __init__(self, generator):
         self.generator = generator
 
-    def __generate(self, kw):
+    def __generate(self, kw, for_signature):
         import SCons.Util
 
         # Wrap the environment dictionary in an EnvDictProxy
         # object to make variable interpolation easier for the
         # client.
         args = copy.copy(kw)
+        args['for_signature'] = for_signature
         if args.has_key("env") and not isinstance(args["env"], EnvDictProxy):
             args["env"] = EnvDictProxy(args["env"])
 
@@ -417,7 +418,7 @@ class CommandGeneratorAction(ActionBase):
         return gen_cmd
 
     def execute(self, **kw):
-        return apply(self.__generate(kw).execute, (), kw)
+        return apply(self.__generate(kw, 0).execute, (), kw)
 
     def get_contents(self, **kw):
         """Return the signature contents of this action's command line.
@@ -425,7 +426,7 @@ class CommandGeneratorAction(ActionBase):
         This strips $(-$) and everything in between the string,
         since those parts don't affect signatures.
         """
-        return apply(self.__generate(kw).get_contents, (), kw)
+        return apply(self.__generate(kw, 1).get_contents, (), kw)
 
 class LazyCmdGenerator:
     """This is a simple callable class that acts as a command generator.
index cda565d3dff8d80f758a3d3cac404d40662ea1a0..1a0ec182ba25160bb8ee0757829e73ba362f7649 100644 (file)
@@ -176,7 +176,7 @@ class CommandGeneratorActionTestCase(unittest.TestCase):
         """Test executing a command generator Action
         """
 
-        def f(dummy, env, self=self):
+        def f(dummy, env, for_signature, self=self):
             self.dummy = dummy
             assert env.subst("$FOO $( bar $) baz") == 'foo baz\nbar ack bar baz', env.subst("$FOO $( bar $) baz")
             assert env.subst("$FOO $( bar $) baz", raw=1) == 'foo baz\nbar ack $( bar $) baz', env.subst("$FOO $( bar $) baz", raw=1)
@@ -194,7 +194,7 @@ class CommandGeneratorActionTestCase(unittest.TestCase):
             assert env.subst_list([ '$foo', '$(', 'bar', '$)' ],
                                   raw=1) == [[ 'bar', '$(', 'bar', '$)' ]], env.subst_list([ '$foo', '$(', 'bar', '$)' ], raw=1)
             self.dummy=dummy
-        def f2(dummy, env, f=func_action):
+        def f2(dummy, env, for_signature, f=func_action):
             return f
         def ch(cmd, args, env, self=self):
             self.cmd.append(cmd)
@@ -223,7 +223,8 @@ class CommandGeneratorActionTestCase(unittest.TestCase):
     def test_get_contents(self):
         """Test fetching the contents of a command generator Action
         """
-        def f(target, source, foo, bar):
+        def f(target, source, foo, bar, for_signature):
+            assert for_signature, for_signature
             return [["guux", foo, "$(", "ignore", "$)", bar]]
 
         a = SCons.Action.CommandGeneratorAction(f)
index 11daa3930527a52f58a5abf08e4d4164844ce5c6..db93a670691a08effcd23e39c57ecf4acc8f24a8 100644 (file)
@@ -64,7 +64,7 @@ class SharedCmdGenerator:
         self.action_static = static
         self.action_shared = shared
         
-    def __call__(self, target, source, env, shared=0):
+    def __call__(self, target, source, env, shared=0, for_signature=0):
         for src in source:
             try:
                 if src.attributes.shared != shared:
@@ -165,15 +165,15 @@ Object = SCons.Builder.Builder(name = 'Object',
                                src_suffix = static_obj.src_suffixes(),
                                src_builder = [CFile, CXXFile])
 
-def win32TempFileMunge(env, cmd_list):
+def win32TempFileMunge(env, cmd_list, for_signature):
     """Given a list of command line arguments, see if it is too
     long to pass to the win32 command line interpreter.  If so,
     create a temp file, then pass "@tempfile" as the sole argument
     to the supplied command (which is the first element of cmd_list).
     Otherwise, just return [cmd_list]."""
     cmd = env.subst_list(cmd_list)[0]
-    cmdlen = reduce(lambda x, y: x + len(y), cmd, 0) + len(cmd)
-    if cmdlen <= 2048:
+    if for_signature or \
+       (reduce(lambda x, y: x + len(y), cmd, 0) + len(cmd)) <= 2048:
         return [cmd_list]
     else:
         import tempfile
@@ -187,11 +187,11 @@ def win32TempFileMunge(env, cmd_list):
         return [ [cmd[0], '@' + tmp],
                  ['del', tmp] ]
     
-def win32LinkGenerator(env, target, source, **kw):
+def win32LinkGenerator(env, target, source, for_signature, **kw):
     args = [ '$LINK', '$LINKFLAGS', '/OUT:%s' % target[0],
              '$(', '$_LIBDIRFLAGS', '$)', '$_LIBFLAGS' ]
     args.extend(map(SCons.Util.to_String, source))
-    return win32TempFileMunge(env, args)
+    return win32TempFileMunge(env, args, for_signature)
 
 Program = SCons.Builder.Builder(name='Program',
                                 action='$LINKCOM',
@@ -211,7 +211,7 @@ class LibAffixGenerator:
             return self.shared_affix
         return self.static_affix
 
-def win32LibGenerator(target, source, env, shared=1):
+def win32LibGenerator(target, source, env, for_signature, shared=1):
     listCmd = [ "$SHLINK", "$SHLINKFLAGS" ]
 
     for tgt in target:
@@ -231,7 +231,7 @@ def win32LibGenerator(target, source, env, shared=1):
         else:
             # Just treat it as a generic source file.
             listCmd.append(str(src))
-    return win32TempFileMunge(env, listCmd)
+    return win32TempFileMunge(env, listCmd, for_signature)
 
 def win32LibEmitter(target, source, env, shared=0):
     if shared:
index a85b07a89e538c47c54ee5876925fb81a91c21a3..9a2a7c7926f7c3ec4492e8e6cbc06d90ee7398c1 100644 (file)
@@ -42,7 +42,7 @@ sys.exit(0)
 """)
 
 test.write('SConstruct', """
-def g(source, target, env):
+def g(source, target, for_signature, env):
     import sys
     python = sys.executable
     return [[python, "build.py", "$TEMPFILE"] + source,
index 9cf24d875cb8fcf1666fb5e735cff14c00e02e61..521ed2c4db8180f37d63886ccb9476a21f0a3b23 100644 (file)
@@ -35,10 +35,12 @@ test = TestSCons.TestSCons()
 if sys.platform == 'win32':
     lib_=''
     _dll = '.dll'
+    _export = '__declspec(dllexport) '
     linkflag = '/LIBPATH:' + test.workpath()
 else:
     lib_='lib'
     _dll='.so'
+    _export=''
     linkflag = '-L' + test.workpath()
 
 test.write('SConstruct', """
@@ -52,6 +54,8 @@ env.Library(target = 'bar', source = 'foo.c', shared=1)
 """ % (linkflag, linkflag))
 
 test.write('foo.c', r"""
+%svoid foo() { }
+
 int
 main(int argc, char *argv[])
 {
@@ -59,10 +63,12 @@ main(int argc, char *argv[])
        printf("foo.c\n");
        exit (0);
 }
-""")
+""" % _export)
 
 test.run(arguments = '.')
 
+test.up_to_date(arguments = '.')
+
 test.run(program = test.workpath('foo'), stdout = "foo.c\n")
 
 test.fail_test(not os.path.exists(lib_+'bar'+_dll))