From 14b0749ef9a6232ad1375f750baf00e0fea14e56 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Thu, 2 May 2002 12:16:24 +0000 Subject: Fix for long-line LINKCOM signatures on WIN32; add a for_signature argument to command generators. (Charles Crain) --- doc/man/scons.1 | 12 +++++++++--- src/CHANGES.txt | 4 ++++ src/RELEASE.txt | 4 ++++ src/engine/SCons/Action.py | 7 ++++--- src/engine/SCons/ActionTests.py | 7 ++++--- src/engine/SCons/Defaults.py | 16 ++++++++-------- test/CommandGenerator.py | 2 +- test/long-lines.py | 8 +++++++- 8 files changed, 41 insertions(+), 19 deletions(-) diff --git a/doc/man/scons.1 b/doc/man/scons.1 index afd4c166..3fcfc805 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -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) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 28375d24..f152670b 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -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 diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 8a79ffcf..1d0a5a92 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -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 diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 1941e1a3..94af6bdf 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -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. diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index cda565d3..1a0ec182 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -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) diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index 11daa393..db93a670 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -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: diff --git a/test/CommandGenerator.py b/test/CommandGenerator.py index a85b07a8..9a2a7c79 100644 --- a/test/CommandGenerator.py +++ b/test/CommandGenerator.py @@ -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, diff --git a/test/long-lines.py b/test/long-lines.py index 9cf24d87..521ed2c4 100644 --- a/test/long-lines.py +++ b/test/long-lines.py @@ -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)) -- cgit v1.2.1