From: GregNoel Date: Fri, 12 Sep 2008 08:50:56 +0000 (+0000) Subject: Add common subproc function and modify routines to use it X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=0d50f8d6b33c67cab514324d4875f75f733bbcdd;p=scons.git Add common subproc function and modify routines to use it git-svn-id: http://scons.tigris.org/svn/scons/trunk@3389 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index b1585741..f1de15c9 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -103,6 +103,7 @@ import os import os.path import string import sys +import subprocess from SCons.Debug import logInstanceCreation import SCons.Errors @@ -118,8 +119,6 @@ print_actions = 1 execute_actions = 1 print_actions_presub = 0 -default_ENV = None - def rfile(n): try: return n.rfile() @@ -493,6 +492,64 @@ def _string_from_cmd_list(cmd_list): cl.append(arg) return string.join(cl) +# this function is still in draft mode. We're going to need something like +# it in the long run as more and more places use it, but I'm sure it'll have +# to be tweaked to get the full desired functionality. +default_ENV = None +# one special arg, 'error', to tell what to do with exceptions. +def _subproc(env, cmd, error = 'ignore', **kw): + """Do setup for a subprocess.Popen() call""" + + # If the env has no ENV, get a default + try: + ENV = env['ENV'] + except KeyError: + global default_ENV + if default_ENV is None: + # Unbelievably expensive. What it really should do + # is run the platform setup to get the default ENV. + # Fortunately, it should almost never happen. + default_ENV = SCons.Environment.Environment(tools=[])['ENV'] + ENV = default_ENV + + # Ensure that the ENV values are all strings: + new_env = {} + # It's a string 99.44% of the time, so optimize this + is_String = SCons.Util.is_String + for key, value in ENV.items(): + if is_String(value): + new_env[key] = value + elif SCons.Util.is_List(value): + # If the value is a list, then we assume it is a + # path list, because that's a pretty common list-like + # value to stick in an environment variable: + value = SCons.Util.flatten_sequence(value) + ENV[key] = string.join(map(str, value), os.pathsep) + else: + # If it isn't a string or a list, then we just coerce + # it to a string, which is the proper way to handle + # Dir and File instances and will produce something + # reasonable for just about everything else: + ENV[key] = str(value) + kw['env'] = new_env + + try: + #FUTURE return subprocess.Popen(cmd, **kw) + return apply(subprocess.Popen, (cmd,), kw) + except EnvironmentError, e: + if error == 'raise': raise + # return a dummy Popen instance that only returns error + class popen: + def __init__(self, e): self.exception = e + def communicate(): return ('','') + def wait(): return -self.exception.errno + stdin = None + class f: + def read(self): return '' + def readline(self): return '' + stdout = stderr = f() + return popen(e) + class CommandAction(_ActionAction): """Class for command-execution actions.""" def __init__(self, cmd, cmdstr=None, *args, **kw): diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 1a4f5f56..f416bb07 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -534,13 +534,9 @@ class SubstitutionEnvironment: # if the command is a list, assume it's been quoted # othewise force a shell if not SCons.Util.is_List(command): kw['shell'] = True - # a SubstutionEnvironment has no ENV, so only add it - # to the args if it exists - e = self._dict.get('ENV') - if e: kw['env'] = e # run constructed command - #FUTURE p = subprocess.Popen(command, **kw) - p = apply(subprocess.Popen, (command,), kw) + #FUTURE p = Scons.Action._subproc(env, command, **kw) + p = apply(Scons.Action._subproc, (env, command), kw) out = p.stdout.read() p.stdout.close() err = p.stderr.read() diff --git a/src/engine/SCons/Tool/g++.py b/src/engine/SCons/Tool/g++.py index 0745c03f..f8f5b34e 100644 --- a/src/engine/SCons/Tool/g++.py +++ b/src/engine/SCons/Tool/g++.py @@ -63,13 +63,9 @@ def generate(env): env['SHOBJSUFFIX'] = '.pic.o' # determine compiler version if env['CXX']: - try: - pipe = subprocess.Popen([env['CXX'], '--version'], - env=env['ENV'], - stderr = subprocess.PIPE, - stdout = subprocess.PIPE) - except OSError: - return + pipe = SCons.Action._subproc(env, [env['CXX'], '--version'], + stderr = subprocess.PIPE, + stdout = subprocess.PIPE) # -dumpversion was added in GCC 3.0. As long as we're supporting # GCC versions older than that, we should use --version and a # regular expression. diff --git a/src/engine/SCons/Tool/gcc.py b/src/engine/SCons/Tool/gcc.py index 4e81ba84..232d64aa 100644 --- a/src/engine/SCons/Tool/gcc.py +++ b/src/engine/SCons/Tool/gcc.py @@ -53,13 +53,9 @@ def generate(env): env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS -fPIC') # determine compiler version if env['CC']: - try: - pipe = subprocess.Popen([env['CC'], '--version'], - env=env['ENV'], - stderr = subprocess.PIPE, - stdout = subprocess.PIPE) - except OSError: - return + pipe = SCons.Action._subproc(env, [env['CC'], '--version'], + stderr = subprocess.PIPE, + stdout = subprocess.PIPE) # -dumpversion was added in GCC 3.0. As long as we're supporting # GCC versions older than that, we should use --version and a # regular expression.