diff options
author | Paweł Tomulik <ptomulik@meil.pw.edu.pl> | 2015-09-04 21:37:17 (GMT) |
---|---|---|
committer | Paweł Tomulik <ptomulik@meil.pw.edu.pl> | 2015-09-04 21:37:17 (GMT) |
commit | d124e8dd69f7c73e7ce82d55abf5f69e12379098 (patch) | |
tree | 790c4e960f2782dec24110802a0080ddd8aa3772 | |
parent | 97a7990e29435b7fe752ce220aac9a6048393395 (diff) | |
download | SCons-d124e8dd69f7c73e7ce82d55abf5f69e12379098.zip SCons-d124e8dd69f7c73e7ce82d55abf5f69e12379098.tar.gz SCons-d124e8dd69f7c73e7ce82d55abf5f69e12379098.tar.bz2 |
refactored the versioned lib code a little
-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): |