diff options
Diffstat (limited to 'src/engine/SCons/Tool/link.py')
| -rw-r--r-- | src/engine/SCons/Tool/link.py | 185 | 
1 files changed, 108 insertions, 77 deletions
diff --git a/src/engine/SCons/Tool/link.py b/src/engine/SCons/Tool/link.py index e8c11ed..65fe013 100644 --- a/src/engine/SCons/Tool/link.py +++ b/src/engine/SCons/Tool/link.py @@ -1,4 +1,3 @@ -  """SCons.Tool.link  Tool-specific initialization for the generic Posix linker. @@ -10,7 +9,7 @@ selection method.  """  # -# 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 @@ -33,7 +32,7 @@ selection method.  #  from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/link.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/link.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog"  import sys  import re @@ -47,22 +46,21 @@ from SCons.Tool.FortranCommon import isfortran  from SCons.Tool.DCommon import isD -import SCons.Tool.cxx -cplusplus = SCons.Tool.cxx -# cplusplus = __import__(__package__+'.cxx', globals(), locals(), ['*']) +from SCons.Tool.cxx import iscplusplus  issued_mixed_link_warning = False +  def smart_link(source, target, env, for_signature): -    has_cplusplus = cplusplus.iscplusplus(source) +    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." +                  "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 @@ -77,11 +75,14 @@ def smart_link(source, target, env, for_signature):          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())) +        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: @@ -90,21 +91,24 @@ def _lib_emitter(target, source, env, **kw):          pass      else:          if Verbose: -            print("_lib_emitter: symlink_generator={:r}".format(symlink_generator)) +            print("_lib_emitter: symlink_generator={!r}".format(symlink_generator))          symlinks = symlink_generator(env, target[0])          if Verbose: -            print("_lib_emitter: symlinks={:r}".format(symlinks)) +            print("_lib_emitter: symlinks={!r}".format(symlinks))          if symlinks:              SCons.Tool.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 = SCons.Tool.ShLibSymlinkGenerator) +    return _lib_emitter(target, source, env, symlink_generator=SCons.Tool.ShLibSymlinkGenerator) +  def ldmod_emitter(target, source, env): -    return _lib_emitter(target, source, env, symlink_generator = SCons.Tool.LdModSymlinkGenerator) +    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, prefix, suffix, prefix_generator, suffix_generator, **kw): @@ -112,98 +116,107 @@ def _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator,      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)) +        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)) +        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)) +        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)) +        print("_versioned_lib_name: name={!r}".format(name))      return name +  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) +    prefix_generator = SCons.Tool.ShLibPrefixGenerator +    suffix_generator = SCons.Tool.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): -    pg = SCons.Tool.LdModPrefixGenerator -    sg = SCons.Tool.LdModSuffixGenerator -    return _versioned_lib_name(env, libnode, version, prefix, suffix, pg, sg, **kw) +    prefix_generator = SCons.Tool.LdModPrefixGenerator +    suffix_generator = SCons.Tool.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)) +        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)) +        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)) +        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)) +        print("_versioned_lib_soname: name={!r}".format(name))      major = version.split('.')[0]      soname = name + '.' + major      if Verbose: -        print("_versioned_lib_soname: soname={:r}".format(soname)) +        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 lirbrary. +    """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)) +        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)) +            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())) +        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)) +        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) @@ -211,50 +224,63 @@ def _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, so      # We create direct symlinks, not daisy-chained.      if link0 == libnode:          # This enables SHLIBVERSION without periods (e.g. SHLIBVERSION=1) -        symlinks = [ (link1, libnode) ] +        symlinks = [(link1, libnode)]      else:          # This handles usual SHLIBVERSION, i.e. '1.2', '1.2.3', etc. -        symlinks = [ (link0, libnode), (link1, libnode) ] +        symlinks = [(link0, libnode), (link1, libnode)]      if Verbose: -        print("_versioned_lib_symlinks: return symlinks={:r}".format(SCons.Tool.StringizeLibSymlinks(symlinks))) +        print("_versioned_lib_symlinks: return symlinks={!r}".format(SCons.Tool.StringizeLibSymlinks(symlinks)))      return symlinks +  def _versioned_shlib_symlinks(env, libnode, version, prefix, suffix): -    nf = _versioned_shlib_name -    sf = _versioned_shlib_soname -    return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, nf, sf) +    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): -    nf = _versioned_ldmod_name -    sf = _versioned_ldmod_soname -    return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, nf, sf) +    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, +        '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 +    try: +        tool = kw['tool'] +    except KeyError: +        pass      use_soname = False -    try: use_soname = kw['use_soname'] -    except KeyError: pass +    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 @@ -284,22 +310,25 @@ def generate(env):      SCons.Tool.createSharedLibBuilder(env)      SCons.Tool.createProgBuilder(env) -    env['SHLINK']      = '$LINK' +    env['SHLINK'] = '$LINK'      env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared') -    env['SHLINKCOM']   = '$SHLINK -o $TARGET $SHLINKFLAGS $__SHLIBVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' -    # don't set up the emitter, cause AppendUnique will generate a list +    env['SHLINKCOM'] = '$SHLINK -o $TARGET $SHLINKFLAGS $__SHLIBVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' + +    # don't set up the emitter, because AppendUnique will generate a list      # starting with None :-( -    env.Append(SHLIBEMITTER = [shlib_emitter]) -    env['SMARTLINK']   = smart_link -    env['LINK']        = "$SMARTLINK" -    env['LINKFLAGS']   = SCons.Util.CLVar('') +    env.Append(SHLIBEMITTER=[shlib_emitter]) + +    env['SMARTLINK'] = smart_link +    env['LINK'] = "$SMARTLINK" +    env['LINKFLAGS'] = SCons.Util.CLVar('') +      # __RPATH is only set to something ($_RPATH typically) on platforms that support it. -    env['LINKCOM']     = '$LINK -o $TARGET $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' -    env['LIBDIRPREFIX']='-L' -    env['LIBDIRSUFFIX']='' -    env['_LIBFLAGS']='${_stripixes(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, LIBPREFIXES, LIBSUFFIXES, __env__)}' -    env['LIBLINKPREFIX']='-l' -    env['LIBLINKSUFFIX']='' +    env['LINKCOM'] = '$LINK -o $TARGET $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' +    env['LIBDIRPREFIX'] = '-L' +    env['LIBDIRSUFFIX'] = '' +    env['_LIBFLAGS'] = '${_stripixes(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, LIBPREFIXES, LIBSUFFIXES, __env__)}' +    env['LIBLINKPREFIX'] = '-l' +    env['LIBLINKSUFFIX'] = ''      if env['PLATFORM'] == 'hpux':          env['SHLIBSUFFIX'] = '.sl' @@ -311,14 +340,16 @@ def generate(env):      # setting them the same means that LoadableModule works everywhere.      SCons.Tool.createLoadableModuleBuilder(env)      env['LDMODULE'] = '$SHLINK' -    env.Append(LDMODULEEMITTER = [ldmod_emitter]) +    env.Append(LDMODULEEMITTER=[ldmod_emitter])      env['LDMODULEPREFIX'] = '$SHLIBPREFIX'      env['LDMODULESUFFIX'] = '$SHLIBSUFFIX'      env['LDMODULEFLAGS'] = '$SHLINKFLAGS' -    env['LDMODULECOM'] = '$LDMODULE -o $TARGET $LDMODULEFLAGS $__LDMODULEVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' +    env[ +        'LDMODULECOM'] = '$LDMODULE -o $TARGET $LDMODULEFLAGS $__LDMODULEVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS'      env['LDMODULEVERSION'] = '$SHLIBVERSION'      env['LDMODULENOVERSIONSYMLINKS'] = '$SHLIBNOVERSIONSYMLINKS' +  def exists(env):      # This module isn't really a Tool on its own, it's common logic for      # other linkers.  | 
