diff options
-rw-r--r-- | SCons/Builder.py | 1 | ||||
-rw-r--r-- | SCons/Defaults.py | 11 | ||||
-rw-r--r-- | SCons/Environment.py | 2 | ||||
-rw-r--r-- | SCons/Platform/aix.py | 1 | ||||
-rw-r--r-- | SCons/Platform/hpux.py | 2 | ||||
-rw-r--r-- | SCons/Tool/FortranCommon.py | 6 | ||||
-rw-r--r-- | SCons/Tool/aixlink.py | 9 | ||||
-rw-r--r-- | SCons/Tool/applelink.py | 12 | ||||
-rw-r--r-- | SCons/Tool/cxx.py | 5 | ||||
-rw-r--r-- | SCons/Tool/cyglink.py | 31 | ||||
-rw-r--r-- | SCons/Tool/gnulink.py | 12 | ||||
-rw-r--r-- | SCons/Tool/hplink.py | 5 | ||||
-rw-r--r-- | SCons/Tool/ilink.py | 4 | ||||
-rw-r--r-- | SCons/Tool/link.py | 303 | ||||
-rw-r--r-- | SCons/Tool/linkCommon/README.md | 103 | ||||
-rw-r--r-- | SCons/Tool/linkCommon/__init__.py | 283 | ||||
-rw-r--r-- | SCons/Tool/mslink.py | 3 | ||||
-rw-r--r-- | SCons/Tool/sgilink.py | 3 | ||||
-rw-r--r-- | SCons/Tool/sunlink.py | 14 | ||||
-rw-r--r-- | test/LINK/SHLIBVERSIONFLAGS.py | 27 |
20 files changed, 469 insertions, 368 deletions
diff --git a/SCons/Builder.py b/SCons/Builder.py index a0df272..035196d 100644 --- a/SCons/Builder.py +++ b/SCons/Builder.py @@ -503,6 +503,7 @@ class BuilderBase: splitext = lambda S: self.splitext(S,env) tlist = [ t_from_s(pre, suf, splitext) ] else: + orig_target = target target = self._adjustixes(target, pre, suf, self.ensure_suffix) tlist = env.arg2nodes(target, target_factory, target=target, source=source) diff --git a/SCons/Defaults.py b/SCons/Defaults.py index 06d938c..c59fbcf 100644 --- a/SCons/Defaults.py +++ b/SCons/Defaults.py @@ -20,6 +20,7 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# """Builders and other things for the local site. @@ -542,8 +543,14 @@ class Variable_Method_Caller: frame = frame.f_back return None -# if $version_var is not empty, returns env[flags_var], otherwise returns None def __libversionflags(env, version_var, flags_var): + """ + if $version_var is not empty, returns env[flags_var], otherwise returns None + :param env: + :param version_var: + :param flags_var: + :return: + """ try: if env.subst('$'+version_var): return env[flags_var] @@ -551,6 +558,8 @@ def __libversionflags(env, version_var, flags_var): pass return None + + ConstructionEnvironment = { 'BUILDERS' : {}, 'SCANNERS' : [ SCons.Tool.SourceFileScanner ], diff --git a/SCons/Environment.py b/SCons/Environment.py index 4ebd515..55a5003 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -1613,7 +1613,7 @@ class Base(SubstitutionEnvironment): prefix = self.subst('$'+prefix) for path in paths: - dir,name = os.path.split(str(path)) + name = os.path.basename(str(path)) if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix: return path diff --git a/SCons/Platform/aix.py b/SCons/Platform/aix.py index bee3eb8..db1ccdb 100644 --- a/SCons/Platform/aix.py +++ b/SCons/Platform/aix.py @@ -71,6 +71,7 @@ def generate(env): posix.generate(env) #Based on AIX 5.2: ARG_MAX=24576 - 3000 for environment expansion env['MAXLINELENGTH'] = 21576 + env['SHLIBSUFFIX'] = '.a' # Local Variables: # tab-width:4 diff --git a/SCons/Platform/hpux.py b/SCons/Platform/hpux.py index 551468e..53c7b67 100644 --- a/SCons/Platform/hpux.py +++ b/SCons/Platform/hpux.py @@ -35,6 +35,8 @@ def generate(env): #Based on HP-UX11i: ARG_MAX=2048000 - 3000 for environment expansion env['MAXLINELENGTH'] = 2045000 + env['SHLIBSUFFIX'] = '.sl' + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/SCons/Tool/FortranCommon.py b/SCons/Tool/FortranCommon.py index bfa1c1c..f8d9fdc 100644 --- a/SCons/Tool/FortranCommon.py +++ b/SCons/Tool/FortranCommon.py @@ -5,8 +5,6 @@ Stuff for processing Fortran, common to all fortran dialects. """ # -# __COPYRIGHT__ -# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -26,13 +24,11 @@ Stuff for processing Fortran, common to all fortran dialects. # 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import re import os.path import SCons.Action -import SCons.Defaults import SCons.Scanner.Fortran import SCons.Tool import SCons.Util @@ -78,10 +74,12 @@ def _fortranEmitter(target, source, env): return (target, source) def FortranEmitter(target, source, env): + import SCons.Defaults target, source = _fortranEmitter(target, source, env) return SCons.Defaults.StaticObjectEmitter(target, source, env) def ShFortranEmitter(target, source, env): + import SCons.Defaults target, source = _fortranEmitter(target, source, env) return SCons.Defaults.SharedObjectEmitter(target, source, env) diff --git a/SCons/Tool/aixlink.py b/SCons/Tool/aixlink.py index fed4342..dc0de2a 100644 --- a/SCons/Tool/aixlink.py +++ b/SCons/Tool/aixlink.py @@ -8,8 +8,6 @@ selection method. """ # -# __COPYRIGHT__ -# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -30,8 +28,6 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - import os import os.path @@ -42,7 +38,6 @@ from . import link import SCons.Tool.cxx cplusplus = SCons.Tool.cxx -#cplusplus = __import__('cxx', globals(), locals(), []) def smart_linkflags(source, target, env, for_signature): @@ -52,6 +47,7 @@ def smart_linkflags(source, target, env, for_signature): return '-qtempinc=' + os.path.join(build_dir, 'tempinc') return '' + def generate(env): """ Add Builders and construction variables for Visual Age linker to @@ -64,12 +60,13 @@ def generate(env): env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -qmkshrobj -qsuppress=1501-218') env['SHLIBSUFFIX'] = '.a' + def exists(env): # TODO: sync with link.smart_link() to choose a linker linkers = { 'CXX': ['aixc++'], 'CC': ['aixcc'] } alltools = [] for langvar, linktools in linkers.items(): - if langvar in env: # use CC over CXX when user specified CC but not CXX + if langvar in env: # use CC over CXX when user specified CC but not CXX return SCons.Tool.FindTool(linktools, env) alltools.extend(linktools) return SCons.Tool.FindTool(alltools, env) diff --git a/SCons/Tool/applelink.py b/SCons/Tool/applelink.py index aec8b93..f51a6af 100644 --- a/SCons/Tool/applelink.py +++ b/SCons/Tool/applelink.py @@ -9,8 +9,6 @@ selection method. """ # -# __COPYRIGHT__ -# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -31,8 +29,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - +import SCons.Tool.linkCommon import SCons.Util # Even though the Mac is based on the GNU toolchain, it doesn't understand @@ -85,7 +82,8 @@ def _applelib_versioned_lib_soname(env, libnode, version, prefix, suffix, name_f def _applelib_versioned_shlib_soname(env, libnode, version, prefix, suffix): - return _applelib_versioned_lib_soname(env, libnode, version, prefix, suffix, link._versioned_shlib_name) + return _applelib_versioned_lib_soname(env, libnode, version, prefix, suffix, + SCons.Tool.linkCommon._versioned_shlib_name) # User programmatically describes how SHLIBVERSION maps to values for compat/current. @@ -197,8 +195,8 @@ def generate(env): env['SHLINKCOM'] = env['SHLINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' # see: http://docstore.mik.ua/orelly/unix3/mac/ch05_04.htm for proper naming - link._setup_versioned_lib_variables(env, tool='applelink') #, use_soname=True) - env['LINKCALLBACKS'] = link._versioned_lib_callbacks() + SCons.Tool.linkCommon._setup_versioned_lib_variables(env, tool='applelink', use_soname=True) + env['LINKCALLBACKS'] = SCons.Tool.linkCommon._versioned_lib_callbacks() env['LINKCALLBACKS']['VersionedShLibSuffix'] = _applelib_versioned_lib_suffix env['LINKCALLBACKS']['VersionedShLibSoname'] = _applelib_versioned_shlib_soname diff --git a/SCons/Tool/cxx.py b/SCons/Tool/cxx.py index 430851c..128cdc4 100644 --- a/SCons/Tool/cxx.py +++ b/SCons/Tool/cxx.py @@ -8,8 +8,6 @@ selection method. """ # -# __COPYRIGHT__ -# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -30,11 +28,8 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - import os.path -import SCons.Tool import SCons.Defaults import SCons.Util diff --git a/SCons/Tool/cyglink.py b/SCons/Tool/cyglink.py index 08b8a98..595cc2e 100644 --- a/SCons/Tool/cyglink.py +++ b/SCons/Tool/cyglink.py @@ -12,13 +12,13 @@ import re import os import SCons.Action +import SCons.Tool.linkCommon as linkCommon from SCons.Tool.linkCommon import ImpLibSymlinkGenerator, StringizeLibSymlinks, EmitLibSymlinks, ImpLibPrefixGenerator, \ ImpLibSuffixGenerator, ImpLibNameGenerator import SCons.Util import SCons.Tool from . import gnulink -from . import link def _lib_generator(target, source, env, for_signature, **kw): @@ -120,14 +120,15 @@ def _lib_emitter(target, source, env, **kw): implib_target.attributes.shared = 1 target.append(implib_target) - symlinks = ImpLibSymlinkGenerator(env, implib_target, - implib_libtype=libtype, - generator_libtype=libtype + 'ImpLib') - if Verbose: - print("_lib_emitter: implib symlinks=%r" % StringizeLibSymlinks(symlinks)) - if symlinks: - EmitLibSymlinks(env, symlinks, implib_target, clean_targets=target[0]) - implib_target.attributes.shliblinks = symlinks + # Only create the symlinks if there is actually an import library + symlinks = ImpLibSymlinkGenerator(env, implib_target, + implib_libtype=libtype, + generator_libtype=libtype + 'ImpLib') + if Verbose: + print("_lib_emitter: implib symlinks=%r" % StringizeLibSymlinks(symlinks)) + if symlinks: + EmitLibSymlinks(env, symlinks, implib_target, clean_targets=target[0]) + implib_target.attributes.shliblinks = symlinks return (target, source) @@ -156,10 +157,10 @@ def _versioned_lib_suffix(env, suffix, version): def _versioned_implib_name(env, libnode, version, prefix, suffix, **kw): - return link._versioned_lib_name(env, libnode, version, prefix, suffix, - ImpLibPrefixGenerator, - ImpLibSuffixGenerator, - implib_libtype=kw['libtype']) + return linkCommon._versioned_lib_name(env, libnode, version, prefix, suffix, + ImpLibPrefixGenerator, + ImpLibSuffixGenerator, + implib_libtype=kw['libtype']) def _versioned_implib_symlinks(env, libnode, version, prefix, suffix, **kw): @@ -230,8 +231,8 @@ def generate(env): 'VersionedShLibSuffix': _versioned_lib_suffix, 'VersionedLdModSuffix': _versioned_lib_suffix, 'VersionedImpLibSuffix': _versioned_lib_suffix, - 'VersionedShLibName': link._versioned_shlib_name, - 'VersionedLdModName': link._versioned_ldmod_name, + 'VersionedShLibName': linkCommon._versioned_shlib_name, + 'VersionedLdModName': linkCommon._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'), diff --git a/SCons/Tool/gnulink.py b/SCons/Tool/gnulink.py index 5372322..2b09549 100644 --- a/SCons/Tool/gnulink.py +++ b/SCons/Tool/gnulink.py @@ -9,8 +9,6 @@ selection method. """ # -# __COPYRIGHT__ -# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -31,13 +29,14 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +import SCons.Tool.linkCommon import SCons.Util import SCons.Tool import sys from . import link +import SCons.Tool.linkCommon as linkCommon def generate(env): @@ -55,11 +54,8 @@ def generate(env): # OpenBSD doesn't usually use SONAME for libraries use_soname = not sys.platform.startswith('openbsd') - link._setup_versioned_lib_variables(env, tool='gnulink', use_soname=use_soname) - env['LINKCALLBACKS'] = link._versioned_lib_callbacks() - - # # For backward-compatibility with older SCons versions - # env['SHLIBVERSIONFLAGS'] = SCons.Util.CLVar('') + linkCommon._setup_versioned_lib_variables(env, tool='gnulink', use_soname=use_soname) + env['LINKCALLBACKS'] = linkCommon._versioned_lib_callbacks() def exists(env): diff --git a/SCons/Tool/hplink.py b/SCons/Tool/hplink.py index 10ef30b..ba182f1 100644 --- a/SCons/Tool/hplink.py +++ b/SCons/Tool/hplink.py @@ -8,8 +8,6 @@ selection method. """ # -# __COPYRIGHT__ -# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -30,9 +28,6 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import os import os.path import SCons.Util diff --git a/SCons/Tool/ilink.py b/SCons/Tool/ilink.py index aa6bcaa..4112825 100644 --- a/SCons/Tool/ilink.py +++ b/SCons/Tool/ilink.py @@ -9,8 +9,6 @@ selection method. """ # -# __COPYRIGHT__ -# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -31,8 +29,6 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - import SCons.Defaults import SCons.Tool import SCons.Util diff --git a/SCons/Tool/link.py b/SCons/Tool/link.py index de377ac..c552273 100644 --- a/SCons/Tool/link.py +++ b/SCons/Tool/link.py @@ -1,13 +1,7 @@ -"""SCons.Tool.link - -Tool-specific initialization for the generic Posix linker. - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - +# +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,287 +22,21 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +""" +Tool-specific initialization for the generic Posix linker. + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. + +""" -import sys -import re -import os import SCons.Tool import SCons.Util import SCons.Warnings -from SCons.Tool.FortranCommon import isfortran - -from SCons.Tool.DCommon import isD - -from SCons.Tool.cxx import iscplusplus - -from SCons.Tool.linkCommon import StringizeLibSymlinks, ShLibSonameGenerator, EmitLibSymlinks, ShLibSymlinkGenerator, \ - LdModSymlinkGenerator, ShLibPrefixGenerator, ShLibSuffixGenerator, LdModPrefixGenerator, LdModSuffixGenerator, \ - LdModSonameGenerator - -issued_mixed_link_warning = False - - -def smart_link(source, target, env, for_signature): - has_cplusplus = iscplusplus(source) - has_fortran = isfortran(env, source) - has_d = isD(env, source) - if has_cplusplus and has_fortran and not has_d: - global issued_mixed_link_warning - if not issued_mixed_link_warning: - msg = "Using $CXX to link Fortran and C++ code together.\n\t" + \ - "This may generate a buggy executable if the '%s'\n\t" + \ - "compiler does not know how to deal with Fortran runtimes." - SCons.Warnings.warn(SCons.Warnings.FortranCxxMixWarning, - msg % env.subst('$CXX')) - issued_mixed_link_warning = True - return '$CXX' - elif has_d: - env['LINKCOM'] = env['DLINKCOM'] - env['SHLINKCOM'] = env['SHDLINKCOM'] - return '$DC' - elif has_fortran: - return '$FORTRAN' - elif has_cplusplus: - return '$CXX' - return '$CC' - - -def _lib_emitter(target, source, env, **kw): - Verbose = False - if Verbose: - print("_lib_emitter: target[0]={!r}".format(target[0].get_path())) - for tgt in target: - if SCons.Util.is_String(tgt): - tgt = env.File(tgt) - tgt.attributes.shared = 1 - - try: - symlink_generator = kw['symlink_generator'] - except KeyError: - pass - else: - if Verbose: - print("_lib_emitter: symlink_generator={!r}".format(symlink_generator)) - symlinks = symlink_generator(env, target[0]) - if Verbose: - print("_lib_emitter: symlinks={!r}".format(symlinks)) - - if symlinks: - EmitLibSymlinks(env, symlinks, target[0]) - target[0].attributes.shliblinks = symlinks - return (target, source) - - -def shlib_emitter(target, source, env): - return _lib_emitter(target, source, env, symlink_generator=ShLibSymlinkGenerator) - - -def ldmod_emitter(target, source, env): - return _lib_emitter(target, source, env, symlink_generator=LdModSymlinkGenerator) - - -# This is generic enough to be included here... -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}".format(libnode.get_path())) - print("_versioned_lib_name: version={!r}".format(version)) - print("_versioned_lib_name: prefix={!r}".format(prefix)) - print("_versioned_lib_name: suffix={!r}".format(suffix)) - print("_versioned_lib_name: suffix_generator={!r}".format(suffix_generator)) - - versioned_name = os.path.basename(libnode.get_path()) - if Verbose: - print("_versioned_lib_name: versioned_name={!r}".format(versioned_name)) - - versioned_prefix = prefix_generator(env, **kw) - versioned_suffix = suffix_generator(env, **kw) - if Verbose: - print("_versioned_lib_name: versioned_prefix={!r}".format(versioned_prefix)) - print("_versioned_lib_name: versioned_suffix={!r}".format(versioned_suffix)) - - versioned_prefix_re = '^' + re.escape(versioned_prefix) - versioned_suffix_re = re.escape(versioned_suffix) + '$' - 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}".format(name)) - return name - - -def _versioned_shlib_name(env, libnode, version, prefix, suffix, **kw): - prefix_generator = ShLibPrefixGenerator - suffix_generator = ShLibSuffixGenerator - return _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw) - - -def _versioned_ldmod_name(env, libnode, version, prefix, suffix, **kw): - prefix_generator = LdModPrefixGenerator - suffix_generator = LdModSuffixGenerator - return _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw) - - -def _versioned_lib_suffix(env, suffix, version): - """For suffix='.so' and version='0.1.2' it returns '.so.0.1.2'""" - Verbose = False - if Verbose: - print("_versioned_lib_suffix: suffix={!r}".format(suffix)) - print("_versioned_lib_suffix: version={!r}".format(version)) - if not suffix.endswith(version): - suffix = suffix + '.' + version - if Verbose: - print("_versioned_lib_suffix: return suffix={!r}".format(suffix)) - return suffix - - -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}".format(version)) - name = name_func(env, libnode, version, prefix, suffix) - if Verbose: - print("_versioned_lib_soname: name={!r}".format(name)) - major = version.split('.')[0] - - # if a desired SONAME was supplied, use that, otherwise create - # a default from the major version - if env.get('SONAME'): - soname = ShLibSonameGenerator(env, libnode) - else: - soname = name + '.' + major - if Verbose: - print("_versioned_lib_soname: soname={!r}".format(soname)) - return soname - - -def _versioned_shlib_soname(env, libnode, version, prefix, suffix): - return _versioned_lib_soname(env, libnode, version, prefix, suffix, _versioned_shlib_name) - - -def _versioned_ldmod_soname(env, libnode, version, prefix, suffix): - return _versioned_lib_soname(env, libnode, version, prefix, suffix, _versioned_ldmod_name) - - -def _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func): - """Generate link names that should be created for a versioned shared library. - Returns a dictionary in the form { linkname : linktarget } - """ - Verbose = False - - if Verbose: - print("_versioned_lib_symlinks: libnode={!r}".format(libnode.get_path())) - print("_versioned_lib_symlinks: version={!r}".format(version)) - - if sys.platform.startswith('openbsd'): - # OpenBSD uses x.y shared library versioning numbering convention - # and doesn't use symlinks to backwards-compatible libraries - if Verbose: - print("_versioned_lib_symlinks: return symlinks={!r}".format(None)) - return None - - linkdir = libnode.get_dir() - if Verbose: - print("_versioned_lib_symlinks: linkdir={!r}".format(linkdir.get_path())) - - name = name_func(env, libnode, version, prefix, suffix) - if Verbose: - print("_versioned_lib_symlinks: name={!r}".format(name)) - - soname = soname_func(env, libnode, version, prefix, suffix) - if Verbose: - print("_versioned_lib_symlinks: soname={!r}".format(soname)) - - link0 = env.fs.File(soname, linkdir) - link1 = env.fs.File(name, linkdir) - - # We create direct symlinks, not daisy-chained. - if link0 == libnode: - # This enables SHLIBVERSION without periods (e.g. SHLIBVERSION=1) - symlinks = [(link1, libnode)] - else: - # This handles usual SHLIBVERSION, i.e. '1.2', '1.2.3', etc. - symlinks = [(link0, libnode), (link1, libnode)] - - if Verbose: - print("_versioned_lib_symlinks: return symlinks={!r}".format( - StringizeLibSymlinks(symlinks))) - - return symlinks - - -def _versioned_shlib_symlinks(env, libnode, version, prefix, suffix): - name_func = env['LINKCALLBACKS']['VersionedShLibName'] - soname_func = env['LINKCALLBACKS']['VersionedShLibSoname'] - - return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func) - - -def _versioned_ldmod_symlinks(env, libnode, version, prefix, suffix): - name_func = _versioned_ldmod_name - soname_func = _versioned_ldmod_soname - - name_func = env['LINKCALLBACKS']['VersionedLdModName'] - soname_func = env['LINKCALLBACKS']['VersionedLdModSoname'] - - return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func) - - -def _versioned_lib_callbacks(): - return { - 'VersionedShLibSuffix': _versioned_lib_suffix, - 'VersionedLdModSuffix': _versioned_lib_suffix, - 'VersionedShLibSymlinks': _versioned_shlib_symlinks, - 'VersionedLdModSymlinks': _versioned_ldmod_symlinks, - 'VersionedShLibName': _versioned_shlib_name, - 'VersionedLdModName': _versioned_ldmod_name, - 'VersionedShLibSoname': _versioned_shlib_soname, - 'VersionedLdModSoname': _versioned_ldmod_soname, - }.copy() - - -def _setup_versioned_lib_variables(env, **kw): - """ - Setup all variables required by the versioning machinery - """ - - tool = None - try: - tool = kw['tool'] - except KeyError: - pass - - use_soname = False - try: - use_soname = kw['use_soname'] - except KeyError: - pass - - # The $_SHLIBVERSIONFLAGS define extra commandline flags used when - # building VERSIONED shared libraries. It's always set, but used only - # when VERSIONED library is built (see __SHLIBVERSIONFLAGS in SCons/Defaults.py). - if use_soname: - # If the linker uses SONAME, then we need this little automata - if tool == 'sunlink': - env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -h $_SHLIBSONAME' - env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -h $_LDMODULESONAME' - else: - env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -Wl,-soname=$_SHLIBSONAME' - env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -Wl,-soname=$_LDMODULESONAME' - env['_SHLIBSONAME'] = '${ShLibSonameGenerator(__env__,TARGET)}' - env['_LDMODULESONAME'] = '${LdModSonameGenerator(__env__,TARGET)}' - env['ShLibSonameGenerator'] = ShLibSonameGenerator - env['LdModSonameGenerator'] = LdModSonameGenerator - else: - env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS' - env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS' - - # LDOMDULVERSIONFLAGS should always default to $SHLIBVERSIONFLAGS - env['LDMODULEVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS' +from SCons.Tool.linkCommon import smart_link, shlib_emitter, ldmod_emitter def generate(env): @@ -336,11 +64,6 @@ def generate(env): env['LIBLINKPREFIX'] = '-l' env['LIBLINKSUFFIX'] = '' - if env['PLATFORM'] == 'hpux': - env['SHLIBSUFFIX'] = '.sl' - elif env['PLATFORM'] == 'aix': - env['SHLIBSUFFIX'] = '.a' - # For most platforms, a loadable module is the same as a shared # library. Platforms which are different can override these, but # setting them the same means that LoadableModule works everywhere. diff --git a/SCons/Tool/linkCommon/README.md b/SCons/Tool/linkCommon/README.md new file mode 100644 index 0000000..add1246 --- /dev/null +++ b/SCons/Tool/linkCommon/README.md @@ -0,0 +1,103 @@ + + +# Versioned Shared Library and Loadable modules requirements + +The following env variables can affect the command line and created files for these + +* `SHLIBVERSION` - If this is not set, the all of the following will be ignored? +* `SONAME` +* `SOVERSION` +* `APPLELINK_NO_CURRENT_VERSION` (applelink only) +* `APPLELINK_CURRENT_VERSION` (applelink only) +* `APPLELINK_COMPATIBILITY_VERSION` (applelink only) + +In most cases the linker will create a file named as + +`${SHLIBPREFIX}lib_name${SHLIBVERSION}${SHLIBSUFFIX}` + +Which will have a soname baked into it as one of the + +* `${SONAME}` +* `${SHLIBPREFIX}lib_name${SOVERSION}${SHLIBSUFFIX}` +* `-Wl,-soname=$_SHLIBSONAME` (for gnulink as similar) +* (for applelink only) + * `${SHLIBPREFIX}lib_name${major version only from SHLIBVERSION}${SHLIBSUFFIX}` + * `-Wl,-compatibility_version,%s` + * `-Wl,-current_version,%s` + +For **applelink** the version has to follow these rules to verify that the version # is valid. + +* For version # = X[.Y[.Z]] +* where X 0-65535 +* where Y either not specified or 0-255 +* where Z either not specified or 0-255 + + +For most platforms this will lead to a series of symlinks eventually pointing to the actual shared library (or loadable module file). +1. `${SHLIBPREFIX}lib_name${SHLIBSUFFIX} -> ${SHLIBPREFIX}lib_name${SHLIBVERSION}${SHLIBSUFFIX}` +1. `${SHLIBPREFIX}lib_name${SOVERSION}${SHLIBSUFFIX} -> ${SHLIBPREFIX}lib_name${SHLIBVERSION}${SHLIBSUFFIX}` + +These symlinks are stored by the emitter in the following +`target[0].attributes.shliblinks = symlinks` +This means that those values are fixed a the time SharedLibrary() is called (generally) + +For **openbsd** the following rules for symlinks apply + + * OpenBSD uses x.y shared library versioning numbering convention and doesn't use symlinks to backwards-compatible libraries + + +The current code provides the following hooks a compiler can use to customize: + +``` + 'VersionedShLibSuffix': _versioned_lib_suffix, + 'VersionedLdModSuffix': _versioned_lib_suffix, + 'VersionedShLibSymlinks': _versioned_shlib_symlinks, + 'VersionedLdModSymlinks': _versioned_ldmod_symlinks, + 'VersionedShLibName': _versioned_shlib_name, + 'VersionedLdModName': _versioned_ldmod_name, + 'VersionedShLibSoname': _versioned_shlib_soname, + 'VersionedLdModSoname': _versioned_ldmod_soname, +``` + + +User can request: +env.SharedLibrary('a',sources, SHLIBVERSION) +env.SharedLibrary('liba.so',sources, SHLIBVERSION) +Ideally we'll keep the 'a' for use in constructing all follow on. To do this we have to do it in the Builder() or at +least prevent BuilderBase._create_nodes() from discarding this info if it's available. + + +Firstly check if [SH|LD]LIBNOVERSIONSYMLINKS defined or if [SH|LD]LIBVERSION is not defined, if so we do nothing special + +The emitter can calculate the filename stem 'a' above and store it on the target node. Then also create the symlinks +and store those on the node. We should have all the information needed by the time the emitter is called. +Same should apply for loadable modules.. +This should be vastly simpler. +Unfortunately we cannot depend on the target having an OverrideEnvironment() which we could populate all the related +env variables in the emitter... +Maybe we can force one at that point? + + +SOVERSION can be specified, if not, then defaults to major portion of SHLIBVERSION +SONAME can be specified, if not defaults to ${SHLIBPREFIX}lib_name${SOVERSION} + +NOTE: mongodb uses Append(SHLIBEMITTER=.. ) for their libdeps stuff. (So test +with that once you have new logic working) + + +TODO: +1. Generate proper naming for: + * shared library (altered by emitter if SHLIBVERSION is set) + * soname'd library (for symlink) - SHLIB_SONAME_SYMLINK + * non versioned shared library (for symlink) - SHLIB_NOVERSION_SYMLINK +2. in emitter also, actually create the symlinks (if SHLIBVERSION is set) and + add to node.attributes.symlinks. (note bsd doesn't do this so skip if on bsd) +3. We need to check somewhere if SONAME and SOVERSION are both set and thrown an error. + Probably in the emitter to it will traceback to where the SharedLibrary() which + yielded the issue is located. +4. Generate proper linker soname compiler construct (-Wl,soname=libxyz.1.so for example) + +hrm.. tricky. +SHLIBSUFFIX needs to have .${SHLIBVERSION}${SHLIBSUFFIX} as it's value when +fixing a sharedlibrary()'s target file name (from a -> liba.1.2.3.so) +But when creating the symlinks for the rest, we need to drop the versioned SHLIBSUFFIX
\ No newline at end of file diff --git a/SCons/Tool/linkCommon/__init__.py b/SCons/Tool/linkCommon/__init__.py index f66ad6d..c49bc23 100644 --- a/SCons/Tool/linkCommon/__init__.py +++ b/SCons/Tool/linkCommon/__init__.py @@ -1,8 +1,6 @@ -"""SCons.Tool.linkCommon - -Common link/shared library logic -""" - +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -22,8 +20,19 @@ Common link/shared library logic # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Common link/shared library logic +""" + import os +import re +import sys from typing import Callable + +import SCons.Util +import SCons.Warnings +from SCons.Tool.DCommon import isD from SCons.Util import is_List @@ -499,4 +508,266 @@ def _call_env_subst(env, string, *args, **kw): kw2[k] = kw[k] except KeyError: pass - return env.subst(string, *args, **kw2)
\ No newline at end of file + return env.subst(string, *args, **kw2) + + +def smart_link(source, target, env, for_signature): + import SCons.Tool.cxx + import SCons.Tool.FortranCommon + + has_cplusplus = SCons.Tool.cxx.iscplusplus(source) + has_fortran = SCons.Tool.FortranCommon.isfortran(env, source) + has_d = isD(env, source) + if has_cplusplus and has_fortran and not has_d: + global issued_mixed_link_warning + if not issued_mixed_link_warning: + msg = "Using $CXX to link Fortran and C++ code together.\n\t" + \ + "This may generate a buggy executable if the '%s'\n\t" + \ + "compiler does not know how to deal with Fortran runtimes." + SCons.Warnings.warn(SCons.Warnings.FortranCxxMixWarning, + msg % env.subst('$CXX')) + issued_mixed_link_warning = True + return '$CXX' + elif has_d: + env['LINKCOM'] = env['DLINKCOM'] + env['SHLINKCOM'] = env['SHDLINKCOM'] + return '$DC' + elif has_fortran: + return '$FORTRAN' + elif has_cplusplus: + return '$CXX' + return '$CC' + + +def _lib_emitter(target, source, env, **kw): + Verbose = False + if Verbose: + print("_lib_emitter: target[0]={!r}".format(target[0].get_path())) + for tgt in target: + if SCons.Util.is_String(tgt): + tgt = env.File(tgt) + tgt.attributes.shared = 1 + + try: + symlink_generator = kw['symlink_generator'] + except KeyError: + pass + else: + if Verbose: + print("_lib_emitter: symlink_generator={!r}".format(symlink_generator)) + symlinks = symlink_generator(env, target[0]) + if Verbose: + print("_lib_emitter: symlinks={!r}".format(symlinks)) + + if symlinks: + EmitLibSymlinks(env, symlinks, target[0]) + target[0].attributes.shliblinks = symlinks + return target, source + + +def shlib_emitter(target, source, env): + return _lib_emitter(target, source, env, symlink_generator=ShLibSymlinkGenerator) + + +def ldmod_emitter(target, source, env): + return _lib_emitter(target, source, env, symlink_generator=LdModSymlinkGenerator) + + +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}".format(libnode.get_path())) + print("_versioned_lib_name: version={!r}".format(version)) + print("_versioned_lib_name: prefix={!r}".format(prefix)) + print("_versioned_lib_name: suffix={!r}".format(suffix)) + print("_versioned_lib_name: suffix_generator={!r}".format(suffix_generator)) + + versioned_name = os.path.basename(libnode.get_path()) + if Verbose: + print("_versioned_lib_name: versioned_name={!r}".format(versioned_name)) + + versioned_prefix = prefix_generator(env, **kw) + versioned_suffix = suffix_generator(env, **kw) + if Verbose: + print("_versioned_lib_name: versioned_prefix={!r}".format(versioned_prefix)) + print("_versioned_lib_name: versioned_suffix={!r}".format(versioned_suffix)) + + versioned_prefix_re = '^' + re.escape(versioned_prefix) + versioned_suffix_re = re.escape(versioned_suffix) + '$' + 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}".format(name)) + return name + + +def _versioned_shlib_name(env, libnode, version, prefix, suffix, **kw): + prefix_generator = ShLibPrefixGenerator + suffix_generator = ShLibSuffixGenerator + return _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw) + + +def _versioned_ldmod_name(env, libnode, version, prefix, suffix, **kw): + prefix_generator = LdModPrefixGenerator + suffix_generator = LdModSuffixGenerator + return _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw) + + +def _versioned_lib_suffix(env, suffix, version): + """For suffix='.so' and version='0.1.2' it returns '.so.0.1.2'""" + Verbose = False + if Verbose: + print("_versioned_lib_suffix: suffix={!r}".format(suffix)) + print("_versioned_lib_suffix: version={!r}".format(version)) + if not suffix.endswith(version): + suffix = suffix + '.' + version + if Verbose: + print("_versioned_lib_suffix: return suffix={!r}".format(suffix)) + return suffix + + +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}".format(version)) + name = name_func(env, libnode, version, prefix, suffix) + if Verbose: + print("_versioned_lib_soname: name={!r}".format(name)) + major = version.split('.')[0] + + # if a desired SONAME was supplied, use that, otherwise create + # a default from the major version + if env.get('SONAME'): + soname = ShLibSonameGenerator(env, libnode) + else: + soname = name + '.' + major + if Verbose: + print("_versioned_lib_soname: soname={!r}".format(soname)) + return soname + + +def _versioned_shlib_soname(env, libnode, version, prefix, suffix): + return _versioned_lib_soname(env, libnode, version, prefix, suffix, _versioned_shlib_name) + + +def _versioned_ldmod_soname(env, libnode, version, prefix, suffix): + return _versioned_lib_soname(env, libnode, version, prefix, suffix, _versioned_ldmod_name) + + +def _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func): + """Generate link names that should be created for a versioned shared library. + Returns a dictionary in the form { linkname : linktarget } + """ + Verbose = False + + if Verbose: + print("_versioned_lib_symlinks: libnode={!r}".format(libnode.get_path())) + print("_versioned_lib_symlinks: version={!r}".format(version)) + + if sys.platform.startswith('openbsd'): + # OpenBSD uses x.y shared library versioning numbering convention + # and doesn't use symlinks to backwards-compatible libraries + if Verbose: + print("_versioned_lib_symlinks: return symlinks={!r}".format(None)) + return None + + linkdir = libnode.get_dir() + if Verbose: + print("_versioned_lib_symlinks: linkdir={!r}".format(linkdir.get_path())) + + name = name_func(env, libnode, version, prefix, suffix) + if Verbose: + print("_versioned_lib_symlinks: name={!r}".format(name)) + + soname = soname_func(env, libnode, version, prefix, suffix) + if Verbose: + print("_versioned_lib_symlinks: soname={!r}".format(soname)) + + link0 = env.fs.File(soname, linkdir) + link1 = env.fs.File(name, linkdir) + + # We create direct symlinks, not daisy-chained. + if link0 == libnode: + # This enables SHLIBVERSION without periods (e.g. SHLIBVERSION=1) + symlinks = [(link1, libnode)] + else: + # This handles usual SHLIBVERSION, i.e. '1.2', '1.2.3', etc. + symlinks = [(link0, libnode), (link1, libnode)] + + if Verbose: + print("_versioned_lib_symlinks: return symlinks={!r}".format( + StringizeLibSymlinks(symlinks))) + + return symlinks + + +def _versioned_shlib_symlinks(env, libnode, version, prefix, suffix): + name_func = env['LINKCALLBACKS']['VersionedShLibName'] + soname_func = env['LINKCALLBACKS']['VersionedShLibSoname'] + + return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func) + + +def _versioned_ldmod_symlinks(env, libnode, version, prefix, suffix): + name_func = _versioned_ldmod_name + soname_func = _versioned_ldmod_soname + + name_func = env['LINKCALLBACKS']['VersionedLdModName'] + soname_func = env['LINKCALLBACKS']['VersionedLdModSoname'] + + return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func) + + +def _versioned_lib_callbacks(): + return { + 'VersionedShLibSuffix': _versioned_lib_suffix, + 'VersionedLdModSuffix': _versioned_lib_suffix, + 'VersionedShLibSymlinks': _versioned_shlib_symlinks, + 'VersionedLdModSymlinks': _versioned_ldmod_symlinks, + 'VersionedShLibName': _versioned_shlib_name, + 'VersionedLdModName': _versioned_ldmod_name, + 'VersionedShLibSoname': _versioned_shlib_soname, + 'VersionedLdModSoname': _versioned_ldmod_soname, + }.copy() + + +issued_mixed_link_warning = False + + +def _setup_versioned_lib_variables(env, **kw): + """ + Setup all variables required by the versioning machinery + """ + + tool = None + try: + tool = kw['tool'] + except KeyError: + pass + + use_soname = False + try: + use_soname = kw['use_soname'] + except KeyError: + pass + + # The $_SHLIBVERSIONFLAGS define extra commandline flags used when + # building VERSIONED shared libraries. It's always set, but used only + # when VERSIONED library is built (see __SHLIBVERSIONFLAGS in SCons/Defaults.py). + if use_soname: + # If the linker uses SONAME, then we need this little automata + env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -Wl,-soname=$_SHLIBSONAME' + env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -Wl,-soname=$_LDMODULESONAME' + env['_SHLIBSONAME'] = '${ShLibSonameGenerator(__env__,TARGET)}' + env['_LDMODULESONAME'] = '${LdModSonameGenerator(__env__,TARGET)}' + env['ShLibSonameGenerator'] = ShLibSonameGenerator + env['LdModSonameGenerator'] = LdModSonameGenerator + else: + env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS' + env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS' + + # LDOMDULVERSIONFLAGS should always default to $SHLIBVERSIONFLAGS + env['LDMODULEVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS'
\ No newline at end of file diff --git a/SCons/Tool/mslink.py b/SCons/Tool/mslink.py index bab78d8..8fd7922 100644 --- a/SCons/Tool/mslink.py +++ b/SCons/Tool/mslink.py @@ -9,8 +9,6 @@ selection method. """ # -# __COPYRIGHT__ -# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -30,7 +28,6 @@ selection method. # 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import os.path diff --git a/SCons/Tool/sgilink.py b/SCons/Tool/sgilink.py index b1e7921..e92c7b9 100644 --- a/SCons/Tool/sgilink.py +++ b/SCons/Tool/sgilink.py @@ -9,8 +9,6 @@ selection method. """ # -# __COPYRIGHT__ -# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -31,7 +29,6 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Util diff --git a/SCons/Tool/sunlink.py b/SCons/Tool/sunlink.py index 39d9ec2..f668903 100644 --- a/SCons/Tool/sunlink.py +++ b/SCons/Tool/sunlink.py @@ -8,8 +8,6 @@ selection method. """ # -# __COPYRIGHT__ -# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -30,11 +28,9 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import os import os.path +import SCons.Tool.linkCommon as linkCommon import SCons.Util from . import link @@ -67,8 +63,12 @@ def generate(env): env['_RPATH'] = '${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}' # Support for versioned libraries - link._setup_versioned_lib_variables(env, tool = 'sunlink', use_soname = True) - env['LINKCALLBACKS'] = link._versioned_lib_callbacks() + linkCommon._setup_versioned_lib_variables(env, tool='sunlink', use_soname=True) + + env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -h $_SHLIBSONAME' + env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -h $_LDMODULESONAME' + + env['LINKCALLBACKS'] = linkCommon._versioned_lib_callbacks() def exists(env): return ccLinker diff --git a/test/LINK/SHLIBVERSIONFLAGS.py b/test/LINK/SHLIBVERSIONFLAGS.py index d2e271c..7bcabf0 100644 --- a/test/LINK/SHLIBVERSIONFLAGS.py +++ b/test/LINK/SHLIBVERSIONFLAGS.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -22,7 +24,6 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import TestSCons @@ -67,15 +68,35 @@ test.write('SConstruct', "SharedLibrary('foo','foo.c',SHLIBVERSION='1.2.3')\n") test.run(stdout = versionflags, match = TestSCons.match_re_dotall) test.run(arguments = ['-c']) -# stdout must contain SHLIBVERSIONFLAGS if there is SHLIBVERSION provided +# stdout must contain SONAME if there is SONAME provided test = TestSCons.TestSCons() test.write('foo.c', foo_c_src) test.write('SConstruct', """ SharedLibrary('foo','foo.c',SHLIBVERSION='1.2.3',SONAME='%s') """ % soname) test.run(stdout = sonameVersionFlags, match = TestSCons.match_re_dotall) +test.must_exist(test.workpath(soname)) test.run(arguments = ['-c']) +# stdout must contain SOVERSION if there is SOVERSION provided +test = TestSCons.TestSCons() +test.write('foo.c', foo_c_src) +test.write('SConstruct', """ +SharedLibrary('foo','foo.c',SHLIBVERSION='1.2.3',SOVERSION='4') +""") +test.run(stdout = sonameVersionFlags, match = TestSCons.match_re_dotall) +test.must_exist(test.workpath(soname)) +test.run(arguments = ['-c']) + +# test if both SONAME and SOVERSION are used +test = TestSCons.TestSCons() +test.write('foo.c', foo_c_src) +test.write('SConstruct', """ +SharedLibrary('foo','foo.c',SHLIBVERSION='1.2.3',SONAME='%s',SOVERSION='4') +""" % soname) +test.run(status=2,stderr=None) +test.must_contain_all_lines(test.stderr(), ['Ambiguous library .so naming']) + test.pass_test() # Local Variables: |