diff options
author | Robert Managan <managan1@llnl.gov> | 2012-11-05 20:26:20 (GMT) |
---|---|---|
committer | Robert Managan <managan1@llnl.gov> | 2012-11-05 20:26:20 (GMT) |
commit | 66ff94edc6d248131e1038a664c79f96805bcd89 (patch) | |
tree | 9d6d975da6e4e150db25d8e513f6fb40b4596ed5 /src/engine | |
parent | c073b68aec779a67f72fb72e14b386ed5709af59 (diff) | |
download | SCons-66ff94edc6d248131e1038a664c79f96805bcd89.zip SCons-66ff94edc6d248131e1038a664c79f96805bcd89.tar.gz SCons-66ff94edc6d248131e1038a664c79f96805bcd89.tar.bz2 |
Start to clean up changes in __init__.py and link.py. Add support in install.py for versioned shared libs. Still need test case.
Diffstat (limited to 'src/engine')
-rw-r--r-- | src/engine/SCons/Tool/__init__.py | 82 | ||||
-rw-r--r-- | src/engine/SCons/Tool/install.py | 79 | ||||
-rw-r--r-- | src/engine/SCons/Tool/link.py | 59 |
3 files changed, 167 insertions, 53 deletions
diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 708fc64..36e2a56 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -236,12 +236,53 @@ def createStaticLibBuilder(env): return static_lib +def VersionShLibLinkNames(version, libname, env): + """Generate names of symlinks to the versioned shared library""" + Verbose = False + platform = env.subst('$PLATFORM') + shlib_suffix = env.subst('$SHLIBSUFFIX') + shlink_flags = SCons.Util.CLVar(env.subst('$SHLINKFLAGS')) + + linknames = [] + if version.count(".") != 2: + # We need a version string of the form x.y.z to proceed + raise ValueError + + if platform == 'darwin': + # For libfoo.x.y.z.dylib, linknames libfoo.so + suffix_re = re.escape('.' + version + shlib_suffix) + linkname = re.sub(suffix_re, shlib_suffix, libname) + if Verbose: + print "VersionShLibLinkNames: linkname = ",linkname + linknames.append(linkname) + elif platform == 'posix': + # For libfoo.so.x.y.z, linknames libfoo.so libfoo.so.x.y libfoo.so.x + suffix_re = re.escape(shlib_suffix + '.' + version) + # First linkname has no version number + linkname = re.sub(suffix_re, shlib_suffix, libname) + if Verbose: + print "VersionShLibLinkNames: linkname = ",linkname + linknames.append(linkname) + versionparts = version.split('.') + major_name = linkname + "." + versionparts[0] + minor_name = major_name + "." + versionparts[1] + for linkname in [major_name, minor_name]: + if Verbose: + print "VersionShLibLinkNames: linkname ",linkname, ", target ",libname + linknames.append(linkname) + return linknames + def VersionedSharedLibrary(target = None, source= None, env=None): + """Build a shared library. If the environment has SHLIBVERSION +defined make a versioned shared library and create the appropriate +symlinks for the platform we are on""" Verbose = False try: version = env.subst('$SHLIBVERSION') except KeyError: version = None + + # libname includes the version number if one was given libname = target[0].name platform = env.subst('$PLATFORM') shlib_suffix = env.subst('$SHLIBSUFFIX') @@ -252,10 +293,11 @@ def VersionedSharedLibrary(target = None, source= None, env=None): print "VersionShLib: shlib_suffix = ",shlib_suffix if version: - # set the shared lib link flags + # set the shared library link flags if platform == 'posix': suffix_re = re.escape(shlib_suffix + '.' + version) (major, age, revision) = version.split(".") + # soname will have only the major version number in it soname = re.sub(suffix_re, shlib_suffix, libname) + '.' + major shlink_flags += [ '-Wl,-Bsymbolic', '-Wl,-soname=%s' % soname ] if Verbose: @@ -277,39 +319,14 @@ def VersionedSharedLibrary(target = None, source= None, env=None): result = SCons.Defaults.ShLinkAction(target, source, envlink) if version: + linknames = VersionShLibLinkNames(version, libname, env) # keep name with version in it lib_ver = libname - if platform == 'darwin': - if version.count(".") != 2: - # We need a library name in libfoo.x.y.z.dylib form to proceed - raise ValueError - # create sym link of linkname -> lib_ver, linkname has no version number - suffix_re = re.escape('.' + version + shlib_suffix) - linkname = re.sub(suffix_re, shlib_suffix, libname) - if Verbose: - print "VersionShLib: linkname = ",linkname + for linkname in linknames: os.symlink(lib_ver,linkname) - elif platform == 'posix': - if version.count(".") != 2: - # We need a library name in libfoo.so.x.y.z form to proceed - raise ValueError - suffix_re = re.escape(shlib_suffix + '.' + version) - # remove version number for linkname - linkname = re.sub(suffix_re, shlib_suffix, libname) - if Verbose: - print "VersionShLib: linkname = ",linkname - os.symlink(lib_ver, linkname) - # For libfoo.so.x.y.z, links libfoo.so libfoo.so.x.y libfoo.so.x - versionparts = version.split('.') - major_name = linkname + "." + versionparts[0] - minor_name = major_name + "." + versionparts[1] - for linkname in [major_name, minor_name]: - if Verbose: - print " linkname ",linkname, ", target ",libname - os.symlink(lib_ver,linkname) - return False - -ShLibAction = SCons.Action.Action(VersionedSharedLibrary, "$SHLINKCOMSTR") + return result + +ShLibAction = SCons.Action.Action(VersionedSharedLibrary, None) def createSharedLibBuilder(env): """This is a utility function that creates the SharedLibrary @@ -757,3 +774,6 @@ def tool_list(platform, env): # indent-tabs-mode:nil # End: # vim: set expandtab tabstop=4 shiftwidth=4: + + + diff --git a/src/engine/SCons/Tool/install.py b/src/engine/SCons/Tool/install.py index 7e5fed5..50a96a9 100644 --- a/src/engine/SCons/Tool/install.py +++ b/src/engine/SCons/Tool/install.py @@ -33,6 +33,7 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os +import re import shutil import stat @@ -118,9 +119,73 @@ def copyFunc(dest, source, env): shutil.copy2(source, dest) st = os.stat(source) os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE) + versionedLibLinks(dest, source, env) return 0 +def versionedLibVersion(dest, env): + """Check if dest is a version shared library name. Return version libname if it is.""" + Verbose = False + platform = env.subst('$PLATFORM') + if not (platform == 'posix' or platform == 'darwin'): + return (None, None, None) + + libname = os.path.basename(dest) + install_dir = os.path.dirname(dest) + shlib_suffix = env.subst('$SHLIBSUFFIX') + # See if the source name is a versioned shared library, get the version number + result = False + + version_re = re.compile("[0-9]+\\.[0-9]+\\.[0-9a-zA-Z]+") + version_File = None + if platform == 'posix': + # handle unix names + versioned_re = re.compile(re.escape(shlib_suffix + '.') + "[0-9]+\\.[0-9]+\\.[0-9a-zA-Z]+") + result = versioned_re.findall(libname) + if result: + version_File = version_re.findall(versioned_re.findall(libname)[-1])[-1] + elif platform == 'darwin': + # handle OSX names + versioned_re = re.compile("\\.[0-9]+\\.[0-9]+\\.[0-9a-zA-Z]+" + re.escape(shlib_suffix) ) + result = versioned_re.findall(libname) + if result: + version_File = version_re.findall(versioned_re.findall(libname)[-1])[-1] + + if Verbose: + print "install: version_File ", version_File + # result is False if we did not find a versioned shared library name, so return and empty list + if not result: + return (None, libname, install_dir) + + version = None + # get version number from the environment + try: + version = env.subst('$SHLIBVERSION') + except KeyError: + version = None + + if version != version_File: + #raise SCons.Errors.UserError("SHLIBVERSION '%s' does not match the version # '%s' in the filename" % (version, version_File) ) + print "SHLIBVERSION '%s' does not match the version # '%s' in the filename, proceeding based on file name" % (version, version_File) + version = version_File + return (version, libname, install_dir) + +def versionedLibLinks(dest, source, env): + """If we are installing a versioned shared library create the required links.""" + Verbose = False + linknames = [] + version, libname, install_dir = versionedLibVersion(dest, env) + + if version != None: + # libname includes the version number if one was given + linknames = SCons.Tool.VersionShLibLinkNames(version,libname,env) + for linkname in linknames: + if Verbose: + print "make link of %s to %s" %(libname, os.path.join(install_dir, linkname)) + fulllinkname = os.path.join(install_dir, linkname) + os.symlink(libname,fulllinkname) + return + def installFunc(target, source, env): """Install a source file into a target using the function specified as the INSTALL construction variable.""" @@ -158,7 +223,21 @@ def add_targets_to_INSTALLED_FILES(target, source, env): scons call will be collected. """ global _INSTALLED_FILES, _UNIQUE_INSTALLED_FILES + Verbose = False _INSTALLED_FILES.extend(target) + + # see if we have a versioned shared library, if so generate side effects + version, libname, install_dir = versionedLibVersion(target[0].path, env) + if version != None: + # generate list of link names + linknames = SCons.Tool.VersionShLibLinkNames(version,libname,env) + for linkname in linknames: + if Verbose: + print "make side effect of %s" % os.path.join(install_dir, linkname) + fulllinkname = os.path.join(install_dir, linkname) + env.SideEffect(fulllinkname,target[0]) + env.Clean(target[0],fulllinkname) + _UNIQUE_INSTALLED_FILES = None return (target, source) diff --git a/src/engine/SCons/Tool/link.py b/src/engine/SCons/Tool/link.py index 4ad4948..9c9600e 100644 --- a/src/engine/SCons/Tool/link.py +++ b/src/engine/SCons/Tool/link.py @@ -74,45 +74,60 @@ def shlib_emitter(target, source, env): # target[0] comes in as libtest.so. Add the version extensions version = env.subst('$SHLIBVERSION') if version: + version_names = shlib_emitter_names(target, source, env) + # change the name of the target to include the version number + target[0].name = version_names[0] + for name in version_names: + env.SideEffect(name, target[0]) + env.Clean(target[0], name) + except KeyError: + version = None + return (target, source) + +def shlib_emitter_names(target, source, env): + """Return list of file names that are side effects for a versioned library build. The first name in the list is the new name for the target""" + Verbose = False + platform = env.subst('$PLATFORM') + version_names = [] + try: + # target[0] comes in as libtest.so. Add the version extensions + version = env.subst('$SHLIBVERSION') + if version.count(".") != 2: + # We need a version of the form x.y.z to proceed + raise ValueError + if version: if platform == 'posix': versionparts = version.split('.') name = target[0].name # generate library name with the version number version_name = target[0].name + '.' + version - # change the name of the target to version_name - target[0].name = version_name if Verbose: - print "shlib_emitter: target is ", version_name - print "shlib_emitter: side effect: ", name - # make name w/o version number a side effect (will be a sym link) - env.SideEffect(version_name, target[0]) - env.Clean(target[0], version_name) + print "shlib_emitter_names: target is ", version_name + print "shlib_emitter_names: side effect: ", name + # add version_name to list of names to be a Side effect + version_names.append(version_name) if Verbose: - print "shlib_emitter: versionparts ",versionparts + print "shlib_emitter_names: versionparts ",versionparts for ver in versionparts[0:-1]: name = name + '.' + ver if Verbose: - print "shlib_emitter: side effect: ", name - # make side effects of sym links with partial version number - env.SideEffect(name, target[0]) - env.Clean(target[0], name) + print "shlib_emitter_names: side effect: ", name + # add name to list of names to be a Side effect + version_names.append(name) elif platform == 'darwin': shlib_suffix = env.subst('$SHLIBSUFFIX') name = target[0].name # generate library name with the version number suffix_re = re.escape(shlib_suffix) version_name = re.sub(suffix_re, '.' + version + shlib_suffix, name) - # change the name of the target to version_name - target[0].name = version_name if Verbose: - print "shlib_emitter: target is ", version_name - print "shlib_emitter: side effect: ", name - # make name w/o version number a side effect (will be a sym link) - env.SideEffect(version_name, target[0]) - env.Clean(target[0], version_name) + print "shlib_emitter_names: target is ", version_name + print "shlib_emitter_names: side effect: ", name + # add version_name to list of names to be a Side effect + version_names.append(version_name) except KeyError: version = None - return (target, source) + return version_names def generate(env): """Add Builders and construction variables for gnulink to an Environment.""" @@ -123,7 +138,7 @@ def generate(env): env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared') env['SHLINKCOM'] = '$SHLINK -o $TARGET $SHLINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' # don't set up the emitter, cause AppendUnique will generate a list - # starting with None :-( + # starting with None env.Append(SHLIBEMITTER = [shlib_emitter]) env['SMARTLINK'] = smart_link env['LINK'] = "$SMARTLINK" @@ -147,7 +162,7 @@ def generate(env): SCons.Tool.createLoadableModuleBuilder(env) env['LDMODULE'] = '$SHLINK' # don't set up the emitter, cause AppendUnique will generate a list - # starting with None :-( + # starting with None env.Append(LDMODULEEMITTER='$SHLIBEMITTER') env['LDMODULEPREFIX'] = '$SHLIBPREFIX' env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' |