diff --git a/SConstruct b/SConstruct index df0f16c5d..784770904 100644 --- a/SConstruct +++ b/SConstruct @@ -32,6 +32,44 @@ def get_Werror_string(l): return '-W' return '-Werror=' +class StaticSubprocess: + class CachedCall: + def __init__(self,out,err,returncode): + self.out = out + self.err = err + self.returncode = returncode + __call_cache = {} + @classmethod + def pcall(cls,args,stdout,stderr=None): + a = repr(args) + try: + return cls.__call_cache[a] + except KeyError: + pass + p = subprocess.Popen(args, executable=args[0], stdout=stdout, stderr=stderr, close_fds=True) + (o, e) = p.communicate() + cls.__call_cache[a] = c = cls.CachedCall(o, e, p.wait()) + return c + +class Git(StaticSubprocess): + __missing_git = StaticSubprocess.CachedCall(None, None, 1) + __path_git = None + @classmethod + def pcall(cls,args,stdout,stderr=None): + git = cls.__path_git + if git is None: + cls.__path_git = git = (os.environ.get('GIT', 'git').split(),) + git = git[0] + if not git: + return cls.__missing_git + return StaticSubprocess.pcall(git + args, stdout=stdout, stderr=stderr) + @classmethod + def spcall(cls,args,stdout,stderr=None): + g = cls.pcall(args, stdout, stderr) + if g.returncode: + return None + return g.out + class ConfigureTests: class Collector: def __init__(self): @@ -1369,8 +1407,7 @@ class DXXCommon(LazyObjectConstructor): check_header_includes = os.path.join(builddir, 'check_header_includes.cpp') if not self.__shared_header_file_list: open(check_header_includes, 'wt') - git = subprocess.Popen(['git', 'ls-files', '-z', '--', '*.h'], executable='/usr/bin/git', stdout=subprocess.PIPE, close_fds=True) - headers = git.communicate(None)[0] + headers = Git.pcall(['ls-files', '-z', '--', '*.h'], stdout=subprocess.PIPE).out excluded_directories = ( 'common/arch/cocoa/', 'common/arch/carbon/', @@ -1985,38 +2022,27 @@ class DXXProgram(DXXCommon): def compute_extra_version(cls): c = cls._computed_extra_version if c is None: - git = (os.environ.get('GIT', 'git')).split() - v = s = ds = None - if git: - v = cls._compute_extra_version(git) - if v: - g = subprocess.Popen(git + ['status', '--short', '--branch'], executable=git[0], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - (go, ge) = g.communicate(None) - if not g.wait(): - s = go - g = subprocess.Popen(git + ['diff', '--stat', 'HEAD'], executable=git[0], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - (go, ge) = g.communicate(None) - if not g.wait(): - ds = go + s = ds = None + v = cls._compute_extra_version() + if v: + s = Git.spcall(['status', '--short', '--branch'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + ds = Git.spcall(['diff', '--stat', 'HEAD'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) cls._computed_extra_version = c = (v or '', s, ds) return c @classmethod - def _compute_extra_version(cls, git): + def _compute_extra_version(cls): try: - g = subprocess.Popen(git + ['describe', '--tags', '--abbrev=8'], executable=git[0], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + g = Git.pcall(['describe', '--tags', '--abbrev=8'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) except OSError as e: if e.errno == errno.ENOENT: return None raise - (go, ge) = g.communicate(None) - if g.wait(): + if g.returncode: return None - g = subprocess.Popen(git + ['diff', '--quiet', '--cached'], executable=git[0], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - c = g.wait() - g = subprocess.Popen(git + ['diff', '--quiet'], executable=git[0], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - d = g.wait() - return go.split('\n')[0] + ('+' if c else '') + ('*' if d else '') + c = Git.pcall(['diff', '--quiet', '--cached'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).returncode + d = Git.pcall(['diff', '--quiet'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).returncode + return g.out.split('\n')[0] + ('+' if c else '') + ('*' if d else '') def _register_program(self,dxxstr,program_specific_objects=[]): env = self.env @@ -2045,10 +2071,9 @@ class DXXProgram(DXXCommon): versid_build_environ = ['CXX', 'CPPFLAGS', 'CXXFLAGS', 'LINKFLAGS'] versid_cppdefines = env['CPPDEFINES'][:] versid_cppdefines.extend([('DESCENT_%s' % k, self._quote_cppdefine(env.get(k, ''))) for k in versid_build_environ]) - v = subprocess.Popen(env['CXX'].split(' ') + ['--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - (so,se) = v.communicate(None) - if not v.returncode and (so or se): - v = (so or se).split('\n')[0] + v = StaticSubprocess.pcall(env['CXX'].split(' ') + ['--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if not v.returncode and (v.out or v.err): + v = (v.out or v.err).split('\n')[0] versid_cppdefines.append(('DESCENT_%s' % 'CXX_version', self._quote_cppdefine(v))) versid_build_environ.append('CXX_version') extra_version = self.user_settings.extra_version