Commits

Rob Managan committed 944aa4d Merge

merge main line changes

Comments (0)

Files changed (26)

QMTest/TestCmd.py

 
 re_space = re.compile('\s')
 
-_Cleanup = []
-
-def _clean():
-    global _Cleanup
-    cleanlist = [ c for c in _Cleanup if c ]
-    del _Cleanup[:]
-    cleanlist.reverse()
-    for test in cleanlist:
-        test.cleanup()
-
-atexit.register(_clean)
-
 def _caller(tblist, skip):
     string = ""
     arr = []
             raise Exception(disconnect_message)
         data = memoryview(data)[sent:]
 
+_Cleanup = []
+
+def _clean():
+    global _Cleanup
+    cleanlist = [ c for c in _Cleanup if c ]
+    del _Cleanup[:]
+    cleanlist.reverse()
+    for test in cleanlist:
+        test.cleanup()
+
+atexit.register(_clean)
 
 
 class TestCmd(object):
                 shutil.rmtree(dir, ignore_errors = 1)
             self._dirlist = []
 
-        try:
             global _Cleanup
-            _Cleanup.remove(self)
-        except (AttributeError, ValueError):
-            pass
+            if self in _Cleanup:
+                _Cleanup.remove(self)
 
     def command_args(self, program = None,
                            interpreter = None,
 
         #
         self._dirlist.append(path)
+
         global _Cleanup
-        try:
-            _Cleanup.index(self)
-        except ValueError:
+        if self not in _Cleanup:
             _Cleanup.append(self)
 
         return path
                             'LICENSE.txt',
                             'README.txt',
                             'RELEASE.txt',
-                            'os_spawnv_fix.diff',
                             'scons.1',
                             'sconsign.1',
                             'scons-time.1',
         if len(args) > 1:
             print arg + ':'
 
-        command = [sys.executable, 'runtest.py', '--noqmtest']
+        command = [sys.executable, 'runtest.py']
         if opts.package:
             command.extend(['-p', opts.package])
         command.append(arg)

bin/scons-test.py

 # so that problems on different platforms can be identified sooner.
 #
 
+import atexit
 import getopt
 import imp
 import os
         import shutil
         os.chdir(startdir)
         shutil.rmtree(tempdir)
-    sys.exitfunc = cleanup
+    atexit.register(cleanup)
 
 # Fetch the input file if it happens to be across a network somewhere.
 # Ohmigod, does Python make this simple...
       * replaced `-o FILE --xml` combination with `--xml FILE`
       * changed `-o, --output FILE` option to capture stdout/stderr output
         from runtest.py
+    - Remove os_spawnv_fix.diff patch required to enable parallel builds
+      support prior to Python 2.2
 
   From Juan Lang:
     - Fix WiX Tool to use .wixobj rather than .wxiobj for compiler output
       in LaTeX's glossaries package and the files it creates.
     - Improve support for new versions of biblatex in the TeX builder 
       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.
+      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/MANIFEST-xml.in

File contents unchanged.

src/engine/MANIFEST.in

File contents unchanged.

src/engine/SCons/Environment.py

             install._UNIQUE_INSTALLED_FILES = SCons.Util.uniquer_hashables(install._INSTALLED_FILES)
         return install._UNIQUE_INSTALLED_FILES
 
+
 class OverrideEnvironment(Base):
     """A proxy that overrides variables in a wrapped construction
     environment by returning values from an overrides dictionary in

src/engine/SCons/Script/__init__.py

File contents unchanged.

src/engine/SCons/Tool/__init__.py

 
 import imp
 import sys
+import re
+import os
+import shutil
 
 import SCons.Builder
 import SCons.Errors
 
     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
+        # Several changes need to be made to support versions like x.y
+        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]
+        #Only add link for major_name
+        #for linkname in [major_name, minor_name]:
+        for linkname in [major_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')
+    shlink_flags = SCons.Util.CLVar(env.subst('$SHLINKFLAGS'))
+    if Verbose:
+        print "VersionShLib: libname      = ",libname
+        print "VersionShLib: platform     = ",platform
+        print "VersionShLib: shlib_suffix = ",shlib_suffix
+        print "VersionShLib: target = ",str(target[0])
+
+    if version:
+        # 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:
+                print " soname ",soname,", shlink_flags ",shlink_flags
+        elif platform == 'cygwin':
+            shlink_flags += [ '-Wl,-Bsymbolic',
+                              '-Wl,--out-implib,${TARGET.base}.a' ]
+        elif platform == 'darwin':
+            shlink_flags += [ '-current_version', '%s' % version,
+                              '-compatibility_version', '%s' % version,
+                              '-undefined', 'dynamic_lookup' ]
+        if Verbose:
+            print "VersionShLib: shlink_flags = ",shlink_flags
+        envlink = env.Clone()
+        envlink['SHLINKFLAGS'] = shlink_flags
+    else:
+        envlink = env
+
+    result = SCons.Defaults.ShLinkAction(target, source, envlink)
+
+    if version:
+        # here we need the full pathname so the links end up in the right directory
+        libname = target[0].path
+        linknames = VersionShLibLinkNames(version, libname, env)
+        if Verbose:
+            print "VerShLib: linknames ",linknames
+        # Here we just need the file name w/o path as the target of the link
+        lib_ver = target[0].name
+        # make symlink of adjacent names in linknames
+        for count in range(len(linknames)):
+            linkname = linknames[count]
+            if count > 0:
+                os.symlink(os.path.basename(linkname),lastname)
+                if Verbose:
+                    print "VerShLib: made sym link of %s -> %s" % (lastname,linkname)
+            lastname = linkname
+        # finish chain of sym links with link to the actual library
+        os.symlink(lib_ver,lastname)
+        if Verbose:
+            print "VerShLib: made sym link of %s -> %s" % (lib_ver,linkname)
+    return result
+
+ShLibAction = SCons.Action.Action(VersionedSharedLibrary, None)
+
 def createSharedLibBuilder(env):
     """This is a utility function that creates the SharedLibrary
     Builder in an Environment if it is not there already.
     except KeyError:
         import SCons.Defaults
         action_list = [ SCons.Defaults.SharedCheck,
-                        SCons.Defaults.ShLinkAction ]
+                        ShLibAction ]
         shared_lib = SCons.Builder.Builder(action = action_list,
                                            emitter = "$SHLIBEMITTER",
                                            prefix = '$SHLIBPREFIX',
 	# 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:
 # indent-tabs-mode:nil
 # End:
 # vim: set expandtab tabstop=4 shiftwidth=4:
+

src/engine/SCons/Tool/__init__.xml

 and a loadable module (explicitly loaded by user action).
 For maximum portability, use the &b-LoadableModule; builder for the latter.
 
+When the &cv-link-SHLIBVERSION; construction variable is defined a versioned
+shared library is created. This modifies the &cv-link-SHLINKFLAGS; as required,
+adds the version number to the library name, and creates the symlinks that
+are needed. &cv-link-SHLIBVERSION; needs to be of the form X.Y.Z, where X
+and Y are numbers, and Z is a number but can also contain letters to designate
+alpha, beta, or release candidate patch levels.
+
+This builder may create multiple links to the library. On a POSIX system,
+for the shared library libbar.so.2.3.1, the links created would be
+libbar.so, libbar.so.2, and libbar.so.2.3; on a Darwin (OSX) system
+the library would be libbar.2.3.1.dylib and the link would be
+libbar.dylib.
+
 On Windows systems, specifying
 <literal>register=1</literal>
 will cause the <filename>.dll</filename> to be
 TODO
 </summary>
 </cvar>
+
+<cvar name="SHLIBVERSION">
+<summary>
+When this construction variable is defined, a versioned shared library
+is created. This modifies the &cv-link-SHLINKFLAGS; as required, adds
+the version number to the library name, and creates the symlinks that
+are needed. &cv-link-SHLIBVERSION; needs to be of the form X.Y.Z,
+where X and Y are numbers, and Z is a number but can also contain
+letters to designate alpha, beta, or release candidate patch levels.
+</summary>
+</cvar>

src/engine/SCons/Tool/dmd.py

File contents unchanged.

src/engine/SCons/Tool/dmd.xml

File contents unchanged.

src/engine/SCons/Tool/install.py

 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 import os
+import re
 import shutil
 import stat
 
 
     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
+
+def versionedLibVersion(dest, env):
+    """Check if dest is a version shared library name. Return version, libname, & install_dir 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."""
 
     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:
     """
     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)
+
+    # 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)
 
 #
 # 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

 in the specified target,
 which must be a directory.
 The names of the specified source files or directories
-remain the same within the destination directory.
+remain the same within the destination directory. The
+sources may be given as a string or as a node returned by
+a builder.
 
 <example>
 env.Install('/usr/local/bin', source = ['foo', 'bar'])
 and
 source
 arguments list different numbers of files or directories.
+</summary>
+</builder>
+
+<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',

src/engine/SCons/Tool/link.py

 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
+import re
+
 import SCons.Defaults
 import SCons.Tool
 import SCons.Util
     return '$CC'
 
 def shlib_emitter(target, source, env):
+    Verbose = False
+    platform = env.subst('$PLATFORM')
     for tgt in target:
         tgt.attributes.shared = 1
+    try:
+        # 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)
+                if Verbose:
+                    print "shlib_emitter: add side effect - ",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
+                if Verbose:
+                    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_names: versionparts ",versionparts
+                for ver in versionparts[0:-1]:
+                    name = name + '.' + ver
+                    if Verbose:
+                        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)
+                if Verbose:
+                    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 version_names
+
 def generate(env):
     """Add Builders and construction variables for gnulink to an Environment."""
     SCons.Tool.createSharedLibBuilder(env)

src/engine/SCons/cppTests.py

 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
+import atexit
 import sys
 import unittest
 
         if os.path.exists(dir):
             shutil.rmtree(dir)
 
-sys.exitfunc = _clean
+atexit.register(_clean)
 
 class fileTestCase(unittest.TestCase):
     cpp_class = cpp.DumbPreProcessor

src/engine/SCons/exitfuncs.py

 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 
+import atexit
 
 _exithandlers = []
 def _run_exitfuncs():
     """
     _exithandlers.append((func, targs, kargs))
 
-import sys
 
-try:
-    x = sys.exitfunc
-
-    # if x isn't our own exit func executive, assume it's another
-    # registered exit function - append it to our list...
-    if x != _run_exitfuncs:
-        register(x)
-
-except AttributeError:
-    pass
-
-# make our exit function get run by python when it exits:    
-sys.exitfunc = _run_exitfuncs
-
-del sys
+# make our exit function get run by python when it exits
+atexit.register(_run_exitfuncs)
 
 # Local Variables:
 # tab-width:4

src/os_spawnv_fix.diff

-? dist/src/Mac/IDE scripts/Hold option to open a script
-? dist/src/Mac/IDE scripts/Insert file name
-? dist/src/Mac/IDE scripts/Insert folder name
-? dist/src/Mac/IDE scripts/Search Python Documentation
-? dist/src/Mac/IDE scripts/Hack/Remove .pyc files
-? dist/src/Mac/IDE scripts/Hack/Toolbox Assistant
-Index: dist/src/Modules/posixmodule.c
-===================================================================
-RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v
-retrieving revision 2.213
-diff -c -c -r2.213 posixmodule.c
-*** dist/src/Modules/posixmodule.c	2001/12/03 20:41:00	2.213
---- dist/src/Modules/posixmodule.c	2001/12/05 00:52:58
-***************
-*** 1668,1674 ****
-  #ifdef HAVE_SPAWNV
-  static char posix_spawnv__doc__[] =
-  "spawnv(mode, path, args)\n\
-! Execute an executable path with arguments, replacing current process.\n\
-  \n\
-  	mode: mode of process creation\n\
-  	path: path of executable file\n\
---- 1668,1674 ----
-  #ifdef HAVE_SPAWNV
-  static char posix_spawnv__doc__[] =
-  "spawnv(mode, path, args)\n\
-! Execute the program 'path' in a new process.\n\
-  \n\
-  	mode: mode of process creation\n\
-  	path: path of executable file\n\
-***************
-*** 1717,1724 ****
-  
-  	if (mode == _OLD_P_OVERLAY)
-  		mode = _P_OVERLAY;
-  	spawnval = _spawnv(mode, path, argvlist);
-! 
-  	PyMem_DEL(argvlist);
-  
-  	if (spawnval == -1)
---- 1717,1727 ----
-  
-  	if (mode == _OLD_P_OVERLAY)
-  		mode = _P_OVERLAY;
-+ 	
-+ 	Py_BEGIN_ALLOW_THREADS
-  	spawnval = _spawnv(mode, path, argvlist);
-! 	Py_END_ALLOW_THREADS
-! 	
-  	PyMem_DEL(argvlist);
-  
-  	if (spawnval == -1)
-***************
-*** 1734,1740 ****
-  
-  static char posix_spawnve__doc__[] =
-  "spawnve(mode, path, args, env)\n\
-! Execute a path with arguments and environment, replacing current process.\n\
-  \n\
-  	mode: mode of process creation\n\
-  	path: path of executable file\n\
---- 1737,1743 ----
-  
-  static char posix_spawnve__doc__[] =
-  "spawnve(mode, path, args, env)\n\
-! Execute the program 'path' in a new process.\n\
-  \n\
-  	mode: mode of process creation\n\
-  	path: path of executable file\n\
-***************
-*** 1830,1836 ****
---- 1833,1843 ----
-  
-  	if (mode == _OLD_P_OVERLAY)
-  		mode = _P_OVERLAY;
-+ 
-+ 	Py_BEGIN_ALLOW_THREADS
-  	spawnval = _spawnve(mode, path, argvlist, envlist);
-+ 	Py_END_ALLOW_THREADS
-+ 
-  	if (spawnval == -1)
-  		(void) posix_error();
-  	else

src/test_strings.py

             'engine/SCons/Conftest.py',
             'engine/SCons/dblite.py',
             'MANIFEST',
-            'os_spawnv_fix.diff',
             'setup.cfg',
         ],
         # We run epydoc on the *.py files, which generates *.pyc files.
             'QMTest/TestCmdTests.py',
             'QMTest/TestCommon.py',
             'QMTest/TestCommonTests.py',
