From 566740b738519b4d8c805273139b68144006ee6b Mon Sep 17 00:00:00 2001 From: stevenknight Date: Thu, 10 Mar 2005 13:30:11 +0000 Subject: [PATCH] Add TempFileMunge support to AIX, Cygwin, HP-UX, Linux/UNIX and SunOS. (Leanid Nazdrynau) git-svn-id: http://scons.tigris.org/svn/scons/trunk@1251 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- src/engine/SCons/Platform/__init__.py | 71 ++++++++++++++++++++++++++ src/engine/SCons/Platform/aix.py | 3 ++ src/engine/SCons/Platform/cygwin.py | 5 +- src/engine/SCons/Platform/hpux.py | 2 + src/engine/SCons/Platform/posix.py | 5 ++ src/engine/SCons/Platform/sunos.py | 2 + src/engine/SCons/Platform/win32.py | 72 +-------------------------- 7 files changed, 88 insertions(+), 72 deletions(-) diff --git a/src/engine/SCons/Platform/__init__.py b/src/engine/SCons/Platform/__init__.py index 0856775a..9c15a087 100644 --- a/src/engine/SCons/Platform/__init__.py +++ b/src/engine/SCons/Platform/__init__.py @@ -48,6 +48,7 @@ import imp import os import string import sys +import tempfile import SCons.Errors import SCons.Tool @@ -116,6 +117,76 @@ class PlatformSpec: def __str__(self): return self.name + +class TempFileMunge: + """A callable class. You can set an Environment variable to this, + then call it with a string argument, then it will perform temporary + file substitution on it. This is used to circumvent the long command + line limitation. + + Example usage: + env["TEMPFILE"] = TempFileMunge + env["LINKCOM"] = "${TEMPFILE('$LINK $TARGET $SOURCES')}" + """ + def __init__(self, cmd): + self.cmd = cmd + + def __call__(self, target, source, env, for_signature): + if for_signature: + return self.cmd + cmd = env.subst_list(self.cmd, 0, target, source)[0] + try: + maxline = int(env.subst('$MAXLINELENGTH')) + except ValueError: + maxline = 2048 + if (reduce(lambda x, y: x + len(y), cmd, 0) + len(cmd)) <= maxline: + return self.cmd + else: + # We do a normpath because mktemp() has what appears to be + # a bug in Win32 that will use a forward slash as a path + # delimiter. Win32's link mistakes that for a command line + # switch and barfs. + # + # We use the .lnk suffix for the benefit of the Phar Lap + # linkloc linker, which likes to append an .lnk suffix if + # none is given. + tmp = os.path.normpath(tempfile.mktemp('.lnk')) + native_tmp = SCons.Util.get_native_path(tmp) + + if env['SHELL'] and env['SHELL'] == 'sh': + # The sh shell will try to escape the backslashes in the + # path, so unescape them. + native_tmp = string.replace(native_tmp, '\\', r'\\\\') + # In Cygwin, we want to use rm to delete the temporary + # file, because del does not exist in the sh shell. + rm = env.Detect('rm') or 'del' + else: + # Don't use 'rm' if the shell is not sh, because rm won't + # work with the win32 shells (cmd.exe or command.com) or + # win32 path names. + rm = 'del' + + args = map(SCons.Util.quote_spaces, cmd[1:]) + open(tmp, 'w').write(string.join(args, " ") + "\n") + # XXX Using the SCons.Action.print_actions value directly + # like this is bogus, but expedient. This class should + # really be rewritten as an Action that defines the + # __call__() and strfunction() methods and lets the + # normal action-execution logic handle whether or not to + # print/execute the action. The problem, though, is all + # of that is decided before we execute this method as + # part of expanding the $TEMPFILE construction variable. + # Consequently, refactoring this will have to wait until + # we get more flexible with allowing Actions to exist + # independently and get strung together arbitrarily like + # Ant tasks. In the meantime, it's going to be more + # user-friendly to not let obsession with architectural + # purity get in the way of just being helpful, so we'll + # reach into SCons.Action directly. + if SCons.Action.print_actions: + print("Using tempfile "+native_tmp+" for command line:\n"+ + str(cmd[0]) + " " + string.join(args," ")) + return [ cmd[0], '@' + native_tmp + '\n' + rm, native_tmp ] def Platform(name = platform_default()): """Select a canned Platform specification. diff --git a/src/engine/SCons/Platform/aix.py b/src/engine/SCons/Platform/aix.py index e0d2e76d..cc114666 100644 --- a/src/engine/SCons/Platform/aix.py +++ b/src/engine/SCons/Platform/aix.py @@ -57,3 +57,6 @@ def get_xlc(env, xlc, xlc_r, packages): def generate(env): posix.generate(env) + #Based on AIX 5.2: ARG_MAX=24576 - 3000 for environment expansion + env['MAXLINELENGTH'] = 21576 + diff --git a/src/engine/SCons/Platform/cygwin.py b/src/engine/SCons/Platform/cygwin.py index fad95be4..728eda39 100644 --- a/src/engine/SCons/Platform/cygwin.py +++ b/src/engine/SCons/Platform/cygwin.py @@ -33,7 +33,7 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import posix -import win32 +from SCons.Platform import TempFileMunge def generate(env): posix.generate(env) @@ -44,4 +44,5 @@ def generate(env): env['SHLIBSUFFIX'] = '.dll' env['LIBPREFIXES'] = [ '$LIBPREFIX', '$SHLIBPREFIX' ] env['LIBSUFFIXES'] = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ] - env['TEMPFILE'] = win32.TempFileMunge + env['TEMPFILE'] = TempFileMunge + env['MAXLINELENGTH'] = 2048 diff --git a/src/engine/SCons/Platform/hpux.py b/src/engine/SCons/Platform/hpux.py index 9b3a6bb6..ddbfafc4 100644 --- a/src/engine/SCons/Platform/hpux.py +++ b/src/engine/SCons/Platform/hpux.py @@ -36,3 +36,5 @@ import posix def generate(env): posix.generate(env) + #Based on HP-UX11i: ARG_MAX=2048000 - 3000 for environment expansion + env['MAXLINELENGTH'] = 2045000 diff --git a/src/engine/SCons/Platform/posix.py b/src/engine/SCons/Platform/posix.py index 24ce2fb5..b945d1cc 100644 --- a/src/engine/SCons/Platform/posix.py +++ b/src/engine/SCons/Platform/posix.py @@ -40,6 +40,7 @@ import sys import select import SCons.Util +from SCons.Platform import TempFileMunge exitvalmap = { 2 : 127, @@ -240,6 +241,10 @@ def generate(env): env['SPAWN'] = spawn env['SHELL'] = 'sh' env['ESCAPE'] = escape + env['TEMPFILE'] = TempFileMunge + #Based on LINUX: ARG_MAX=ARG_MAX=131072 - 3000 for environment expansion + #Note: specific platforms might rise or lower this value + env['MAXLINELENGTH'] = 128072 # This platform supports RPATH specifications. env['__RPATH'] = '$_RPATH' diff --git a/src/engine/SCons/Platform/sunos.py b/src/engine/SCons/Platform/sunos.py index 6b37dd67..b2bbb7f2 100644 --- a/src/engine/SCons/Platform/sunos.py +++ b/src/engine/SCons/Platform/sunos.py @@ -36,3 +36,5 @@ import posix def generate(env): posix.generate(env) + #Based on sunSparc 8:32bit ARG_MAX=1048320 - 3000 for environment expansion + env['MAXLINELENGTH'] = 1045320 diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py index 62f2ee7e..382e5b8d 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -36,83 +36,15 @@ import os import os.path import string import sys -import tempfile + from SCons.Platform.posix import exitvalmap +from SCons.Platform import TempFileMunge # XXX See note below about why importing SCons.Action should be # eventually refactored. import SCons.Action import SCons.Util -class TempFileMunge: - """A callable class. You can set an Environment variable to this, - then call it with a string argument, then it will perform temporary - file substitution on it. This is used to circumvent the win32 long command - line limitation. - - Example usage: - env["TEMPFILE"] = TempFileMunge - env["LINKCOM"] = "${TEMPFILE('$LINK $TARGET $SOURCES')}" - """ - def __init__(self, cmd): - self.cmd = cmd - - def __call__(self, target, source, env, for_signature): - if for_signature: - return self.cmd - cmd = env.subst_list(self.cmd, 0, target, source)[0] - try: - maxline = int(env.subst('$MAXLINELENGTH')) - except ValueError: - maxline = 2048 - if (reduce(lambda x, y: x + len(y), cmd, 0) + len(cmd)) <= maxline: - return self.cmd - else: - # We do a normpath because mktemp() has what appears to be - # a bug in Win32 that will use a forward slash as a path - # delimiter. Win32's link mistakes that for a command line - # switch and barfs. - # - # We use the .lnk suffix for the benefit of the Phar Lap - # linkloc linker, which likes to append an .lnk suffix if - # none is given. - tmp = os.path.normpath(tempfile.mktemp('.lnk')) - native_tmp = SCons.Util.get_native_path(tmp) - - if env['SHELL'] and env['SHELL'] == 'sh': - # The sh shell will try to escape the backslashes in the - # path, so unescape them. - native_tmp = string.replace(native_tmp, '\\', r'\\\\') - # In Cygwin, we want to use rm to delete the temporary - # file, because del does not exist in the sh shell. - rm = env.Detect('rm') or 'del' - else: - # Don't use 'rm' if the shell is not sh, because rm won't - # work with the win32 shells (cmd.exe or command.com) or - # win32 path names. - rm = 'del' - - args = map(SCons.Util.quote_spaces, cmd[1:]) - open(tmp, 'w').write(string.join(args, " ") + "\n") - # XXX Using the SCons.Action.print_actions value directly - # like this is bogus, but expedient. This class should - # really be rewritten as an Action that defines the - # __call__() and strfunction() methods and lets the - # normal action-execution logic handle whether or not to - # print/execute the action. The problem, though, is all - # of that is decided before we execute this method as - # part of expanding the $TEMPFILE construction variable. - # Consequently, refactoring this will have to wait until - # we get more flexible with allowing Actions to exist - # independently and get strung together arbitrarily like - # Ant tasks. In the meantime, it's going to be more - # user-friendly to not let obsession with architectural - # purity get in the way of just being helpful, so we'll - # reach into SCons.Action directly. - if SCons.Action.print_actions: - print("Using tempfile "+native_tmp+" for command line:\n"+ - str(cmd[0]) + " " + string.join(args," ")) - return [ cmd[0], '@' + native_tmp + '\n' + rm, native_tmp ] # The upshot of all this is that, if you are using Python 1.5.2, # you had better have cmd or command.com in your PATH when you run -- 2.26.2