Commits

Rob Managan committed 30f4014

removed versioned library support from Install and put it in InstallVersionedLib

Comments (0)

Files changed (6)

       so biber is called automatically if biblatex requires it.
     - Add SHLIBVERSION as an option that tells SharedLibrary to build
       a versioned shared library and create the required symlinks.
-      Update Install to create the required symlinks when installing
-      a versioned shared library.
+      Add builder InstallVersionedLib to create the required symlinks 
+      installing a versioned shared library.
 
 RELEASE 2.2.0 - Mon, 05 Aug 2012 15:37:48 +0000
 

src/engine/SCons/Tool/__init__.py

     linknames = []
     if version.count(".") != 2:
         # We need a version string of the form x.y.z to proceed
+        # Several changes need to be made to support versions like x.y
         raise ValueError
 
     if platform == 'darwin':
 	# the ToolInitializer class.
 
 def Initializers(env):
-    ToolInitializer(env, ['install'], ['_InternalInstall', '_InternalInstallAs'])
+    ToolInitializer(env, ['install'], ['_InternalInstall', '_InternalInstallAs', '_InternalInstallVersionedLib'])
     def Install(self, *args, **kw):
         return self._InternalInstall(*args, **kw)
     def InstallAs(self, *args, **kw):
         return self._InternalInstallAs(*args, **kw)
+    def InstallVersionedLib(self, *args, **kw):
+        return self._InternalInstallVersionedLib(*args, **kw)
     env.AddMethod(Install)
     env.AddMethod(InstallAs)
+    env.AddMethod(InstallVersionedLib)
 
 def FindTool(tools, env):
     for tool in tools:
 # End:
 # vim: set expandtab tabstop=4 shiftwidth=4:
 
-
-

src/engine/SCons/Tool/install.py

         shutil.copy2(source, dest)
         st = os.stat(source)
         os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
+
+    return 0
+
+#
+# Functions doing the actual work of the InstallVersionedLib Builder.
+#
+def copyFuncVersionedLib(dest, source, env):
+    """Install a versioned library into a destination by copying,
+    (including copying permission/mode bits) and then creating
+    required symlinks."""
+
+    if os.path.isdir(source):
+        raise SCons.Errors.UserError("cannot install directory `%s' as a version library" % str(source) )
+    else:
+        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
 
     return 0
 
