diff options
author | Steven Knight <knight@baldmt.com> | 2006-07-25 02:30:45 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2006-07-25 02:30:45 (GMT) |
commit | dd9bbc79353ae90b2402c16b1613dad4e502d250 (patch) | |
tree | 42f857f72bb4dcab6d876d1f9c73e0a1dd70d8c2 /src/engine/SCons/Environment.py | |
parent | 57fcbbc5d24fb16f988e4fe3294d5d49abef8e2a (diff) | |
download | SCons-dd9bbc79353ae90b2402c16b1613dad4e502d250.zip SCons-dd9bbc79353ae90b2402c16b1613dad4e502d250.tar.gz SCons-dd9bbc79353ae90b2402c16b1613dad4e502d250.tar.bz2 |
Merged revisions 1441-1539 via svnmerge from
http://scons.tigris.org/svn/scons/branches/core
........
r1441 | stevenknight | 2006-04-22 23:06:53 -0400 (Sat, 22 Apr 2006) | 1 line
0.96.D397 - The scons command, branch 0.96.91.
........
r1442 | stevenknight | 2006-04-27 00:45:12 -0400 (Thu, 27 Apr 2006) | 1 line
0.96.D398 - The scons command, branch 0.96.92.
........
r1443 | stevenknight | 2006-04-27 00:49:25 -0400 (Thu, 27 Apr 2006) | 1 line
0.96.D399 - Taskmaster clean-ups in anticipation of refactoring speedups.
........
r1450 | stevenknight | 2006-05-02 00:04:55 -0400 (Tue, 02 May 2006) | 1 line
0.96.D400 - Fix VC+++ 2005 Express detection. (Atul Varma) Fix parsing Intel C compiler Li
........
r1451 | stevenknight | 2006-05-02 01:14:24 -0400 (Tue, 02 May 2006) | 1 line
0.96.D401 - Enhance ParseConfig() to understand -arch and -isysroot options. (Gary Oberbrun
........
r1458 | stevenknight | 2006-05-02 23:21:04 -0400 (Tue, 02 May 2006) | 1 line
0.96.D402 - Make strfunction handling consistent. (David Gruener)
........
r1459 | stevenknight | 2006-05-02 23:37:08 -0400 (Tue, 02 May 2006) | 1 line
0.96.D403 - Comment out the test of CVS checkout from the old tigris.org repository.
........
r1460 | stevenknight | 2006-05-03 23:47:54 -0400 (Wed, 03 May 2006) | 1 line
0.96.D404 - Preserve white space in display Action string. (David Gruener)
........
r1461 | stevenknight | 2006-05-04 09:16:15 -0400 (Thu, 04 May 2006) | 1 line
0.96.D405 - Add MergeFlags() and AddFlags() methods. (Greg Noel) Support recognizing compi
........
r1462 | stevenknight | 2006-05-04 23:46:53 -0400 (Thu, 04 May 2006) | 1 line
0.96.D406 - Fix stack trace when ParseFlags has a null string.
........
r1464 | stevenknight | 2006-05-05 17:21:27 -0400 (Fri, 05 May 2006) | 1 line
0.96.D408 - Fix the string displayed by InstallAs() when called through the default construc
........
r1465 | stevenknight | 2006-05-05 18:30:28 -0400 (Fri, 05 May 2006) | 1 line
0.96.D409 - Fix test/ParseConfig.py, broken in the previous checkin by ParseFlags() changes.
........
r1466 | stevenknight | 2006-05-05 20:42:35 -0400 (Fri, 05 May 2006) | 1 line
0.96.D407 - Avoid recursive calls to main() in SConf test programs. (Karol Pietrzak)
........
r1467 | stevenknight | 2006-05-06 00:27:21 -0400 (Sat, 06 May 2006) | 1 line
0.96.D410 - Catch errors from commands that ParseConfig() calls. (John Pye)
........
r1468 | stevenknight | 2006-05-06 10:55:38 -0400 (Sat, 06 May 2006) | 1 line
0.96.D411 - Significant taskmaster speedup by using reference counts, not list manipulation.
........
r1469 | stevenknight | 2006-05-06 18:38:02 -0400 (Sat, 06 May 2006) | 1 line
0.96.D413 - TeX improvements.
........
r1471 | stevenknight | 2006-05-07 09:07:58 -0400 (Sun, 07 May 2006) | 2 lines
Delete properties interfering with clean .jpg checkout.
........
r1472 | stevenknight | 2006-05-07 09:23:54 -0400 (Sun, 07 May 2006) | 1 line
0.96.D412 - Windows portability fixes for two tests and ParseConfig() execution.
........
r1473 | stevenknight | 2006-05-07 09:30:11 -0400 (Sun, 07 May 2006) | 1 line
0.96.D414 - Various man page and documentation updates.
........
r1474 | stevenknight | 2006-05-07 23:53:12 -0400 (Sun, 07 May 2006) | 1 line
0.96.D415 - Initial infrastructure for executing tests under QMTest. (Stefan Seefeld)
........
r1476 | stevenknight | 2006-05-09 00:03:47 -0400 (Tue, 09 May 2006) | 1 line
0.96.D416 - Fix QMTest infrastructure to avoid listing directories with no tests and to find
........
r1477 | stevenknight | 2006-05-16 06:47:51 -0400 (Tue, 16 May 2006) | 1 line
0.96.D417 - Fix Alias turning Entries into Nodes or Dirs too soon.
........
r1478 | stevenknight | 2006-05-17 08:32:58 -0400 (Wed, 17 May 2006) | 1 line
0.96.D418 - Next QMTest changes (including fixing copyrights).
........
r1479 | stevenknight | 2006-05-18 05:07:06 -0400 (Thu, 18 May 2006) | 1 line
0.96.D419 - Fix DVIPDF tests after recent changes.
........
r1497 | stevenknight | 2006-05-23 08:47:01 -0400 (Tue, 23 May 2006) | 1 line
0.96.D420 - Better error message when trying to build a file from an unknown sufix. (Gary O
........
r1498 | stevenknight | 2006-05-23 09:38:52 -0400 (Tue, 23 May 2006) | 1 line
0.96.D421 - Suppress duplicate entries in latest TeX patch. (Joel B. Mohler)
........
r1499 | stevenknight | 2006-05-23 22:00:06 -0400 (Tue, 23 May 2006) | 1 line
0.96.D422 - Add tests for tuple variable expansion. (Gary Oberbrunner)
........
r1515 | stevenknight | 2006-06-12 06:44:24 -0400 (Mon, 12 Jun 2006) | 1 line
0.96.D423 - More QMTest work: start giving runtest.py its own tests, more functionality for
........
r1517 | stevenknight | 2006-06-21 07:34:30 -0400 (Wed, 21 Jun 2006) | 1 line
0.96.D424 - Move test/Configure.py and test/Options.py to avoid confusion with similarly-nam
........
r1518 | stevenknight | 2006-06-21 12:40:37 -0400 (Wed, 21 Jun 2006) | 1 line
0.96.D425 - Change the QMTest infrastructure to use File naming, not Python. Rename tests w
........
r1533 | stevenknight | 2006-07-23 20:10:08 -0400 (Sun, 23 Jul 2006) | 1 line
0.96.D426 - Fix ramifications of changing when Node disambiguation happens.
........
r1535 | stevenknight | 2006-07-24 06:40:43 -0400 (Mon, 24 Jul 2006) | 3 lines
Initialized merge tracking via "svnmerge" with revisions "1-1534" from
http://scons.tigris.org/svn/scons/trunk
........
r1536 | stevenknight | 2006-07-24 21:45:40 -0400 (Mon, 24 Jul 2006) | 2 lines
Remove svnmerge-integrated property to start over.
........
r1538 | stevenknight | 2006-07-24 21:51:32 -0400 (Mon, 24 Jul 2006) | 3 lines
Initialized merge tracking via "svnmerge" with revisions "1-1440" from
http://scons.tigris.org/svn/scons/trunk
........
Diffstat (limited to 'src/engine/SCons/Environment.py')
-rw-r--r-- | src/engine/SCons/Environment.py | 307 |
1 files changed, 235 insertions, 72 deletions
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 691098d..d76f71d 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -38,6 +38,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import copy import os import os.path +import popen2 import string from UserDict import UserDict @@ -83,7 +84,7 @@ def installFunc(target, source, env): return install(target[0].path, source[0].path, env) def installString(target, source, env): - return env.subst(env['INSTALLSTR'], 0, target, source) + return env.subst_target_source(env['INSTALLSTR'], 0, target, source) installAction = SCons.Action.Action(installFunc, installString) @@ -435,6 +436,34 @@ class SubstitutionEnvironment: subst_target_source = subst + def backtick(self, command): + try: + popen2.Popen3 + except AttributeError: + (tochild, fromchild, childerr) = os.popen3(self.subst(command)) + tochild.close() + err = childerr.read() + out = fromchild.read() + fromchild.close() + status = childerr.close() + else: + p = popen2.Popen3(command, 1) + p.tochild.close() + out = p.fromchild.read() + err = p.childerr.read() + status = p.wait() + if err: + import sys + sys.stderr.write(err) + if status: + try: + if os.WIFEXITED(status): + status = os.WEXITSTATUS(status) + except AttributeError: + pass + raise OSError("'%s' exited %s" % (command, status)) + return out + def Override(self, overrides): """ Produce a modified environment whose variables are overriden by @@ -458,6 +487,196 @@ class SubstitutionEnvironment: else: return self + def ParseFlags(self, *flags): + """ + Parse the set of flags and return a dict with the flags placed + in the appropriate entry. The flags are treated as a typical + set of command-line flags for a GNU-like toolchain and used to + populate the entries in the dict immediately below. If one of + the flag strings begins with a bang (exclamation mark), it is + assumed to be a command and the rest of the string is executed; + the result of that evaluation is then added to the dict. + """ + dict = { + 'ASFLAGS' : [], + 'CCFLAGS' : [], + 'CPPDEFINES' : [], + 'CPPFLAGS' : [], + 'CPPPATH' : [], + 'FRAMEWORKPATH' : [], + 'FRAMEWORKS' : [], + 'LIBPATH' : [], + 'LIBS' : [], + 'LINKFLAGS' : [], + 'RPATH' : [], + } + + # The use of the "me" parameter to provide our own name for + # recursion is an egregious hack to support Python 2.1 and before. + def do_parse(arg, me, self = self, dict = dict): + # if arg is a sequence, recurse with each element + if not arg: + return + + if not SCons.Util.is_String(arg): + for t in arg: me(t, me) + return + + # if arg is a command, execute it + if arg[0] == '!': + arg = self.backtick(arg[1:]) + + # utility function to deal with -D option + def append_define(name, dict = dict): + t = string.split(name, '=') + if len(t) == 1: + dict['CPPDEFINES'].append(name) + else: + dict['CPPDEFINES'].append([t[0], string.join(t[1:], '=')]) + + # Loop through the flags and add them to the appropriate option. + # This tries to strike a balance between checking for all possible + # flags and keeping the logic to a finite size, so it doesn't + # check for some that don't occur often. It particular, if the + # flag is not known to occur in a config script and there's a way + # of passing the flag to the right place (by wrapping it in a -W + # flag, for example) we don't check for it. Note that most + # preprocessor options are not handled, since unhandled options + # are placed in CCFLAGS, so unless the preprocessor is invoked + # separately, these flags will still get to the preprocessor. + # Other options not currently handled: + # -iqoutedir (preprocessor search path) + # -u symbol (linker undefined symbol) + # -s (linker strip files) + # -static* (linker static binding) + # -shared* (linker dynamic binding) + # -symbolic (linker global binding) + # -R dir (deprecated linker rpath) + # IBM compilers may also accept -qframeworkdir=foo + + params = string.split(arg) + append_next_arg_to = None # for multi-word args + for arg in params: + if append_next_arg_to: + if append_next_arg_to == 'CPPDEFINES': + append_define(arg) + elif append_next_arg_to == '-include': + t = ('-include', self.fs.File(arg)) + dict['CCFLAGS'].append(t) + elif append_next_arg_to == '-isysroot': + t = ('-isysroot', arg) + dict['CCFLAGS'].append(t) + dict['LINKFLAGS'].append(t) + elif append_next_arg_to == '-arch': + t = ('-arch', arg) + dict['CCFLAGS'].append(t) + dict['LINKFLAGS'].append(t) + else: + dict[append_next_arg_to].append(arg) + append_next_arg_to = None + elif not arg[0] in ['-', '+']: + dict['LIBS'].append(self.fs.File(arg)) + elif arg[:2] == '-L': + if arg[2:]: + dict['LIBPATH'].append(arg[2:]) + else: + append_next_arg_to = 'LIBPATH' + elif arg[:2] == '-l': + if arg[2:]: + dict['LIBS'].append(arg[2:]) + else: + append_next_arg_to = 'LIBS' + elif arg[:2] == '-I': + if arg[2:]: + dict['CPPPATH'].append(arg[2:]) + else: + append_next_arg_to = 'CPPPATH' + elif arg[:4] == '-Wa,': + dict['ASFLAGS'].append(arg[4:]) + dict['CCFLAGS'].append(arg) + elif arg[:4] == '-Wl,': + if arg[:11] == '-Wl,-rpath=': + dict['RPATH'].append(arg[11:]) + elif arg[:7] == '-Wl,-R,': + dict['RPATH'].append(arg[7:]) + elif arg[:6] == '-Wl,-R': + dict['RPATH'].append(arg[6:]) + else: + dict['LINKFLAGS'].append(arg) + elif arg[:4] == '-Wp,': + dict['CPPFLAGS'].append(arg) + elif arg[:2] == '-D': + if arg[2:]: + append_define(arg[2:]) + else: + appencd_next_arg_to = 'CPPDEFINES' + elif arg == '-framework': + append_next_arg_to = 'FRAMEWORKS' + elif arg[:14] == '-frameworkdir=': + dict['FRAMEWORKPATH'].append(arg[14:]) + elif arg[:2] == '-F': + if arg[2:]: + dict['FRAMEWORKPATH'].append(arg[2:]) + else: + append_next_arg_to = 'FRAMEWORKPATH' + elif arg == '-mno-cygwin': + dict['CCFLAGS'].append(arg) + dict['LINKFLAGS'].append(arg) + elif arg == '-mwindows': + dict['LINKFLAGS'].append(arg) + elif arg == '-pthread': + dict['CCFLAGS'].append(arg) + dict['LINKFLAGS'].append(arg) + elif arg[0] == '+': + dict['CCFLAGS'].append(arg) + dict['LINKFLAGS'].append(arg) + elif arg in ['-include', '-isysroot', '-arch']: + append_next_arg_to = arg + else: + dict['CCFLAGS'].append(arg) + + for arg in flags: + do_parse(arg, do_parse) + return dict + + def MergeFlags(self, args, unique=1): + """ + Merge the dict in args into the construction variables. If args + is not a dict, it is converted into a dict using ParseFlags. + If unique is not set, the flags are appended rather than merged. + """ + + if not SCons.Util.is_Dict(args): + args = self.ParseFlags(args) + if not unique: + apply(self.Append, (), args) + return self + for key, value in args.items(): + if value == '': + continue + try: + orig = self[key] + except KeyError: + orig = value + else: + if len(orig) == 0: orig = [] + elif not SCons.Util.is_List(orig): orig = [orig] + orig = orig + value + t = [] + if key[-4:] == 'PATH': + ### keep left-most occurence + for v in orig: + if v not in t: + t.append(v) + else: + ### keep right-most occurence + orig.reverse() + for v in orig: + if v not in t: + t.insert(0, v) + self[key] = t + return self + class Base(SubstitutionEnvironment): """Base class for "real" construction Environments. These are the primary objects used to communicate dependency and construction @@ -838,82 +1057,22 @@ class Base(SubstitutionEnvironment): def ParseConfig(self, command, function=None, unique=1): """ Use the specified function to parse the output of the command - in order to modify the current environment. The 'command' can + in order to modify the current environment. The 'command' can be a string or a list of strings representing a command and - it's arguments. 'Function' is an optional argument that takes - the environment and the output of the command. If no function is - specified, the output will be treated as the output of a typical - 'X-config' command (i.e. gtk-config) and used to append to the - ASFLAGS, CCFLAGS, CPPFLAGS, CPPPATH, LIBPATH, LIBS, LINKFLAGS - and CCFLAGS variables. + its arguments. 'Function' is an optional argument that takes + the environment, the output of the command, and the unique flag. + If no function is specified, MergeFlags, which treats the output + as the result of a typical 'X-config' command (i.e. gtk-config), + will merge the output into the appropriate variables. """ - - # the default parse function - def parse_conf(env, output, fs=self.fs, unique=unique): - dict = { - 'ASFLAGS' : [], - 'CCFLAGS' : [], - 'CPPFLAGS' : [], - 'CPPPATH' : [], - 'LIBPATH' : [], - 'LIBS' : [], - 'LINKFLAGS' : [], - } - - params = string.split(output) - append_next_arg_to='' # for multi-word args - for arg in params: - if append_next_arg_to: - dict[append_next_arg_to].append(arg) - append_next_arg_to = '' - elif arg[0] != '-': - dict['LIBS'].append(fs.File(arg)) - elif arg[:2] == '-L': - if arg[2:]: - dict['LIBPATH'].append(arg[2:]) - else: - append_next_arg_to = 'LIBPATH' - elif arg[:2] == '-l': - if arg[2:]: - dict['LIBS'].append(arg[2:]) - else: - append_next_arg_to = 'LIBS' - elif arg[:2] == '-I': - if arg[2:]: - dict['CPPPATH'].append(arg[2:]) - else: - append_next_arg_to = 'CPPPATH' - elif arg[:4] == '-Wa,': - dict['ASFLAGS'].append(arg) - elif arg[:4] == '-Wl,': - dict['LINKFLAGS'].append(arg) - elif arg[:4] == '-Wp,': - dict['CPPFLAGS'].append(arg) - elif arg == '-framework': - dict['LINKFLAGS'].append(arg) - append_next_arg_to='LINKFLAGS' - elif arg == '-mno-cygwin': - dict['CCFLAGS'].append(arg) - dict['LINKFLAGS'].append(arg) - elif arg == '-mwindows': - dict['LINKFLAGS'].append(arg) - elif arg == '-pthread': - dict['CCFLAGS'].append(arg) - dict['LINKFLAGS'].append(arg) - else: - dict['CCFLAGS'].append(arg) - if unique: - appender = env.AppendUnique - else: - appender = env.Append - apply(appender, (), dict) - if function is None: + def parse_conf(env, cmd, unique=unique): + return env.MergeFlags(cmd, unique) function = parse_conf - if type(command) is type([]): + if SCons.Util.is_List(command): command = string.join(command) command = self.subst(command) - return function(self, os.popen(command).read()) + return function(self, self.backtick(command)) def ParseDepends(self, filename, must_exist=None, only_one=0): """ @@ -1137,7 +1296,11 @@ class Base(SubstitutionEnvironment): ####################################################################### def Action(self, *args, **kw): - nargs = self.subst(args) + def subst_string(a, self=self): + if SCons.Util.is_String(a): + a = self.subst(a) + return a + nargs = map(subst_string, args) nkw = self.subst_kw(kw) return apply(SCons.Action.Action, nargs, nkw) |