diff options
Diffstat (limited to 'src/engine/SCons/Tool/__init__.py')
| -rw-r--r-- | src/engine/SCons/Tool/__init__.py | 601 | 
1 files changed, 360 insertions, 241 deletions
diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 9265b81..271f214 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -14,7 +14,7 @@ tool definition.  """  # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation  #  # Permission is hereby granted, free of charge, to any person obtaining  # a copy of this software and associated documentation files (the @@ -35,16 +35,13 @@ tool definition.  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/__init__.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" -import imp -import importlib  import sys  import re  import os  import shutil -  import SCons.Builder  import SCons.Errors  import SCons.Node.FS @@ -54,9 +51,14 @@ import SCons.Scanner.D  import SCons.Scanner.LaTeX  import SCons.Scanner.Prog  import SCons.Scanner.SWIG -import collections +try: +    # Python 3 +    from collections.abc import Callable +except ImportError: +    # Python 2.7 +    from collections import Callable -DefaultToolpath=[] +DefaultToolpath = []  CScanner = SCons.Scanner.C.CScanner()  DScanner = SCons.Scanner.D.DScanner() @@ -97,20 +99,22 @@ for suffix in LaTeXSuffixes:      SourceFileScanner.add_scanner(suffix, LaTeXScanner)      SourceFileScanner.add_scanner(suffix, PDFLaTeXScanner) -  # Tool aliases are needed for those tools whos module names also  # occur in the python standard library. This causes module shadowing and  # can break using python library functions under python3  TOOL_ALIASES = { -    'gettext':'gettext_tool', +    'gettext': 'gettext_tool',      'clang++': 'clangxx',  } +  class Tool(object): -    def __init__(self, name, toolpath=[], **kw): +    def __init__(self, name, toolpath=None, **kw): +        if toolpath is None: +            toolpath = []          # Rename if there's a TOOL_ALIAS for this tool -        self.name = TOOL_ALIASES.get(name,name) +        self.name = TOOL_ALIASES.get(name, name)          self.toolpath = toolpath + DefaultToolpath          # remember these so we can merge them into the call          self.init_kw = kw @@ -122,6 +126,8 @@ class Tool(object):              self.options = module.options      def _load_dotted_module_py2(self, short_name, full_name, searchpaths=None): +        import imp +          splitname = short_name.split('.')          index = 0          srchpths = searchpaths @@ -136,7 +142,7 @@ class Tool(object):          sys.path = self.toolpath + sys.path          # sys.stderr.write("Tool:%s\nPATH:%s\n"%(self.name,sys.path)) -        if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] in (0,1,2,3,4)): +        if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] in (0, 1, 2, 3, 4)):              # Py 2 code              try:                  try: @@ -149,8 +155,8 @@ class Tool(object):                              file.close()                  except ImportError as e:                      splitname = self.name.split('.') -                    if str(e)!="No module named %s"%splitname[0]: -                        raise SCons.Errors.EnvironmentError(e) +                    if str(e) != "No module named %s" % splitname[0]: +                        raise SCons.Errors.SConsEnvironmentError(e)                      try:                          import zipimport                      except ImportError: @@ -184,46 +190,48 @@ class Tool(object):              add_to_scons_tools_namespace = False              for path in self.toolpath:                  sepname = self.name.replace('.', os.path.sep) -                file_path = os.path.join(path, "%s.py"%sepname) +                file_path = os.path.join(path, "%s.py" % sepname)                  file_package = os.path.join(path, sepname) -                if debug: sys.stderr.write("Trying:%s %s\n"%(file_path, file_package)) +                if debug: sys.stderr.write("Trying:%s %s\n" % (file_path, file_package))                  if os.path.isfile(file_path):                      spec = importlib.util.spec_from_file_location(self.name, file_path) -                    if debug: print("file_Path:%s FOUND"%file_path) +                    if debug: print("file_Path:%s FOUND" % file_path)                      break                  elif os.path.isdir(file_package):                      file_package = os.path.join(file_package, '__init__.py')                      spec = importlib.util.spec_from_file_location(self.name, file_package) -                    if debug: print("PACKAGE:%s Found"%file_package) +                    if debug: print("PACKAGE:%s Found" % file_package)                      break                  else:                      continue              if spec is None: -                if debug: sys.stderr.write("NO SPEC :%s\n"%self.name) -                spec = importlib.util.find_spec("."+self.name, package='SCons.Tool') +                if debug: sys.stderr.write("NO SPEC :%s\n" % self.name) +                spec = importlib.util.find_spec("." + self.name, package='SCons.Tool')                  if spec: -                    found_name = 'SCons.Tool.'+self.name +                    found_name = 'SCons.Tool.' + self.name                      add_to_scons_tools_namespace = True -                if debug: sys.stderr.write("Spec Found? .%s :%s\n"%(self.name, spec)) +                if debug: sys.stderr.write("Spec Found? .%s :%s\n" % (self.name, spec))              if spec is None: -                error_string = "No module named %s"%self.name -                raise SCons.Errors.EnvironmentError(error_string) +                error_string = "No module named %s" % self.name +                raise SCons.Errors.SConsEnvironmentError(error_string)              module = importlib.util.module_from_spec(spec)              if module is None: -                if debug: print("MODULE IS NONE:%s"%self.name) -                error_string = "No module named %s"%self.name -                raise SCons.Errors.EnvironmentError(error_string) +                if debug: print("MODULE IS NONE:%s" % self.name) +                error_string = "No module named %s" % self.name +                raise SCons.Errors.SConsEnvironmentError(error_string)              # Don't reload a tool we already loaded. -            sys_modules_value = sys.modules.get(found_name,False) +            sys_modules_value = sys.modules.get(found_name, False) + +            found_module = None              if sys_modules_value and sys_modules_value.__file__ == spec.origin: -                return sys.modules[found_name] +                found_module = sys.modules[found_name]              else:                  # Not sure what to do in the case that there already                  # exists sys.modules[self.name] but the source file is @@ -235,8 +243,11 @@ class Tool(object):                      # If we found it in SCons.Tool, then add it to the module                      setattr(SCons.Tool, self.name, module) -                return module +                found_module = module +            if found_module is not None: +                sys.path = oldpythonpath +                return found_module          sys.path = oldpythonpath @@ -253,20 +264,20 @@ class Tool(object):                          file.close()                      return module                  except ImportError as e: -                    if str(e)!="No module named %s"%self.name: -                        raise SCons.Errors.EnvironmentError(e) +                    if str(e) != "No module named %s" % self.name: +                        raise SCons.Errors.SConsEnvironmentError(e)                      try:                          import zipimport -                        importer = zipimport.zipimporter( sys.modules['SCons.Tool'].__path__[0] ) +                        importer = zipimport.zipimporter(sys.modules['SCons.Tool'].__path__[0])                          module = importer.load_module(full_name)                          setattr(SCons.Tool, self.name, module)                          return module                      except ImportError as e:                          m = "No tool named '%s': %s" % (self.name, e) -                        raise SCons.Errors.EnvironmentError(m) +                        raise SCons.Errors.SConsEnvironmentError(m)              except ImportError as e:                  m = "No tool named '%s': %s" % (self.name, e) -                raise SCons.Errors.EnvironmentError(m) +                raise SCons.Errors.SConsEnvironmentError(m)      def __call__(self, env, *args, **kw):          if self.init_kw is not None: @@ -278,13 +289,13 @@ class Tool(object):                  kw.update(call_kw)              else:                  kw = self.init_kw -        env.Append(TOOLS = [ self.name ]) +        env.Append(TOOLS=[self.name])          if hasattr(self, 'options'):              import SCons.Variables              if 'options' not in env:                  from SCons.Script import ARGUMENTS -                env['options']=SCons.Variables.Variables(args=ARGUMENTS) -            opts=env['options'] +                env['options'] = SCons.Variables.Variables(args=ARGUMENTS) +            opts = env['options']              self.options(opts)              opts.Update(env) @@ -294,6 +305,7 @@ class Tool(object):      def __str__(self):          return self.name +  ##########################################################################  #  Create common executable program / library / object builders @@ -308,13 +320,13 @@ def createProgBuilder(env):          program = env['BUILDERS']['Program']      except KeyError:          import SCons.Defaults -        program = SCons.Builder.Builder(action = SCons.Defaults.LinkAction, -                                        emitter = '$PROGEMITTER', -                                        prefix = '$PROGPREFIX', -                                        suffix = '$PROGSUFFIX', -                                        src_suffix = '$OBJSUFFIX', -                                        src_builder = 'Object', -                                        target_scanner = ProgramScanner) +        program = SCons.Builder.Builder(action=SCons.Defaults.LinkAction, +                                        emitter='$PROGEMITTER', +                                        prefix='$PROGPREFIX', +                                        suffix='$PROGSUFFIX', +                                        src_suffix='$OBJSUFFIX', +                                        src_builder='Object', +                                        target_scanner=ProgramScanner)          env['BUILDERS']['Program'] = program      return program @@ -330,23 +342,24 @@ def createStaticLibBuilder(env):      try:          static_lib = env['BUILDERS']['StaticLibrary']      except KeyError: -        action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ] -        if env.get('RANLIB',False) or env.Detect('ranlib'): +        action_list = [SCons.Action.Action("$ARCOM", "$ARCOMSTR")] +        if env.get('RANLIB', False) or env.Detect('ranlib'):              ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR")              action_list.append(ranlib_action) -        static_lib = SCons.Builder.Builder(action = action_list, -                                           emitter = '$LIBEMITTER', -                                           prefix = '$LIBPREFIX', -                                           suffix = '$LIBSUFFIX', -                                           src_suffix = '$OBJSUFFIX', -                                           src_builder = 'StaticObject') +        static_lib = SCons.Builder.Builder(action=action_list, +                                           emitter='$LIBEMITTER', +                                           prefix='$LIBPREFIX', +                                           suffix='$LIBSUFFIX', +                                           src_suffix='$OBJSUFFIX', +                                           src_builder='StaticObject')          env['BUILDERS']['StaticLibrary'] = static_lib          env['BUILDERS']['Library'] = static_lib      return static_lib -def _call_linker_cb(env, callback, args, result = None): + +def _call_linker_cb(env, callback, args, result=None):      """Returns the result of env['LINKCALLBACKS'][callback](*args)      if env['LINKCALLBACKS'] is a dictionary and env['LINKCALLBACKS'][callback]      is callable. If these conditions are not met, return the value provided as @@ -370,136 +383,163 @@ def _call_linker_cb(env, callback, args, result = None):          if Verbose:              print('_call_linker_cb: env["LINKCALLBACKS"][%r] found' % callback)              print('_call_linker_cb: env["LINKCALLBACKS"][%r]=%r' % (callback, cbfun)) -        if(isinstance(cbfun, collections.Callable)): +        if isinstance(cbfun, Callable):              if Verbose:                  print('_call_linker_cb: env["LINKCALLBACKS"][%r] is callable' % callback)              result = cbfun(env, *args)      return result +  def _call_env_subst(env, string, *args, **kw):      kw2 = {}      for k in ('raw', 'target', 'source', 'conv', 'executor'): -        try: kw2[k] = kw[k] -        except KeyError: pass +        try: +            kw2[k] = kw[k] +        except KeyError: +            pass      return env.subst(string, *args, **kw2) +  class _ShLibInfoSupport(object): -    def get_libtype(self): +    @property +    def libtype(self):          return 'ShLib' +      def get_lib_prefix(self, env, *args, **kw): -        return _call_env_subst(env,'$SHLIBPREFIX', *args, **kw) +        return _call_env_subst(env, '$SHLIBPREFIX', *args, **kw) +      def get_lib_suffix(self, env, *args, **kw): -        return _call_env_subst(env,'$SHLIBSUFFIX', *args, **kw) +        return _call_env_subst(env, '$SHLIBSUFFIX', *args, **kw) +      def get_lib_version(self, env, *args, **kw): -        return _call_env_subst(env,'$SHLIBVERSION', *args, **kw) +        return _call_env_subst(env, '$SHLIBVERSION', *args, **kw) +      def get_lib_noversionsymlinks(self, env, *args, **kw): -        return _call_env_subst(env,'$SHLIBNOVERSIONSYMLINKS', *args, **kw) +        return _call_env_subst(env, '$SHLIBNOVERSIONSYMLINKS', *args, **kw) +  class _LdModInfoSupport(object): -    def get_libtype(self): +    @property +    def libtype(self):          return 'LdMod' +      def get_lib_prefix(self, env, *args, **kw): -        return _call_env_subst(env,'$LDMODULEPREFIX', *args, **kw) +        return _call_env_subst(env, '$LDMODULEPREFIX', *args, **kw) +      def get_lib_suffix(self, env, *args, **kw): -        return _call_env_subst(env,'$LDMODULESUFFIX', *args, **kw) +        return _call_env_subst(env, '$LDMODULESUFFIX', *args, **kw) +      def get_lib_version(self, env, *args, **kw): -        return _call_env_subst(env,'$LDMODULEVERSION', *args, **kw) +        return _call_env_subst(env, '$LDMODULEVERSION', *args, **kw) +      def get_lib_noversionsymlinks(self, env, *args, **kw): -        return _call_env_subst(env,'$LDMODULENOVERSIONSYMLINKS', *args, **kw) +        return _call_env_subst(env, '$LDMODULENOVERSIONSYMLINKS', *args, **kw) +  class _ImpLibInfoSupport(object): -    def get_libtype(self): +    @property +    def libtype(self):          return 'ImpLib' +      def get_lib_prefix(self, env, *args, **kw): -        return _call_env_subst(env,'$IMPLIBPREFIX', *args, **kw) +        return _call_env_subst(env, '$IMPLIBPREFIX', *args, **kw) +      def get_lib_suffix(self, env, *args, **kw): -        return _call_env_subst(env,'$IMPLIBSUFFIX', *args, **kw) +        return _call_env_subst(env, '$IMPLIBSUFFIX', *args, **kw) +      def get_lib_version(self, env, *args, **kw): -        version = _call_env_subst(env,'$IMPLIBVERSION', *args, **kw) +        version = _call_env_subst(env, '$IMPLIBVERSION', *args, **kw)          if not version: -            try: lt = kw['implib_libtype'] -            except KeyError: pass +            try: +                lt = kw['implib_libtype'] +            except KeyError: +                pass              else:                  if lt == 'ShLib': -                    version = _call_env_subst(env,'$SHLIBVERSION', *args, **kw) +                    version = _call_env_subst(env, '$SHLIBVERSION', *args, **kw)                  elif lt == 'LdMod': -                    version = _call_env_subst(env,'$LDMODULEVERSION', *args, **kw) +                    version = _call_env_subst(env, '$LDMODULEVERSION', *args, **kw)          return version +      def get_lib_noversionsymlinks(self, env, *args, **kw):          disable = None -        try: env['IMPLIBNOVERSIONSYMLINKS'] +        try: +            env['IMPLIBNOVERSIONSYMLINKS']          except KeyError: -            try: lt = kw['implib_libtype'] -            except KeyError: pass +            try: +                lt = kw['implib_libtype'] +            except KeyError: +                pass              else:                  if lt == 'ShLib': -                    disable = _call_env_subst(env,'$SHLIBNOVERSIONSYMLINKS', *args, **kw) +                    disable = _call_env_subst(env, '$SHLIBNOVERSIONSYMLINKS', *args, **kw)                  elif lt == 'LdMod': -                    disable = _call_env_subst(env,'$LDMODULENOVERSIONSYMLINKS', *args, **kw) +                    disable = _call_env_subst(env, '$LDMODULENOVERSIONSYMLINKS', *args, **kw)          else: -            disable = _call_env_subst(env,'$IMPLIBNOVERSIONSYMLINKS', *args, **kw) +            disable = _call_env_subst(env, '$IMPLIBNOVERSIONSYMLINKS', *args, **kw)          return disable +  class _LibInfoGeneratorBase(object):      """Generator base class for library-related info such as suffixes for      versioned libraries, symlink maps, sonames etc. It handles commonities      of SharedLibrary and LoadableModule      """ -    _support_classes = { 'ShLib'  : _ShLibInfoSupport, -                         'LdMod'  : _LdModInfoSupport, -                         'ImpLib' : _ImpLibInfoSupport } +    _support_classes = {'ShLib': _ShLibInfoSupport, +                        'LdMod': _LdModInfoSupport, +                        'ImpLib': _ImpLibInfoSupport} +      def __init__(self, libtype, infoname): -        self.set_libtype(libtype) -        self.set_infoname(infoname) +        self.libtype = libtype +        self.infoname = infoname + +    @property +    def libtype(self): +        return self._support.libtype -    def set_libtype(self, libtype): +    @libtype.setter +    def libtype(self, libtype):          try:              support_class = self._support_classes[libtype]          except KeyError:              raise ValueError('unsupported libtype %r' % libtype)          self._support = support_class() -    def get_libtype(self): -        return self._support.get_libtype() - -    def set_infoname(self, infoname): -        self.infoname = infoname - -    def get_infoname(self): -        return self.infoname -      def get_lib_prefix(self, env, *args, **kw): -        return self._support.get_lib_prefix(env,*args,**kw) +        return self._support.get_lib_prefix(env, *args, **kw)      def get_lib_suffix(self, env, *args, **kw): -        return self._support.get_lib_suffix(env,*args,**kw) +        return self._support.get_lib_suffix(env, *args, **kw)      def get_lib_version(self, env, *args, **kw): -        return self._support.get_lib_version(env,*args,**kw) +        return self._support.get_lib_version(env, *args, **kw)      def get_lib_noversionsymlinks(self, env, *args, **kw): -        return self._support.get_lib_noversionsymlinks(env,*args,**kw) +        return self._support.get_lib_noversionsymlinks(env, *args, **kw)      # Returns name of generator linker callback that shall be used to generate      # our info for a versioned library. For example, if our libtype is 'ShLib'      # and infoname is 'Prefix', it would return 'VersionedShLibPrefix'.      def get_versioned_lib_info_generator(self, **kw): -        try: libtype = kw['generator_libtype'] -        except KeyError: libtype = self.get_libtype() -        infoname = self.get_infoname() -        return 'Versioned%s%s' % (libtype, infoname) +        try: +            libtype = kw['generator_libtype'] +        except KeyError: +            libtype = self.libtype +        return 'Versioned%s%s' % (libtype, self.infoname) -    def generate_versioned_lib_info(self, env, args, result = None, **kw): +    def generate_versioned_lib_info(self, env, args, result=None, **kw):          callback = self.get_versioned_lib_info_generator(**kw)          return _call_linker_cb(env, callback, args, result) +  class _LibPrefixGenerator(_LibInfoGeneratorBase):      """Library prefix generator, used as target_prefix in SharedLibrary and      LoadableModule builders""" +      def __init__(self, libtype):          super(_LibPrefixGenerator, self).__init__(libtype, 'Prefix') -    def __call__(self, env, sources = None, **kw): +    def __call__(self, env, sources=None, **kw):          Verbose = False          if sources and 'source' not in kw: @@ -508,7 +548,7 @@ class _LibPrefixGenerator(_LibInfoGeneratorBase):          else:              kw2 = kw -        prefix = self.get_lib_prefix(env,**kw2) +        prefix = self.get_lib_prefix(env, **kw2)          if Verbose:              print("_LibPrefixGenerator: input prefix=%r" % prefix) @@ -523,17 +563,20 @@ class _LibPrefixGenerator(_LibInfoGeneratorBase):              print("_LibPrefixGenerator: return prefix=%r" % prefix)          return prefix -ShLibPrefixGenerator  = _LibPrefixGenerator('ShLib') -LdModPrefixGenerator  = _LibPrefixGenerator('LdMod') + +ShLibPrefixGenerator = _LibPrefixGenerator('ShLib') +LdModPrefixGenerator = _LibPrefixGenerator('LdMod')  ImpLibPrefixGenerator = _LibPrefixGenerator('ImpLib') +  class _LibSuffixGenerator(_LibInfoGeneratorBase):      """Library suffix generator, used as target_suffix in SharedLibrary and      LoadableModule builders""" +      def __init__(self, libtype):          super(_LibSuffixGenerator, self).__init__(libtype, 'Suffix') -    def __call__(self, env, sources = None, **kw): +    def __call__(self, env, sources=None, **kw):          Verbose = False          if sources and 'source' not in kw: @@ -557,13 +600,16 @@ class _LibSuffixGenerator(_LibInfoGeneratorBase):              print("_LibSuffixGenerator: return suffix=%r" % suffix)          return suffix -ShLibSuffixGenerator  = _LibSuffixGenerator('ShLib') -LdModSuffixGenerator  = _LibSuffixGenerator('LdMod') + +ShLibSuffixGenerator = _LibSuffixGenerator('ShLib') +LdModSuffixGenerator = _LibSuffixGenerator('LdMod')  ImpLibSuffixGenerator = _LibSuffixGenerator('ImpLib') +  class _LibSymlinkGenerator(_LibInfoGeneratorBase):      """Library symlink map generator. It generates a list of symlinks that      should be created by SharedLibrary or LoadableModule builders""" +      def __init__(self, libtype):          super(_LibSymlinkGenerator, self).__init__(libtype, 'Symlinks') @@ -588,18 +634,20 @@ class _LibSymlinkGenerator(_LibInfoGeneratorBase):              print('_LibSymlinkGenerator: disable=%r' % disable)          if version and not disable: -            prefix = self.get_lib_prefix(env,**kw2) -            suffix = self.get_lib_suffix(env,**kw2) +            prefix = self.get_lib_prefix(env, **kw2) +            suffix = self.get_lib_suffix(env, **kw2)              symlinks = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2)          if Verbose:              print('_LibSymlinkGenerator: return symlinks=%r' % StringizeLibSymlinks(symlinks))          return symlinks -ShLibSymlinkGenerator =  _LibSymlinkGenerator('ShLib') -LdModSymlinkGenerator =  _LibSymlinkGenerator('LdMod') + +ShLibSymlinkGenerator = _LibSymlinkGenerator('ShLib') +LdModSymlinkGenerator = _LibSymlinkGenerator('LdMod')  ImpLibSymlinkGenerator = _LibSymlinkGenerator('ImpLib') +  class _LibNameGenerator(_LibInfoGeneratorBase):      """Generates "unmangled" library name from a library file node. @@ -614,6 +662,7 @@ class _LibNameGenerator(_LibInfoGeneratorBase):      the _LibNameGenerator shall return "libfoo.so". Other link tools may      implement it's own way of library name unmangling.      """ +      def __init__(self, libtype):          super(_LibNameGenerator, self).__init__(libtype, 'Name') @@ -636,8 +685,8 @@ class _LibNameGenerator(_LibInfoGeneratorBase):          name = None          if version: -            prefix = self.get_lib_prefix(env,**kw2) -            suffix = self.get_lib_suffix(env,**kw2) +            prefix = self.get_lib_prefix(env, **kw2) +            suffix = self.get_lib_suffix(env, **kw2)              name = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2)          if not name: @@ -648,13 +697,16 @@ class _LibNameGenerator(_LibInfoGeneratorBase):          return name -ShLibNameGenerator =  _LibNameGenerator('ShLib') -LdModNameGenerator =  _LibNameGenerator('LdMod') + +ShLibNameGenerator = _LibNameGenerator('ShLib') +LdModNameGenerator = _LibNameGenerator('LdMod')  ImpLibNameGenerator = _LibNameGenerator('ImpLib') +  class _LibSonameGenerator(_LibInfoGeneratorBase):      """Library soname generator. Returns library soname (e.g. libfoo.so.0) for      a given node (e.g. /foo/bar/libfoo.so.0.1.2)""" +      def __init__(self, libtype):          super(_LibSonameGenerator, self).__init__(libtype, 'Soname') @@ -673,17 +725,17 @@ class _LibSonameGenerator(_LibInfoGeneratorBase):          soname = _call_env_subst(env, '$SONAME', **kw2)          if not soname: -            version = self.get_lib_version(env,**kw2) +            version = self.get_lib_version(env, **kw2)              if Verbose:                  print("_LibSonameGenerator: version=%r" % version)              if version: -                prefix = self.get_lib_prefix(env,**kw2) -                suffix = self.get_lib_suffix(env,**kw2) +                prefix = self.get_lib_prefix(env, **kw2) +                suffix = self.get_lib_suffix(env, **kw2)                  soname = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2)          if not soname:              # fallback to library name (as returned by appropriate _LibNameGenerator) -            soname = _LibNameGenerator(self.get_libtype())(env, libnode) +            soname = _LibNameGenerator(self.libtype)(env, libnode)              if Verbose:                  print("_LibSonameGenerator: FALLBACK: soname=%r" % soname) @@ -692,40 +744,44 @@ class _LibSonameGenerator(_LibInfoGeneratorBase):          return soname -ShLibSonameGenerator =  _LibSonameGenerator('ShLib') -LdModSonameGenerator =  _LibSonameGenerator('LdMod') + +ShLibSonameGenerator = _LibSonameGenerator('ShLib') +LdModSonameGenerator = _LibSonameGenerator('LdMod') +  def StringizeLibSymlinks(symlinks):      """Converts list with pairs of nodes to list with pairs of node paths      (strings). Used mainly for debugging."""      if SCons.Util.is_List(symlinks):          try: -            return [ (k.get_path(), v.get_path()) for k,v in symlinks ] +            return [(k.get_path(), v.get_path()) for k, v in symlinks]          except (TypeError, ValueError):              return symlinks      else:          return symlinks +  def EmitLibSymlinks(env, symlinks, libnode, **kw):      """Used by emitters to handle (shared/versioned) library symlinks"""      Verbose = False      # nodes involved in process... all symlinks + library -    nodes = list(set([ x for x,y in symlinks ] + [libnode])) +    nodes = list(set([x for x, y in symlinks] + [libnode]))      clean_targets = kw.get('clean_targets', [])      if not SCons.Util.is_List(clean_targets): -        clean_targets = [ clean_targets ] +        clean_targets = [clean_targets]      for link, linktgt in symlinks:          env.SideEffect(link, linktgt) -        if(Verbose): +        if (Verbose):              print("EmitLibSymlinks: SideEffect(%r,%r)" % (link.get_path(), linktgt.get_path()))          clean_list = [x for x in nodes if x != linktgt]          env.Clean(list(set([linktgt] + clean_targets)), clean_list) -        if(Verbose): +        if (Verbose):              print("EmitLibSymlinks: Clean(%r,%r)" % (linktgt.get_path(), [x.get_path() for x in clean_list])) +  def CreateLibSymlinks(env, symlinks):      """Physically creates symlinks. The symlinks argument must be a list in      form [ (link, linktarget), ... ], where link and linktarget are SCons @@ -736,38 +792,40 @@ def CreateLibSymlinks(env, symlinks):      for link, linktgt in symlinks:          linktgt = link.get_dir().rel_path(linktgt)          link = link.get_path() -        if(Verbose): +        if (Verbose):              print("CreateLibSymlinks: preparing to add symlink %r -> %r" % (link, linktgt))          # Delete the (previously created) symlink if exists. Let only symlinks          # to be deleted to prevent accidental deletion of source files...          if env.fs.islink(link):              env.fs.unlink(link) -            if(Verbose): +            if (Verbose):                  print("CreateLibSymlinks: removed old symlink %r" % link)          # If a file or directory exists with the same name as link, an OSError          # will be thrown, which should be enough, I think.          env.fs.symlink(linktgt, link) -        if(Verbose): +        if (Verbose):              print("CreateLibSymlinks: add symlink %r -> %r" % (link, linktgt))      return 0 +  def LibSymlinksActionFunction(target, source, env):      for tgt in target: -        symlinks = getattr(getattr(tgt,'attributes', None), 'shliblinks', None) +        symlinks = getattr(getattr(tgt, 'attributes', None), 'shliblinks', None)          if symlinks:              CreateLibSymlinks(env, symlinks)      return 0 +  def LibSymlinksStrFun(target, source, env, *args):      cmd = None      for tgt in target: -        symlinks = getattr(getattr(tgt,'attributes', None), 'shliblinks', None) +        symlinks = getattr(getattr(tgt, 'attributes', None), 'shliblinks', None)          if symlinks:              if cmd is None: cmd = ""              if cmd: cmd += "\n"              cmd += "Create symlinks for: %r" % tgt.get_path()              try: -                linkstr = ', '.join([ "%r->%r" %(k,v) for k,v in StringizeLibSymlinks(symlinks)]) +                linkstr = ', '.join(["%r->%r" % (k, v) for k, v in StringizeLibSymlinks(symlinks)])              except (KeyError, ValueError):                  pass              else: @@ -789,20 +847,21 @@ def createSharedLibBuilder(env):          shared_lib = env['BUILDERS']['SharedLibrary']      except KeyError:          import SCons.Defaults -        action_list = [ SCons.Defaults.SharedCheck, -                        SCons.Defaults.ShLinkAction, -                        LibSymlinksAction ] -        shared_lib = SCons.Builder.Builder(action = action_list, -                                           emitter = "$SHLIBEMITTER", -                                           prefix = ShLibPrefixGenerator, -                                           suffix = ShLibSuffixGenerator, -                                           target_scanner = ProgramScanner, -                                           src_suffix = '$SHOBJSUFFIX', -                                           src_builder = 'SharedObject') +        action_list = [SCons.Defaults.SharedCheck, +                       SCons.Defaults.ShLinkAction, +                       LibSymlinksAction] +        shared_lib = SCons.Builder.Builder(action=action_list, +                                           emitter="$SHLIBEMITTER", +                                           prefix=ShLibPrefixGenerator, +                                           suffix=ShLibSuffixGenerator, +                                           target_scanner=ProgramScanner, +                                           src_suffix='$SHOBJSUFFIX', +                                           src_builder='SharedObject')          env['BUILDERS']['SharedLibrary'] = shared_lib      return shared_lib +  def createLoadableModuleBuilder(env):      """This is a utility function that creates the LoadableModule      Builder in an Environment if it is not there already. @@ -814,20 +873,21 @@ def createLoadableModuleBuilder(env):          ld_module = env['BUILDERS']['LoadableModule']      except KeyError:          import SCons.Defaults -        action_list = [ SCons.Defaults.SharedCheck, -                        SCons.Defaults.LdModuleLinkAction, -                        LibSymlinksAction ] -        ld_module = SCons.Builder.Builder(action = action_list, -                                          emitter = "$LDMODULEEMITTER", -                                          prefix = LdModPrefixGenerator, -                                          suffix = LdModSuffixGenerator, -                                          target_scanner = ProgramScanner, -                                          src_suffix = '$SHOBJSUFFIX', -                                          src_builder = 'SharedObject') +        action_list = [SCons.Defaults.SharedCheck, +                       SCons.Defaults.LdModuleLinkAction, +                       LibSymlinksAction] +        ld_module = SCons.Builder.Builder(action=action_list, +                                          emitter="$LDMODULEEMITTER", +                                          prefix=LdModPrefixGenerator, +                                          suffix=LdModSuffixGenerator, +                                          target_scanner=ProgramScanner, +                                          src_suffix='$SHOBJSUFFIX', +                                          src_builder='SharedObject')          env['BUILDERS']['LoadableModule'] = ld_module      return ld_module +  def createObjBuilders(env):      """This is a utility function that creates the StaticObject      and SharedObject Builders in an Environment if they @@ -841,34 +901,34 @@ def createObjBuilders(env):      The return is a 2-tuple of (StaticObject, SharedObject)      """ -      try:          static_obj = env['BUILDERS']['StaticObject']      except KeyError: -        static_obj = SCons.Builder.Builder(action = {}, -                                           emitter = {}, -                                           prefix = '$OBJPREFIX', -                                           suffix = '$OBJSUFFIX', -                                           src_builder = ['CFile', 'CXXFile'], -                                           source_scanner = SourceFileScanner, -                                           single_source = 1) +        static_obj = SCons.Builder.Builder(action={}, +                                           emitter={}, +                                           prefix='$OBJPREFIX', +                                           suffix='$OBJSUFFIX', +                                           src_builder=['CFile', 'CXXFile'], +                                           source_scanner=SourceFileScanner, +                                           single_source=1)          env['BUILDERS']['StaticObject'] = static_obj          env['BUILDERS']['Object'] = static_obj      try:          shared_obj = env['BUILDERS']['SharedObject']      except KeyError: -        shared_obj = SCons.Builder.Builder(action = {}, -                                           emitter = {}, -                                           prefix = '$SHOBJPREFIX', -                                           suffix = '$SHOBJSUFFIX', -                                           src_builder = ['CFile', 'CXXFile'], -                                           source_scanner = SourceFileScanner, -                                           single_source = 1) +        shared_obj = SCons.Builder.Builder(action={}, +                                           emitter={}, +                                           prefix='$SHOBJPREFIX', +                                           suffix='$SHOBJSUFFIX', +                                           src_builder=['CFile', 'CXXFile'], +                                           source_scanner=SourceFileScanner, +                                           single_source=1)          env['BUILDERS']['SharedObject'] = shared_obj      return (static_obj, shared_obj) +  def createCFileBuilders(env):      """This is a utility function that creates the CFile/CXXFile      Builders in an Environment if they @@ -885,95 +945,109 @@ def createCFileBuilders(env):      try:          c_file = env['BUILDERS']['CFile']      except KeyError: -        c_file = SCons.Builder.Builder(action = {}, -                                       emitter = {}, -                                       suffix = {None:'$CFILESUFFIX'}) +        c_file = SCons.Builder.Builder(action={}, +                                       emitter={}, +                                       suffix={None: '$CFILESUFFIX'})          env['BUILDERS']['CFile'] = c_file -        env.SetDefault(CFILESUFFIX = '.c') +        env.SetDefault(CFILESUFFIX='.c')      try:          cxx_file = env['BUILDERS']['CXXFile']      except KeyError: -        cxx_file = SCons.Builder.Builder(action = {}, -                                         emitter = {}, -                                         suffix = {None:'$CXXFILESUFFIX'}) +        cxx_file = SCons.Builder.Builder(action={}, +                                         emitter={}, +                                         suffix={None: '$CXXFILESUFFIX'})          env['BUILDERS']['CXXFile'] = cxx_file -        env.SetDefault(CXXFILESUFFIX = '.cc') +        env.SetDefault(CXXFILESUFFIX='.cc')      return (c_file, cxx_file) +  ##########################################################################  #  Create common Java builders  def CreateJarBuilder(env): +    """The Jar builder expects a list of class files +    which it can package into a jar file. + +    The jar tool provides an interface for passing other types +    of java files such as .java, directories or swig interfaces +    and will build them to class files in which it can package +    into the jar. +    """      try: -        java_jar = env['BUILDERS']['Jar'] +        java_jar = env['BUILDERS']['JarFile']      except KeyError:          fs = SCons.Node.FS.get_default_fs()          jar_com = SCons.Action.Action('$JARCOM', '$JARCOMSTR') -        java_jar = SCons.Builder.Builder(action = jar_com, -                                         suffix = '$JARSUFFIX', -                                         src_suffix = '$JAVACLASSSUFFIX', -                                         src_builder = 'JavaClassFile', -                                         source_factory = fs.Entry) -        env['BUILDERS']['Jar'] = java_jar +        java_jar = SCons.Builder.Builder(action=jar_com, +                                         suffix='$JARSUFFIX', +                                         src_suffix='$JAVACLASSSUFFIX', +                                         src_builder='JavaClassFile', +                                         source_factory=fs.Entry) +        env['BUILDERS']['JarFile'] = java_jar      return java_jar +  def CreateJavaHBuilder(env):      try:          java_javah = env['BUILDERS']['JavaH']      except KeyError:          fs = SCons.Node.FS.get_default_fs()          java_javah_com = SCons.Action.Action('$JAVAHCOM', '$JAVAHCOMSTR') -        java_javah = SCons.Builder.Builder(action = java_javah_com, -                                           src_suffix = '$JAVACLASSSUFFIX', -                                           target_factory = fs.Entry, -                                           source_factory = fs.File, -                                           src_builder = 'JavaClassFile') +        java_javah = SCons.Builder.Builder(action=java_javah_com, +                                           src_suffix='$JAVACLASSSUFFIX', +                                           target_factory=fs.Entry, +                                           source_factory=fs.File, +                                           src_builder='JavaClassFile')          env['BUILDERS']['JavaH'] = java_javah      return java_javah +  def CreateJavaClassFileBuilder(env):      try:          java_class_file = env['BUILDERS']['JavaClassFile']      except KeyError:          fs = SCons.Node.FS.get_default_fs()          javac_com = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR') -        java_class_file = SCons.Builder.Builder(action = javac_com, -                                                emitter = {}, -                                                #suffix = '$JAVACLASSSUFFIX', -                                                src_suffix = '$JAVASUFFIX', -                                                src_builder = ['JavaFile'], -                                                target_factory = fs.Entry, -                                                source_factory = fs.File) +        java_class_file = SCons.Builder.Builder(action=javac_com, +                                                emitter={}, +                                                # suffix = '$JAVACLASSSUFFIX', +                                                src_suffix='$JAVASUFFIX', +                                                src_builder=['JavaFile'], +                                                target_factory=fs.Entry, +                                                source_factory=fs.File)          env['BUILDERS']['JavaClassFile'] = java_class_file      return java_class_file +  def CreateJavaClassDirBuilder(env):      try:          java_class_dir = env['BUILDERS']['JavaClassDir']      except KeyError:          fs = SCons.Node.FS.get_default_fs()          javac_com = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR') -        java_class_dir = SCons.Builder.Builder(action = javac_com, -                                               emitter = {}, -                                               target_factory = fs.Dir, -                                               source_factory = fs.Dir) +        java_class_dir = SCons.Builder.Builder(action=javac_com, +                                               emitter={}, +                                               target_factory=fs.Dir, +                                               source_factory=fs.Dir)          env['BUILDERS']['JavaClassDir'] = java_class_dir      return java_class_dir +  def CreateJavaFileBuilder(env):      try:          java_file = env['BUILDERS']['JavaFile']      except KeyError: -        java_file = SCons.Builder.Builder(action = {}, -                                          emitter = {}, -                                          suffix = {None:'$JAVASUFFIX'}) +        java_file = SCons.Builder.Builder(action={}, +                                          emitter={}, +                                          suffix={None: '$JAVASUFFIX'})          env['BUILDERS']['JavaFile'] = java_file          env['JAVASUFFIX'] = '.java'      return java_file +  class ToolInitializerMethod(object):      """      This is added to a construction environment in place of a @@ -984,6 +1058,7 @@ class ToolInitializerMethod(object):      whatever builder was (presumably) added to the construction      environment in place of this particular instance.      """ +      def __init__(self, name, initializer):          """          Note:  we store the tool name as __name__ so it can be used by @@ -1022,6 +1097,7 @@ class ToolInitializerMethod(object):              return [], []          return builder(*args, **kw) +  class ToolInitializer(object):      """      A class for delayed initialization of Tools modules. @@ -1033,6 +1109,7 @@ class ToolInitializer(object):      ToolInitializerMethod objects for the various Builder methods      that we want to use to delay Tool searches until necessary.      """ +      def __init__(self, env, tools, names):          if not SCons.Util.is_List(tools):              tools = [tools] @@ -1067,24 +1144,30 @@ class ToolInitializer(object):                  env.Tool(tool)                  return -	# If we fall through here, there was no tool module found. -	# This is where we can put an informative error message -	# about the inability to find the tool.   We'll start doing -	# this as we cut over more pre-defined Builder+Tools to use -	# the ToolInitializer class. +        # If we fall through here, there was no tool module found. +        # This is where we can put an informative error message +        # about the inability to find the tool.   We'll start doing +        # this as we cut over more pre-defined Builder+Tools to use +        # the ToolInitializer class. +  def Initializers(env):      ToolInitializer(env, ['install'], ['_InternalInstall', '_InternalInstallAs', '_InternalInstallVersionedLib']) +      def Install(self, *args, **kw):          return self._InternalInstall(*args, **kw) +      def InstallAs(self, *args, **kw):          return self._InternalInstallAs(*args, **kw) +      def InstallVersionedLib(self, *args, **kw):          return self._InternalInstallVersionedLib(*args, **kw) +      env.AddMethod(Install)      env.AddMethod(InstallAs)      env.AddMethod(InstallVersionedLib) +  def FindTool(tools, env):      for tool in tools:          t = Tool(tool) @@ -1092,14 +1175,16 @@ def FindTool(tools, env):              return tool      return None +  def FindAllTools(tools, env):      def ToolExists(tool, env=env):          return Tool(tool).exists(env) -    return list(filter (ToolExists, tools)) -def tool_list(platform, env): +    return list(filter(ToolExists, tools)) -    other_plat_tools=[] + +def tool_list(platform, env): +    other_plat_tools = []      # XXX this logic about what tool to prefer on which platform      #     should be moved into either the platform files or      #     the tool files themselves. @@ -1107,21 +1192,21 @@ def tool_list(platform, env):      # change these search orders, update the man page as well.      if str(platform) == 'win32':          "prefer Microsoft tools on Windows" -        linkers = ['mslink', 'gnulink', 'ilink', 'linkloc', 'ilink32' ] -        c_compilers = ['msvc', 'mingw', 'gcc', 'intelc', 'icl', 'icc', 'cc', 'bcc32' ] -        cxx_compilers = ['msvc', 'intelc', 'icc', 'g++', 'cxx', 'bcc32' ] -        assemblers = ['masm', 'nasm', 'gas', '386asm' ] +        linkers = ['mslink', 'gnulink', 'ilink', 'linkloc', 'ilink32'] +        c_compilers = ['msvc', 'mingw', 'gcc', 'intelc', 'icl', 'icc', 'cc', 'bcc32'] +        cxx_compilers = ['msvc', 'intelc', 'icc', 'g++', 'cxx', 'bcc32'] +        assemblers = ['masm', 'nasm', 'gas', '386asm']          fortran_compilers = ['gfortran', 'g77', 'ifl', 'cvf', 'f95', 'f90', 'fortran']          ars = ['mslib', 'ar', 'tlib']          other_plat_tools = ['msvs', 'midl']      elif str(platform) == 'os2':          "prefer IBM tools on OS/2" -        linkers = ['ilink', 'gnulink', ]#'mslink'] -        c_compilers = ['icc', 'gcc',]# 'msvc', 'cc'] -        cxx_compilers = ['icc', 'g++',]# 'msvc', 'cxx'] -        assemblers = ['nasm',]# 'masm', 'gas'] +        linkers = ['ilink', 'gnulink', ]  # 'mslink'] +        c_compilers = ['icc', 'gcc', ]  # 'msvc', 'cc'] +        cxx_compilers = ['icc', 'g++', ]  # 'msvc', 'cxx'] +        assemblers = ['nasm', ]  # 'masm', 'gas']          fortran_compilers = ['ifl', 'g77'] -        ars = ['ar',]# 'mslib'] +        ars = ['ar', ]  # 'mslib']      elif str(platform) == 'irix':          "prefer MIPSPro on IRIX"          linkers = ['sgilink', 'gnulink'] @@ -1174,11 +1259,11 @@ def tool_list(platform, env):      else:          "prefer GNU tools on all other platforms"          linkers = ['gnulink', 'ilink'] -        c_compilers = ['gcc',  'intelc', 'icc', 'cc'] +        c_compilers = ['gcc', 'intelc', 'icc', 'cc']          cxx_compilers = ['g++', 'intelc', 'icc', 'cxx']          assemblers = ['gas', 'nasm', 'masm']          fortran_compilers = ['gfortran', 'g77', 'ifort', 'ifl', 'f95', 'f90', 'f77'] -        ars = ['ar',] +        ars = ['ar', ]      if not str(platform) == 'win32':          other_plat_tools += ['m4', 'rpm'] @@ -1210,22 +1295,24 @@ def tool_list(platform, env):      d_compiler = FindTool(d_compilers, env) or d_compilers[0]      other_tools = FindAllTools(other_plat_tools + [ -                               #TODO: merge 'install' into 'filesystem' and -                               # make 'filesystem' the default -                               'filesystem', -                               'wix', #'midl', 'msvs', -                               # Parser generators -                               'lex', 'yacc', -                               # Foreign function interface -                               'rpcgen', 'swig', -                               # Java -                               'jar', 'javac', 'javah', 'rmic', -                               # TeX -                               'dvipdf', 'dvips', 'gs', -                               'tex', 'latex', 'pdflatex', 'pdftex', -                               # Archivers -                               'tar', 'zip', -                               ], env) +        # TODO: merge 'install' into 'filesystem' and +        # make 'filesystem' the default +        'filesystem', +        'wix',  # 'midl', 'msvs', +        # Parser generators +        'lex', 'yacc', +        # Foreign function interface +        'rpcgen', 'swig', +        # Java +        'jar', 'javac', 'javah', 'rmic', +        # TeX +        'dvipdf', 'dvips', 'gs', +        'tex', 'latex', 'pdflatex', 'pdftex', +        # Archivers +        'tar', 'zip', +        # File builders (text) +        'textfile', +    ], env)      tools = ([linker, c_compiler, cxx_compiler,                fortran_compiler, assembler, ar, d_compiler] @@ -1233,6 +1320,38 @@ def tool_list(platform, env):      return [x for x in tools if x] + +def find_program_path(env, key_program, default_paths=None): +    """ +    Find the location of a tool using various means. + +    Mainly for windows where tools aren't all installed in /usr/bin, etc. + +    :param env: Current Construction Environment. +    :param key_program: Tool to locate. +    :param default_paths: List of additional paths this tool might be found in. +    """ +    # First search in the SCons path +    path = env.WhereIs(key_program) +    if path: +        return path + +    # Then in the OS path +    path = SCons.Util.WhereIs(key_program) +    if path: +        return path + +    # Finally, add the defaults and check again. Do not change +    # ['ENV']['PATH'] permananetly, the caller can do that if needed. +    if default_paths is None: +        return path +    save_path = env['ENV']['PATH'] +    for p in default_paths: +        env.AppendENVPath('PATH', p) +    path = env.WhereIs(key_program) +    env['ENV']['PATH'] = save_path +    return path +  # Local Variables:  # tab-width:4  # indent-tabs-mode:nil  | 
