summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Managan <managan1@llnl.gov>2012-11-05 12:26:20 -0800
committerRobert Managan <managan1@llnl.gov>2012-11-05 12:26:20 -0800
commitd65f381faf88bbb5e2df9fe274120b89f7032a04 (patch)
treecca16af87c1d2f5950c74bec4133fa647601950e
parenta0bd78c78dae55137a855ec426bcd736b2572301 (diff)
downloadscons-d65f381faf88bbb5e2df9fe274120b89f7032a04.tar.gz
Start to clean up changes in __init__.py and link.py. Add support in install.py for versioned shared libs. Still need test case.
-rw-r--r--src/engine/SCons/Tool/__init__.py82
-rw-r--r--src/engine/SCons/Tool/install.py79
-rw-r--r--src/engine/SCons/Tool/link.py59
3 files changed, 167 insertions, 53 deletions
diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py
index 708fc647..36e2a564 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 7e5fed5e..50a96a97 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 4ad4948d..9c9600e0 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'