diff options
Diffstat (limited to 'engine/SCons/Tool/link.py')
-rw-r--r-- | engine/SCons/Tool/link.py | 185 |
1 files changed, 108 insertions, 77 deletions
diff --git a/engine/SCons/Tool/link.py b/engine/SCons/Tool/link.py index 1ff27a8..2347c94 100644 --- a/engine/SCons/Tool/link.py +++ b/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 74b2c53bc42290e911b334a6b44f187da698a668 2017/11/14 13:16:53 bdbaddog" +__revision__ = "src/engine/SCons/Tool/link.py 72ae09dc35ac2626f8ff711d8c4b30b6138e08e3 2019-08-08 14:50:06 bdeegan" 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. |