Rob Managan avatar Rob Managan committed a44ba9a

Start to clean up changes in __init__.py and link.py. Add support in install.py for versioned shared libs. Still need test case.

Comments (0)

Files changed (3)

src/engine/SCons/Tool/__init__.py

 
     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')
         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:
     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
+    return result
 
-ShLibAction = SCons.Action.Action(VersionedSharedLibrary, "$SHLINKCOMSTR")
+ShLibAction = SCons.Action.Action(VersionedSharedLibrary, None)
 
 def createSharedLibBuilder(env):
     """This is a utility function that creates the SharedLibrary
 # indent-tabs-mode:nil
 # End:
 # vim: set expandtab tabstop=4 shiftwidth=4:
+
+
+

src/engine/SCons/Tool/install.py

 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 import os
+import re
 import shutil
 import stat
 
         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."""
     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)
 

src/engine/SCons/Tool/link.py

         # 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."""
     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"
     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' 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.