+def installFuncVersionedLib(target, source, env):
+    """Install a versioned library into a target using the function specified
+    as the INSTALLVERSIONEDLIB construction variable."""
+    try:
+        install = env['INSTALLVERSIONEDLIB']
+    except KeyError:
+        raise SCons.Errors.UserError('Missing INSTALLVERSIONEDLIB construction variable.')
+
+    assert len(target)==len(source), \
+           "Installing source %s into target %s: target and source lists must have same length."%(list(map(str, source)), list(map(str, target)))
+    for t,s in zip(target,source):
+        if install(t.get_path(),s.get_path(),env):
+            return 1
+
+    return 0
+
 def stringFunc(target, source, env):
     installstr = env.get('INSTALLSTR')
     if installstr:
     scons call will be collected.
     """
     global _INSTALLED_FILES, _UNIQUE_INSTALLED_FILES
+    _INSTALLED_FILES.extend(target)
+
+    _UNIQUE_INSTALLED_FILES = None
+    return (target, source)
+
+def add_versioned_targets_to_INSTALLED_FILES(target, source, env):
+    """ an emitter that adds all target files to the list stored in the
+    _INSTALLED_FILES global variable. This way all installed files of one
+    scons call will be collected.
+    """
+    global _INSTALLED_FILES, _UNIQUE_INSTALLED_FILES
     Verbose = False
     _INSTALLED_FILES.extend(target)
 
 #
 # The Builder Definition
 #
-install_action   = SCons.Action.Action(installFunc, stringFunc)
-installas_action = SCons.Action.Action(installFunc, stringFunc)
+install_action       = SCons.Action.Action(installFunc, stringFunc)
+installas_action     = SCons.Action.Action(installFunc, stringFunc)
+installVerLib_action = SCons.Action.Action(installFuncVersionedLib, stringFunc)
 
 BaseInstallBuilder               = None
 
         result.extend(BaseInstallBuilder(env, tgt, src, **kw))
     return result
 
+BaseVersionedInstallBuilder = None
+
+def InstallVersionedBuilderWrapper(env, target=None, source=None, dir=None, **kw):
+    if target and dir:
+        import SCons.Errors
+        raise SCons.Errors.UserError("Both target and dir defined for Install(), only one may be defined.")
+    if not dir:
+        dir=target
+
+    import SCons.Script
+    install_sandbox = SCons.Script.GetOption('install_sandbox')
+    if install_sandbox:
+        target_factory = DESTDIR_factory(env, install_sandbox)
+    else:
+        target_factory = env.fs
+
+    try:
+        dnodes = env.arg2nodes(dir, target_factory.Dir)
+    except TypeError:
+        raise SCons.Errors.UserError("Target `%s' of Install() is a file, but should be a directory.  Perhaps you have the Install() arguments backwards?" % str(dir))
+    sources = env.arg2nodes(source, env.fs.Entry)
+    tgt = []
+    for dnode in dnodes:
+        for src in sources:
+            # Prepend './' so the lookup doesn't interpret an initial
+            # '#' on the file name portion as meaning the Node should
+            # be relative to the top-level SConstruct directory.
+            target = env.fs.Entry('.'+os.sep+src.name, dnode)
+            tgt.extend(BaseVersionedInstallBuilder(env, target, src, **kw))
+    return tgt
+
 added = None
 
 def generate(env):
                               emitter        = [ add_targets_to_INSTALLED_FILES, ],
                               name           = 'InstallBuilder')
 
+    global BaseVersionedInstallBuilder
+    if BaseVersionedInstallBuilder is None:
+        install_sandbox = GetOption('install_sandbox')
+        if install_sandbox:
+            target_factory = DESTDIR_factory(env, install_sandbox)
+        else:
+            target_factory = env.fs
+
+        BaseVersionedInstallBuilder = SCons.Builder.Builder(
+                                       action         = installVerLib_action,
+                                       target_factory = target_factory.Entry,
+                                       source_factory = env.fs.Entry,
+                                       multi          = 1,
+                                       emitter        = [ add_versioned_targets_to_INSTALLED_FILES, ],
+                                       name           = 'InstallVersionedBuilder')
+
     env['BUILDERS']['_InternalInstall'] = InstallBuilderWrapper
     env['BUILDERS']['_InternalInstallAs'] = InstallAsBuilderWrapper
+    env['BUILDERS']['_InternalInstallVersionedLib'] = InstallVersionedBuilderWrapper
 
     # We'd like to initialize this doing something like the following,
     # but there isn't yet support for a ${SOURCE.type} expansion that
     except KeyError:
         env['INSTALL']    = copyFunc
 
+    try:
+        env['INSTALLVERSIONEDLIB']
+    except KeyError:
+        env['INSTALLVERSIONEDLIB']    = copyFuncVersionedLib
+
 def exists(env):
     return 1
 

src/engine/SCons/Tool/install.xml

 The names of the specified source files or directories
 remain the same within the destination directory. The
 sources may be given as a string or as a node returned by
-a builder. If the source is a versioned shared library
-the appropriate symlinks to it will be generated.
+a builder. 
 
 <example>
 env.Install('/usr/local/bin', source = ['foo', 'bar'])
 source
 arguments list different numbers of files or directories.
 
+<builder name="InstallVersionedLib">
+<summary>
+Installs a versioned shared library. The &cv-link-SHLIBVERSION; 
+construction variable should be defined in the environment
+to confirm the version number in the library name.
+The symlinks appropriate to the architecture will be generated.
+
 <example>
 env.InstallAs(target = '/usr/local/bin/foo',
               source = 'foo_debug')

src/engine/SCons/Tool/link.py

     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' 

test/LINK/VersionedLib.py

 mylib = env.SharedLibrary('test', objs, SHLIBVERSION = '2.5.4')
 env.Program(source=['testapp.c',mylib])
 env.Program(target=['testapp2'],source=['testapp.c','libtest.dylib'])
-instnode = env.Install("#/installtest",mylib)
+instnode = env.InstallVersionedLib("#/installtest",mylib)
 env.Default(instnode)
 """)
 
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.