diff options
| -rw-r--r-- | src/engine/SCons/Tool/__init__.py | 98 | ||||
| -rw-r--r-- | src/engine/SCons/Tool/cyglink.py | 48 | ||||
| -rw-r--r-- | src/engine/SCons/Tool/gnulink.py | 56 | ||||
| -rw-r--r-- | src/engine/SCons/Tool/link.py | 35 | 
4 files changed, 148 insertions, 89 deletions
| diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 0e6e7d8..0b09a13 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -236,31 +236,31 @@ def createStaticLibBuilder(env):      return static_lib -def _call_env_cb(env, callback, args, result = None): -    """Returns the result of env[callback](*args) call if env[callback] is -    callable. If env[callback] does not exist or is not callable, return the -    value provided as the *result* argument. This function is mainly used for -    generating library info such as versioned suffixes, symlink maps, sonames -    etc. by delegating the core job to callbacks configured by current linker -    tool""" +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 meet, return the value provided as +    the *result* argument. This function is mainly used for generating library +    info such as versioned suffixes, symlink maps, sonames etc. by delegating +    the core job to callbacks configured by current linker tool"""      Verbose = False      if Verbose: -        print '_call_env_cb: args=%r' % args -        print '_call_env_cb: callback=%r' % callback - +        print '_call_linker_cb: args=%r' % args +        print '_call_linker_cb: callback=%r' % callback +          try: -        cbfun = env[callback] -    except KeyError: +        cbfun = env['LINKCALLBACKS'][callback] +    except (KeyError, TypeError):          pass      else:          if Verbose: -            print '_call_env_cb: env[%r] found' % callback -            print '_call_env_cb: env[%r]=%r' % (callback, cbfun) +            print '_call_linker_cb: env[%r] found' % callback +            print '_call_linker_cb: env[%r]=%r' % (callback, cbfun)          if(callable(cbfun)):              if Verbose: -                print '_call_env_cb: env[%r] is callable' % callback +                print '_call_linker_cb: env[%r] is callable' % callback              result = cbfun(env, *args)      return result @@ -298,6 +298,17 @@ class _LibInfoGeneratorBase(object):              prefix = env.subst('$IMPLIBPREFIX')          return prefix +    def get_lib_prefix(self, env): +        prefix = None +        libtype = self.get_libtype() +        if libtype == 'ShLib': +            prefix = env.subst('$SHLIBPREFIX') +        elif libtype == 'LdMod': +            prefix = env.subst('$LDMODULEPREFIX') +        elif libtype == 'ImpLib': +            prefix = env.subst('$IMPLIBPREFIX') +        return prefix +      def get_lib_suffix(self, env):          suffix = None          libtype = self.get_libtype() @@ -332,11 +343,39 @@ class _LibInfoGeneratorBase(object):          try: libtype = kw['generator_libtype']          except KeyError: libtype = self.get_libtype()          infoname = self.get_infoname() -        return 'GenerateVersioned%s%s' % (libtype, infoname) +        return 'Versioned%s%s' % (libtype, infoname)      def generate_versioned_lib_info(self, env, args, result = None, **kw):          callback = self.get_versioned_lib_info_generator(**kw) -        return _call_env_cb(env, callback, args, result)  +        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): +        Verbose = False + +        prefix = self.get_lib_prefix(env) +        if Verbose: +            print "_LibPrefixGenerator: input prefix=%r" % prefix + +        version = self.get_lib_version(env, **kw) +        if Verbose: +            print "_LibPrefixGenerator: version=%r" % version + +        if version: +            prefix = self.generate_versioned_lib_info(env, [prefix, version], prefix, **kw) + +        if Verbose: +            print "_LibPrefixGenerator: return prefix=%r" % prefix +        return prefix + +ShLibPrefixGenerator  = _LibPrefixGenerator('ShLib') +LdModPrefixGenerator  = _LibPrefixGenerator('LdMod') +ImpLibPrefixGenerator = _LibPrefixGenerator('ImpLib')  class _LibSuffixGenerator(_LibInfoGeneratorBase):      """Library suffix generator, used as target_suffix in SharedLibrary and @@ -408,8 +447,9 @@ class _LibSymlinkGenerator(_LibInfoGeneratorBase):              print '_LibSymlinkGenerator: disable=%r' % disable          if version and not disable: +            prefix = self.get_lib_prefix(env)              suffix = self.get_lib_suffix(env) -            symlinks = self.generate_versioned_lib_info(env, [libnode, version, suffix], **kw) +            symlinks = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw)          if Verbose:              print '_LibSymlinkGenerator: return symlinks=%r' % StringizeLibSymlinks(symlinks) @@ -420,8 +460,19 @@ LdModSymlinkGenerator =  _LibSymlinkGenerator('LdMod')  ImpLibSymlinkGenerator = _LibSymlinkGenerator('ImpLib')  class _LibNameGenerator(_LibInfoGeneratorBase): -    """Library name generator. Returns library name (e.g. libfoo.so) for  -    a given node (e.g. /foo/bar/libfoo.so.0.1.2)""" +    """Generates "unmangled" library name from a library file node. +     +    Generally, it's thought to revert modifications done by prefix/suffix +    generators (_LibPrefixGenerator/_LibSuffixGenerator) used by a library +    builder. For example, on gnulink the suffix generator used by SharedLibrary +    builder appends $SHLIBVERSION to $SHLIBSUFFIX producing node name which +    ends with "$SHLIBSUFFIX.$SHLIBVERSION". Correspondingly, the implementation +    of _LibNameGenerator replaces "$SHLIBSUFFIX.$SHLIBVERSION" with +    "$SHLIBSUFFIX" in the node's basename. So that, if $SHLIBSUFFIX is ".so", +    $SHLIBVERSION is "0.1.2" and the node path is "/foo/bar/libfoo.so.0.1.2", +    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') @@ -438,8 +489,9 @@ class _LibNameGenerator(_LibInfoGeneratorBase):          name = None          if version: +            prefix = self.get_lib_prefix(env)              suffix = self.get_lib_suffix(env) -            name = self.generate_versioned_lib_info(env, [libnode, version, suffix], **kw) +            name = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw)          if not name:              name = os.path.basename(libnode.get_path()) @@ -566,7 +618,7 @@ def createSharedLibBuilder(env):                          LibSymlinksAction ]          shared_lib = SCons.Builder.Builder(action = action_list,                                             emitter = "$SHLIBEMITTER", -                                           prefix = '$SHLIBPREFIX', +                                           prefix = ShLibPrefixGenerator,                                             suffix = ShLibSuffixGenerator,                                             target_scanner = ProgramScanner,                                             src_suffix = '$SHOBJSUFFIX', @@ -591,7 +643,7 @@ def createLoadableModuleBuilder(env):                          LibSymlinksAction ]          ld_module = SCons.Builder.Builder(action = action_list,                                            emitter = "$LDMODULEEMITTER", -                                          prefix = '$LDMODULEPREFIX', +                                          prefix = ShLibPrefixGenerator,                                            suffix = LdModSuffixGenerator,                                            target_scanner = ProgramScanner,                                            src_suffix = '$SHOBJSUFFIX', diff --git a/src/engine/SCons/Tool/cyglink.py b/src/engine/SCons/Tool/cyglink.py index 59258b2..e05e85f 100644 --- a/src/engine/SCons/Tool/cyglink.py +++ b/src/engine/SCons/Tool/cyglink.py @@ -15,6 +15,7 @@ import SCons.Util  import SCons.Tool  import gnulink +import link  def _lib_generator(target, source, env, for_signature, **kw):      try: cmd = kw['cmd'] @@ -135,13 +136,13 @@ def _versioned_lib_suffix(env, suffix, version):          print "_versioned_lib_suffix: return suffix= ", suffix      return suffix -def _versioned_implib_name(env, libnode, version, suffix, **kw): -    import link -    generator = SCons.Tool.ImpLibSuffixGenerator -    libtype = kw['libtype'] -    return link._versioned_lib_name(env, libnode, version, suffix, generator, implib_libtype=libtype) +def _versioned_implib_name(env, libnode, version, prefix, suffix, **kw): +    return link._versioned_lib_name(env, libnode, version, prefix, suffix, +                                    SCons.Tool.ImpLibPrefixGenerator, +                                    SCons.Tool.ImpLibSuffixGenerator, +                                    implib_libtype=kw['libtype']) -def _versioned_implib_symlinks(env, libnode, version, suffix, **kw): +def _versioned_implib_symlinks(env, libnode, version, prefix, suffix, **kw):      """Generate link names that should be created for a versioned shared lirbrary.         Returns a list in the form [ (link, linktarget), ... ]      """ @@ -201,27 +202,24 @@ def generate(env):      # SHLIBVERSIONFLAGS and LDMODULEVERSIONFLAGS are same as in gnulink... -    env['GenerateVersionedShLibSuffix']          = _versioned_lib_suffix -    env['GenerateVersionedLdModSuffix']          = _versioned_lib_suffix -    env['GenerateVersionedImpLibSuffix']         = _versioned_lib_suffix -    env['GenerateVersionedShLibImpLibName']      = lambda *args: _versioned_implib_name(*args, libtype='ShLib') -    env['GenerateVersionedLdModImpLibName']      = lambda *args: _versioned_implib_name(*args, libtype='LdMod') -    env['GenerateVersionedShLibImpLibSymlinks']  = lambda *args: _versioned_implib_symlinks(*args, libtype='ShLib') -    env['GenerateVersionedLdModImpLibSymlinks']  = lambda *args: _versioned_implib_symlinks(*args, libtype='LdMod') - -    def trydel(env, key): -        try: del env[key] -        except KeyError: pass +    # LINKCALLBACKS are NOT inherited from gnulink +    env['LINKCALLBACKS'] = { +        'VersionedShLibSuffix'          : _versioned_lib_suffix, +        'VersionedLdModSuffix'          : _versioned_lib_suffix, +        'VersionedImpLibSuffix'         : _versioned_lib_suffix, +        'VersionedShLibName'            : link._versioned_shlib_name, +        'VersionedLdModName'            : link._versioned_ldmod_name, +        'VersionedShLibImpLibName'      : lambda *args: _versioned_implib_name(*args, libtype='ShLib'), +        'VersionedLdModImpLibName'      : lambda *args: _versioned_implib_name(*args, libtype='LdMod'), +        'VersionedShLibImpLibSymlinks'  : lambda *args: _versioned_implib_symlinks(*args, libtype='ShLib'), +        'VersionedLdModImpLibSymlinks'  : lambda *args: _versioned_implib_symlinks(*args, libtype='LdMod'), +    }      # these variables were set by gnulink but are not used in cyglink -    trydel(env,'_SHLINKSONAME') -    trydel(env,'_LDMODULESONAME') -    trydel(env,'ShLibSonameGenerator') -    trydel(env,'LdModSonameGenerator') -    trydel(env,'GenerateVersionedShLibSymlinks') -    trydel(env,'GenerateVersionedLdModSymlinks') -    trydel(env,'GenerateVersionedShLibSoname') -    trydel(env,'GenerateVersionedLdModSoname') +    try: del env['_SHLINKSONAME'] +    except KeyError: pass +    try: del env['_LDMODULESONAME'] +    except KeyError: pass  def exists(env):      return gnulink.exists(env) diff --git a/src/engine/SCons/Tool/gnulink.py b/src/engine/SCons/Tool/gnulink.py index 14007af..e5e8818 100644 --- a/src/engine/SCons/Tool/gnulink.py +++ b/src/engine/SCons/Tool/gnulink.py @@ -53,12 +53,12 @@ def _versioned_lib_suffix(env, suffix, version):          print "_versioned_lib_suffix: return suffix=%r" % suffix      return suffix -def _versioned_lib_soname(env, libnode, version, suffix, name_generator): +def _versioned_lib_soname(env, libnode, version, prefix, suffix, name_func):      """For libnode='/optional/dir/libfoo.so.X.Y.Z' it returns 'libfoo.so.X'"""      Verbose = False      if Verbose:          print "_versioned_lib_soname: version=%r" % version -    name = name_generator(env, libnode) +    name = name_func(env, libnode, version, prefix, suffix)      if Verbose:          print "_versioned_lib_soname: name=%r" % name      major = version.split('.')[0] @@ -67,22 +67,20 @@ def _versioned_lib_soname(env, libnode, version, suffix, name_generator):          print "_versioned_lib_soname: soname=%r" % soname      return soname -def _versioned_shlib_soname(env, libnode, version, suffix): -    generator = SCons.Tool.ShLibNameGenerator -    return _versioned_lib_soname(env, libnode, version, suffix, generator)  +def _versioned_shlib_soname(env, libnode, version, prefix, suffix): +    return _versioned_lib_soname(env, libnode, version, prefix, suffix, link._versioned_shlib_name)  -def _versioned_ldmod_soname(env, libnode, version, suffix): -    generator = SCons.Tool.LdModNameGenerator -    return _versioned_lib_soname(env, libnode, version, suffix, generator)  +def _versioned_ldmod_soname(env, libnode, version, prefix, suffix): +    return _versioned_lib_soname(env, libnode, version, prefix, suffix, link._versioned_ldmod_name)  -def _versioned_lib_symlinks(env, libnode, version, suffix, name_generator, soname_generator): +def _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func):      """Generate link names that should be created for a versioned shared lirbrary.         Returns a dictionary in the form { linkname : linktarget }      """      Verbose = False      if Verbose: -        print "_versioned_lib_symlinks: str(libnode)=%r" % str(libnode) +        print "_versioned_lib_symlinks: libnode=%r" % libnode.get_path()          print "_versioned_lib_symlinks: version=%r" % version      if sys.platform.startswith('openbsd'): @@ -96,11 +94,11 @@ def _versioned_lib_symlinks(env, libnode, version, suffix, name_generator, sonam      if Verbose:          print "_versioned_lib_symlinks: linkdir=%r" % linkdir.get_path() -    name = name_generator(env, libnode) +    name = name_func(env, libnode, version, prefix, suffix)      if Verbose:          print "_versioned_lib_symlinks: name=%r" % name -    soname = soname_generator(env, libnode) +    soname = soname_func(env, libnode, version, prefix, suffix)      link0 = env.fs.File(soname, linkdir)      link1 = env.fs.File(name, linkdir) @@ -112,15 +110,15 @@ def _versioned_lib_symlinks(env, libnode, version, suffix, name_generator, sonam      return symlinks -def _versioned_shlib_symlinks(env, libnode, version, suffix): -    name_generator = SCons.Tool.ShLibNameGenerator -    soname_generator = SCons.Tool.ShLibSonameGenerator -    return _versioned_lib_symlinks(env, libnode, version, suffix, name_generator, soname_generator) +def _versioned_shlib_symlinks(env, libnode, version, prefix, suffix): +    nf = link._versioned_shlib_name +    sf = _versioned_shlib_soname +    return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, nf, sf) -def _versioned_ldmod_symlinks(env, libnode, version, suffix): -    name_generator = SCons.Tool.LdModNameGenerator -    soname_generator = SCons.Tool.LdModSonameGenerator -    return _versioned_lib_symlinks(env, libnode, version, suffix, name_generator, soname_generator) +def _versioned_ldmod_symlinks(env, libnode, version, prefix, suffix): +    nf = link._versioned_ldmod_name +    sf = _versioned_ldmod_soname +    return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, nf, sf)  def generate(env):      """Add Builders and construction variables for gnulink to an Environment.""" @@ -155,14 +153,16 @@ def generate(env):      env['ShLibSonameGenerator'] = SCons.Tool.ShLibSonameGenerator      env['LdModSonameGenerator'] = SCons.Tool.LdModSonameGenerator -    env['GenerateVersionedShLibSuffix']   = _versioned_lib_suffix -    env['GenerateVersionedLdModSuffix']   = _versioned_lib_suffix -    env['GenerateVersionedShLibSymlinks'] = _versioned_shlib_symlinks -    env['GenerateVersionedLdModSymlinks'] = _versioned_ldmod_symlinks -    env['GenerateVersionedShLibName']     = link._versioned_shlib_name -    env['GenerateVersionedLdModName']     = link._versioned_ldmod_name -    env['GenerateVersionedShLibSoname']   = _versioned_shlib_soname -    env['GenerateVersionedLdModSoname']   = _versioned_shlib_soname +    env['LINKCALLBACKS'] = { +        'VersionedShLibSuffix'   : _versioned_lib_suffix, +        'VersionedLdModSuffix'   : _versioned_lib_suffix, +        'VersionedShLibSymlinks' : _versioned_shlib_symlinks, +        'VersionedLdModSymlinks' : _versioned_ldmod_symlinks, +        'VersionedShLibName'     : link._versioned_shlib_name, +        'VersionedLdModName'     : link._versioned_ldmod_name, +        'VersionedShLibSoname'   : _versioned_shlib_soname, +        'VersionedLdModSoname'   : _versioned_shlib_soname, +    }  def exists(env):      # TODO: sync with link.smart_link() to choose a linker diff --git a/src/engine/SCons/Tool/link.py b/src/engine/SCons/Tool/link.py index 33e50d9..d52a9e5 100644 --- a/src/engine/SCons/Tool/link.py +++ b/src/engine/SCons/Tool/link.py @@ -76,7 +76,7 @@ def smart_link(source, target, env, for_signature):  def _lib_emitter(target, source, env, **kw):      Verbose = False      if Verbose: -        print "_lib_emitter: str(target[0])=%r" % str(target[0]) +        print "_lib_emitter: target[0]=%r" % target[0].get_path()      for tgt in target:          tgt.attributes.shared = 1 @@ -103,35 +103,44 @@ def ldmod_emitter(target, source, env):      return _lib_emitter(target, source, env, symlink_generator = SCons.Tool.LdModSymlinkGenerator)  # This is generic enough to be included here... -def _versioned_lib_name(env, libnode, version, suffix, suffix_generator, **kw): +def _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw):      """For libnode='/optional/dir/libfoo.so.X.Y.Z' it returns 'libfoo.so'"""      Verbose = False      if Verbose: +        print "_versioned_lib_name: libnode=%r" % libnode.get_path()          print "_versioned_lib_name: version=%r" % version +        print "_versioned_lib_name: prefix=%r" % prefix +        print "_versioned_lib_name: suffix=%r" % suffix +        print "_versioned_lib_name: suffix_generator=%r" % suffix_generator -    versioned_name = os.path.basename(str(libnode)) +    versioned_name = os.path.basename(libnode.get_path())      if Verbose:          print "_versioned_lib_name: versioned_name=%r" % versioned_name -    if Verbose: -        print "_versioned_lib_name: suffix=%r" % suffix - +    versioned_prefix = prefix_generator(env, **kw)      versioned_suffix = suffix_generator(env, **kw) +    if Verbose: +        print "_versioned_lib_name: versioned_prefix=%r" % versioned_prefix +        print "_versioned_lib_name: versioned_suffix=%r" % versioned_suffix +    versioned_prefix_re = '^' + re.escape(versioned_prefix)      versioned_suffix_re = re.escape(versioned_suffix) + '$' -    name = re.sub(versioned_suffix_re, suffix, versioned_name) +    name = re.sub(versioned_prefix_re, prefix, versioned_name) +    name = re.sub(versioned_suffix_re, suffix, name)      if Verbose:          print "_versioned_lib_name: name=%r" % name      return name -def _versioned_shlib_name(env, libnode, version, suffix, **kw): -    generator = SCons.Tool.ShLibSuffixGenerator -    return _versioned_lib_name(env, libnode, version, suffix, generator, **kw) +def _versioned_shlib_name(env, libnode, version, prefix, suffix, **kw): +    pg = SCons.Tool.ShLibPrefixGenerator +    sg = SCons.Tool.ShLibSuffixGenerator +    return _versioned_lib_name(env, libnode, version, prefix, suffix, pg, sg, **kw) -def _versioned_ldmod_name(env, libnode, version, suffix, **kw): -    generator = SCons.Tool.LdModSuffixGenerator -    return _versioned_lib_name(env, libnode, version, suffix, generator, **kw) +def _versioned_ldmod_name(env, libnode, version, prefix, suffix, **kw): +    pg = SCons.Tool.LdModPrefixGenerator +    sg = SCons.Tool.LdModSuffixGenerator +    return _versioned_lib_name(env, libnode, version, prefix, suffix, pg, sg, **kw)  def generate(env): | 