-            'src/os_spawnv_fix.diff',
             'src/MANIFEST.in',
             'src/setup.cfg',
             'src/engine/MANIFEST.in',

test/GetBuildFailures/parallel.py

     for bf in sorted(GetBuildFailures(), key=lambda t: t.filename):
         print "%%s failed:  %%s" %% (bf.node, bf.errstr)
 
-try:
-    import atexit
-except ImportError:
-    import sys
-    sys.exitfunc = print_build_failures
-else:
-    atexit.register(print_build_failures)
+import atexit
+atexit.register(print_build_failures)
 """ % locals())
 
 test.write('f3.in', "f3.in\n")

test/GetBuildFailures/serial.py

         if bf.command:
             print "BF:    %%s" %% " ".join(Flatten(bf.command))
 
-try:
-    import atexit
-except ImportError:
-    import sys
-    sys.exitfunc = print_build_failures
-else:
-    atexit.register(print_build_failures)
+import atexit
+atexit.register(print_build_failures)
 """ % locals())
 
 test.write('f03.in', "f03.in\n")

test/LINK/VersionedLib.py

+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import sys
+import TestSCons
+
+import SCons.Platform
+
+_exe = TestSCons._exe
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+import os
+env = Environment()
+objs = env.SharedObject('test.c')
+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.InstallVersionedLib("#/installtest",mylib)
+env.Default(instnode)
+""")
+
+test.write('test.c', """\
+int testlib(int n)
+{
+return n+1 ;
+}
+""")
+
+test.write('testapp.c', """\
+#include <stdio.h>
+int main(int argc, char **argv)
+{
+int itest ;
+
+itest = testlib(2) ;
+printf("results: testlib(2) = %d\n",itest) ;
+return 0 ;
+}
+""")
+
+platform = SCons.Platform.platform_default()
+
+
+test.run()
+
+if platform == 'posix':
+    # All (?) the files we expect will get created in the current directory
+    files = [
+    'libtest.so',
+    'libtest.so.2',
+    'libtest.so.2.5.4',
+    'test.os',
+    ]
+    # All (?) the files we expect will get created in the 'installtest' directory
+    instfiles = [
+    'libtest.so',
+    'libtest.so.2',
+    'libtest.so.2.5.4',
+    ]
+elif platform == 'darwin':
+    # All (?) the files we expect will get created in the current directory
+    files = [
+    'libtest.dylib',
+    'libtest.2.5.4.dylib',
+    'test.os',
+    ]
+    # All (?) the files we expect will get created in the 'installtest' directory
+    instfiles = [
+    'libtest.dylib',
+    'libtest.2.5.4.dylib',
+    ]
+else:
+    # All (?) the files we expect will get created in the current directory
+    files= [
+    'libtest.so',
+    'test.os']
+    # All (?) the files we expect will get created in the 'installtest' directory
+    instfiles = []
+
+for f in files:
+    test.must_exist([ f])
+for f in instfiles:
+    test.must_exist(['installtest', f])
+
+test.run(arguments = '-c')
+
+for f in files:
+    test.must_not_exist([ f])
+for f in instfiles:
+    test.must_not_exist(['installtest', f])
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:

test/SCONSFLAGS.py

 
 expect = r"""usage: scons [OPTION] [TARGET] ...
 
-SCons error: no such option: -Z
+SCons Error: no such option: -Z
 """
 
 test.run(arguments = "-H", status = 2,
-         stderr = TestSCons.re_escape(expect))
+         stderr = expect, match=TestSCons.match_exact)
 
 test.pass_test()
 

test/runtest/noqmtest.py

 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 """
-Test that the --noqmtest option invokes tests directly via Python, not
+Test that by default tests are invoked directly via Python, not
 using qmtest.
 """
 
     test_pass_py,
 ]
 
-test.run(arguments = '-k --noqmtest %s' % ' '.join(testlist),
+test.run(arguments = '-k %s' % ' '.join(testlist),
          status = 1,
          stdout = expect_stdout,
          stderr = expect_stderr)

test/runtest/xml/output.py

 
 test.write_passing_test(['test', 'pass.py'])
 
-test.run(arguments = '-o xml.out --xml test', status=1)
+test.run(arguments = '--xml xml.out test', status=1)
 
 expect = """\
   <results>