Commits

Anonymous committed 763aa89

Version installation of scripts.

  • Participants
  • Parent commits 9c0c876

Comments (0)

Files changed (6)

         C:\scons\>cd build\scons
         C:\scons\build\scons>python setup.py install
 
-If this is the first time you are installing SCons on your system,
-the above command will install:
+By default, the above commands will do the following:
 
-    --  the scons script in the default system script directory (/usr/bin
-        or C:\Python*\Scripts, for example);
+    --  Install the version-numbered "scons-0.96" and "sconsign-0.96"
+        scripts in the default system script directory (/usr/bin or
+        C:\Python*\Scripts, for example).  This can be disabled by
+        specifying the "--no-version-script" option on the command
+        line.
 
-    --  the build engine in an appropriate stand-alone SCons library
-        directory (/usr/lib/scons or C:\Python*\scons, for example);
+    --  Install scripts named "scons" and "sconsign" scripts in the
+        default system script directory (/usr/bin or C:\Python*\Scripts,
+        for example).  This can be disabled by specifying the
+        "--no-scons-script" option on the command line, which is useful
+        if you want to install and experiment with a new version before
+        making it the default on your system.  On UNIX or Linux systems,
+        you can have the "scons" and "sconsign" scripts be hard links or
+        symbolic links to the "scons-0.96" and "sconsign-0.96" scripts
+        by specifying the "--hardlink-scons" or "--symlink-scons"
+        options on the command line.
 
-    --  on UNIX or Linux systems, the troff-formatted man pages in an
-        appropriate directory (/usr/share/man/man1 or /usr/man/man1,
+    --  Install "scons-0.96.bat" and "scons.bat" wrapper scripts in the
+        Python prefix directory on Windows (C:\Python*, for example).
+        This can be disabled by specifying the "--no-install-bat" option
+        on the command line.  On UNIX or Linux systems, the
+        "--install-bat" option may be specified to have "scons-0.96.bat"
+        and "scons.bat" files installed in the default system script
+        directory, which is useful if you want to install SCons in a
+        shared file system directory that can be used to execute SCons
+        from both UNIX/Linux and Windows systems.
+
+    --  Install the SCons build engine (a Python module) in an
+        appropriate version-numbered SCons library directory
+        (/usr/lib/scons-0.96 or C:\Python*\scons-0.96, for example).
+        See below for more options related to installing the build
+        engine library.
+
+    --  Install the troff-format man pages in an appropriate directory
+        on UNIX or Linux systems (/usr/share/man/man1 or /usr/man/man1,
         for example).  This can be disabled by specifying the
-        "--no-install-doc" option on the command line.
+        "--no-install-man" option on the command line.  The man pages
+        can be installed on Windows systems by specifying the
+        "--install-man" option on the command line.
 
-Note that, by default, SCons does not install its library in the
-standard Python library directories.  If you want to be able to use the
-SCons library modules (the build engine) in other Python scripts, you
-can run the setup script as follows:
+Note that, by default, SCons does not install its build engine library
+in the standard Python library directories.  If you want to be able to
+use the SCons library modules (the build engine) in other Python
+scripts, specify the "--standard-lib" option on the command line, as
+follows:
 
-        # cd build/scons
         # python setup.py install --standard-lib
 
-This will install the build engine in the standard Python
-library directory (/usr/lib/python*/site-packages or
+This will install the build engine in the standard Python library
+directory (/usr/lib/python*/site-packages or
 C:\Python*\Lib\site-packages).
 
-Alternatively, you may want to install multiple versions of SCons
-side-by-side, which you can do as follows:
+Alternatively, you can have SCons install its build engine library in a
+hard-coded standalone library directory, instead of the default
+version-numbered directory, by specifying the "--standalone-lib" option
+on the command line, as follows:
 
-        # cd build/scons
-        # python setup.py install --version-lib
+        # python setup.py install --standalone-lib
 
-This will install the build engine in a version-specific library
-directory (/usr/lib/scons-__VERSION__ or C:\Python*\scons-__VERSION__).
-
-If this is not the first time you are installing SCons on your system,
-the setup script will, by default, search for where you have previously
-installed the SCons library, and install this version's library the
-same way--that is, if you previously installed the SCons library in
-the standard Python library, the setup script will install this one
-in the same location.  You may, of course, specify one of the --*-lib
-options described above to select a specific library location, or use
-the following option to explicitly select installation into the default
-standalone library directory (/usr/lib/scons or C:\Python*\scons):
-
-        # cd build/scons
-        # python setup.py install --standalone-lib
+This is usually not recommended, however.
 
 Note that, to install SCons in any of the above system directories,
 you should have system installation privileges (that is, "root" or
 system installation privileges, you can use the --prefix option to
 specify an alternate installation location, such as your home directory:
 
-        $ cd build/scons
         $ python setup.py install --prefix=$HOME
 
 This will install SCons in the appropriate locations relative to
                           ],
 
         'filemap'       : {
-                            'LICENSE.txt' : '../LICENSE.txt',
-                            'scons'       : 'scons.py',
-                            'sconsign'    : 'sconsign.py',
+                            'LICENSE.txt'       : '../LICENSE.txt',
+                            'scons'             : 'scons.py',
+                            'sconsign'          : 'sconsign.py',
                            },
 
+        'extra_rpm_files' : [
+                            'scons-' + version,
+                            'sconsign-' + version,
+                          ],
+
         'explicit_deps' : {
                             'scons'       : Version_values,
                             'sconsign'    : Version_values,
                 rpm_files.append(r)
                 if f[-3:] == ".py":
                     rpm_files.append(r + 'c')
+            for f in sp.get('extra_rpm_files', []):
+                r = os.path.join(sp['rpm_dir'], f)
+                rpm_files.append(r)
             files = map(lambda x, i=isubdir: os.path.join(i, x), files)
             dst_files.extend(files)
             for k, f in sp['filemap'].items():
         env.Command(dfiles, unpack_tar_gz_files, [
             Delete(os.path.join(unpack_tar_gz_dir, pkg_version, 'build')),
             Delete("$TEST_TAR_GZ_DIR"),
-            '$PYTHON "%s" install "--prefix=$TEST_TAR_GZ_DIR"' % \
+            '$PYTHON "%s" install "--prefix=$TEST_TAR_GZ_DIR" --standalone-lib' % \
                 os.path.join(unpack_tar_gz_dir, pkg_version, 'setup.py'),
         ])
 
         env.Command(dfiles, unpack_zip_files, [
             Delete(os.path.join(unpack_zip_dir, pkg_version, 'build')),
             Delete("$TEST_ZIP_DIR"),
-            '$PYTHON "%s" install "--prefix=$TEST_ZIP_DIR"' % \
+            '$PYTHON "%s" install "--prefix=$TEST_ZIP_DIR" --standalone-lib' % \
                 os.path.join(unpack_zip_dir, pkg_version, 'setup.py'),
         ])
 
 
     commands = [
         Delete(local),
-        '$PYTHON $SETUP_PY install "--install-script=%s" "--install-lib=%s" --no-install-doc --no-compile' % \
+        '$PYTHON $SETUP_PY install "--install-script=%s" "--install-lib=%s" --no-install-man --no-compile --standalone-lib --no-version-script' % \
                                                 (cwd_local, cwd_local_slv),
     ]
 
                     (os.path.join(unpack_tar_gz_dir, psv),
                      os.path.join('src', 'script', 'scons.py'),
                      os.path.join('build', 'scons')),
-                '$PYTHON "%s" install "--prefix=$TEST_SRC_TAR_GZ_DIR"' % \
+                '$PYTHON "%s" install "--prefix=$TEST_SRC_TAR_GZ_DIR" --standalone-lib' % \
                     os.path.join(unpack_tar_gz_dir,
                                  psv,
                                  'build',
                     (os.path.join(unpack_zip_dir, psv),
                      os.path.join('src', 'script', 'scons.py'),
                      os.path.join('build', 'scons')),
-                '$PYTHON "%s" install "--prefix=$TEST_SRC_ZIP_DIR"' % \
+                '$PYTHON "%s" install "--prefix=$TEST_SRC_ZIP_DIR" --standalone-lib' % \
                     os.path.join(unpack_zip_dir,
                                  psv,
                                  'build',

File src/README.txt

 
         # python setup.py install
 
-If this is the first time you are installing SCons on your system,
-the above command will install:
+By default, the above command will do the following:
 
-    --  the scons script in the default system script directory (/usr/bin
-        or C:\Python*\Scripts, for example);
+    --  Install the version-numbered "scons-__VERSION__" and
+    "sconsign-__VERSION__"
+        scripts in the default system script directory (/usr/bin or
+        C:\Python*\Scripts, for example).  This can be disabled by
+        specifying the "--no-version-script" option on the command
+        line.
 
-    --  the build engine in an appropriate stand-alone SCons library
-        directory (/usr/lib/scons or C:\Python*\scons, for example);
+    --  Install scripts named "scons" and "sconsign" scripts in the
+        default system script directory (/usr/bin or C:\Python*\Scripts,
+        for example).  This can be disabled by specifying the
+        "--no-scons-script" option on the command line, which is useful
+        if you want to install and experiment with a new version before
+        making it the default on your system.  On UNIX or Linux systems,
+        you can have the "scons" and "sconsign" scripts be hard links or
+        symbolic links to the "scons-__VERSION__" and "sconsign-__VERSION__" scripts
+        by specifying the "--hardlink-scons" or "--symlink-scons"
+        options on the command line.
 
-    --  on UNIX or Linux systems, the troff-formatted man pages in an
-        appropriate directory (/usr/share/man/man1 or /usr/man/man1,
+    --  Install "scons-__VERSION__.bat" and "scons.bat" wrapper scripts in the
+        Python prefix directory on Windows (C:\Python*, for example).
+        This can be disabled by specifying the "--no-install-bat" option
+        on the command line.  On UNIX or Linux systems, the
+        "--install-bat" option may be specified to have "scons-__VERSION__.bat"
+        and "scons.bat" files installed in the default system script
+        directory, which is useful if you want to install SCons in a
+        shared file system directory that can be used to execute SCons
+        from both UNIX/Linux and Windows systems.
+
+    --  Install the SCons build engine (a Python module) in an
+        appropriate version-numbered SCons library directory
+        (/usr/lib/scons-__VERSION__ or C:\Python*\scons-__VERSION__, for example).
+        See below for more options related to installing the build
+        engine library.
+
+    --  Install the troff-format man pages in an appropriate directory
+        on UNIX or Linux systems (/usr/share/man/man1 or /usr/man/man1,
         for example).  This can be disabled by specifying the
-        "--no-install-doc" option on the command line.
+        "--no-install-man" option on the command line.  The man pages
+        can be installed on Windows systems by specifying the
+        "--install-man" option on the command line.
 
-Note that, by default, SCons does not install its library in the
-standard Python library directories.  If you want to be able to use the
-SCons library modules (the build engine) in other Python scripts, you
-can run the setup script as follows:
+Note that, by default, SCons does not install its build engine library
+in the standard Python library directories.  If you want to be able to
+use the SCons library modules (the build engine) in other Python
+scripts, specify the "--standard-lib" option on the command line, as
+follows:
 
         # python setup.py install --standard-lib
 
-This will install the build engine in the standard Python
-library directory (/usr/lib/python*/site-packages or
+This will install the build engine in the standard Python library
+directory (/usr/lib/python*/site-packages or
 C:\Python*\Lib\site-packages).
 
-Alternatively, you may want to install multiple versions of SCons
-side-by-side, which you can do as follows:
-
-        # python setup.py install --version-lib
-
-This will install the build engine in a version-specific library
-directory (/usr/lib/scons-__VERSION__ or C:\Python*\scons-__VERSION__).
-
-If this is not the first time you are installing SCons on your system,
-the setup script will, by default, search for where you have previously
-installed the SCons library, and install this version's library the
-same way--that is, if you previously installed the SCons library in
-the standard Python library, the setup script will install this one
-in the same location.  You may, of course, specify one of the --*-lib
-options described above to select a specific library location, or use
-the following option to explicitly select installation into the default
-standalone library directory (/usr/lib/scons or C:\Python*\scons):
+Alternatively, you can have SCons install its build engine library in a
+hard-coded standalone library directory, instead of the default
+version-numbered directory, by specifying the "--standalone-lib" option
+on the command line, as follows:
 
         # python setup.py install --standalone-lib
 
+This is usually not recommended, however.
+
 Note that, to install SCons in any of the above system directories,
 you should have system installation privileges (that is, "root" or
 "Administrator") when running the setup.py script.  If you don't have

File src/RELEASE.txt

         different file.  This may cause configuration tests to be re-run
         the first time after you install 0.97.
 
+    --  setup.py INSTALLS VERSION-NUMBERED SCRIPTS AND DIRS BY DEFAULT
+
+        The setup.py script has been changed to always install SCons in
+        a version-numbered directory (e.g. /usr/local/lib/scons-0.97
+        or D:\Python23\scons-0.97) and with a version-numbered script
+        name (scons-0.97) in addition to the usual installation of an
+        "scons" script name.  A number of new setup.py options allow
+        control over what does or does not get installed, and where.
+        See the README.txt or README files for additional information.
+
     --  setup.py NOW INSTALLS MAN PAGES ON UNIX AND Linux SYSTEMS
 
         The SCons setup.py script now installs the "scons.1" and

File src/setup.py

 
 import os
 import os.path
+import stat
 import string
 import sys
 
+Version = "0.96"
+
 (head, tail) = os.path.split(sys.argv[0])
 
 if head:
     os.chdir(head)
     sys.argv[0] = tail
 
+is_win32 = 0
+if not sys.platform == 'win32':
+    try:
+        if sys.argv[1] == 'bdist_wininst':
+            is_win32 = 1
+    except IndexError:
+        pass
+else:
+    is_win32 = 1
+
 try:
+    import distutils
     import distutils.core
     import distutils.command.install
     import distutils.command.install_data
 _install_scripts = distutils.command.install_scripts.install_scripts
 _build_scripts = distutils.command.build_scripts.build_scripts
 
-install_doc = 1
-standard_lib = 0
-standalone_lib = 0
-version_lib = 0
+class _options:
+    pass
 
-installed_lib_dir = None
-installed_man_pages_dir = None
-installed_scripts_dir = None
+Options = _options()
+
+Installed = []
 
 def set_explicitly(name, args):
     """
 
 class install(_install):
     user_options = _install.user_options + [
-                    ('no-install-doc', None,
+                    ('no-scons-script', None,
+                     "don't install 'scons', only install 'scons-%s'" % Version),
+                    ('no-version-script', None,
+                     "don't install 'scons-%s', only install 'scons'" % Version),
+                    ('install-bat', None,
+                     "install 'scons.bat' script"),
+                    ('no-install-bat', None,
+                     "do not install 'scons.bat' script"),
+                    ('install-man', None,
+                     "install SCons man pages"),
+                    ('no-install-man', None,
                      "do not install SCons man pages"),
                     ('standard-lib', None,
                      "install SCons library in standard Python location"),
                     ('standalone-lib', None,
                      "install SCons library in separate standalone directory"),
                     ('version-lib', None,
-                     "install SCons library in version-specific directory")
+                     "install SCons library in version-numbered directory"),
                    ]
     boolean_options = _install.boolean_options + [
-                       'no-install-doc',
+                       'no-scons-script',
+                       'no-version-script',
+                       'install-bat',
+                       'no-install-bat',
+                       'install-man',
+                       'no-install-man',
                        'standard-lib',
                        'standalone-lib',
                        'version-lib'
                       ]
 
+    if hasattr(os, 'symlink'):
+        user_options.append(
+                    ('hardlink-scons', None,
+                     "hard link 'scons' to the version-numbered script, don't make a separate 'scons' copy"),
+                     )
+        boolean_options.append('hardlink-script')
+
+    if hasattr(os, 'symlink'):
+        user_options.append(
+                    ('symlink-scons', None,
+                     "make 'scons' a symbolic link to the version-numbered script, don't make a separate 'scons' copy"),
+                     )
+        boolean_options.append('symlink-script')
+
     def initialize_options(self):
         _install.initialize_options(self)
-        self.no_install_doc = 0
+        self.no_scons_script = 0
+        self.no_version_script = 0
+        self.install_bat = 0
+        self.no_install_bat = not is_win32
+        self.install_man = 0
+        self.no_install_man = is_win32
         self.standard_lib = 0
         self.standalone_lib = 0
         self.version_lib = 0
+        self.hardlink_scons = 0
+        self.symlink_scons = 0
+        # Don't warn about having to put the library directory in the
+        # search path.
         self.warn_dir = 0
 
     def finalize_options(self):
         _install.finalize_options(self)
-        global install_doc, standard_lib, standalone_lib, version_lib
-        if self.no_install_doc:
-            install_doc = 0
-        standard_lib = self.standard_lib
-        standalone_lib = self.standalone_lib
-        version_lib = self.version_lib
+        if self.install_bat:
+            Options.install_bat = 1
+        else:
+            Options.install_bat = not self.no_install_bat
+        if self.install_man:
+            Options.install_man = 1
+        else:
+            Options.install_man = not self.no_install_man
+        Options.standard_lib = self.standard_lib
+        Options.standalone_lib = self.standalone_lib
+        Options.version_lib = self.version_lib
+        Options.install_scons_script = not self.no_scons_script
+        Options.install_version_script = not self.no_version_script
+        Options.hardlink_scons = self.hardlink_scons
+        Options.symlink_scons = self.symlink_scons
 
 def get_scons_prefix(libdir, is_win32):
     """
     return libdir
 
 class install_lib(_install_lib):
-    def initialize_options(self):
-        _install_lib.initialize_options(self)
-        global standard_lib, standalone_lib, version_lib
-        self.standard_lib = standard_lib
-        self.standalone_lib = standalone_lib
-        self.version_lib = version_lib
-
     def finalize_options(self):
         _install_lib.finalize_options(self)
         args = self.distribution.script_args
             # directory for libraries...
             is_win32 = sys.platform == "win32" or args[0] == 'bdist_wininst'
             prefix = get_scons_prefix(self.install_dir, is_win32)
-            standard_dir = os.path.join(self.install_dir, "SCons")
-            version_dir = os.path.join(prefix, "scons-__VERSION__")
-            standalone_dir = os.path.join(prefix, "scons")
-            if self.version_lib:
-                # ...but they asked for a version-specific directory.
-                self.install_dir = version_dir
-            elif self.standalone_lib:
+            if Options.standalone_lib:
                 # ...but they asked for a standalone directory.
-                self.install_dir = standalone_dir
-            elif not self.standard_lib:
-                # ...and they didn't explicitly ask for the standard
-                # directory, so guess based on what's out there.
-                try:
-                    l = os.listdir(prefix)
-                except OSError:
-                    e = None
-                else:
-                    e = filter(lambda x: x[:6] == "scons-", l)
-                if e:
-                    # We found a path name (e.g.) /usr/lib/scons-XXX,
-                    # so pick the version-specific directory.
-                    self.install_dir = version_dir
-                elif os.path.exists(standalone_dir) or \
-                     not os.path.exists(standard_dir):
-                    # There's already a standalone directory, or
-                    # there's no SCons library in the standard
-                    # directory, so go with the standalone.
-                    self.install_dir = standalone_dir
-        global installed_lib_dir
-        installed_lib_dir = self.install_dir
+                self.install_dir = os.path.join(prefix, "scons")
+            elif Options.version_lib or not Options.standard_lib:
+                # ...they asked for a version-specific directory,
+                # or they get it by default.
+                self.install_dir = os.path.join(prefix, "scons-%s" % Version)
+
+        msg = "Installed SCons library modules into %s" % self.install_dir
+        Installed.append(msg)
 
 class install_scripts(_install_scripts):
     def finalize_options(self):
         _install_scripts.finalize_options(self)
         self.build_dir = os.path.join('build', 'scripts')
-        global installed_scripts_dir
-        installed_scripts_dir = self.install_dir
+        msg = "Installed SCons scripts into %s" % self.install_dir
+        Installed.append(msg)
+
+    def do_nothing(self, *args, **kw):
+        pass
+
+    def hardlink_scons(self, src, dst, ver):
+        try: os.unlink(dst)
+        except OSError: pass
+        os.link(ver, dst)
+
+    def symlink_scons(self, src, dst, ver):
+        try: os.unlink(dst)
+        except OSError: pass
+        os.symlink(os.path.split(ver)[1], dst)
+
+    def copy_scons(self, src, dst, *args):
+        try: os.unlink(dst)
+        except OSError: pass
+        self.copy_file(src, dst)
+        self.outfiles.append(dst)
+
+    def report(self, msg, args):
+        # Wrapper around self.announce, used by older distutils versions.
+        self.announce(msg % args)
+
+    def run(self):
+        # This "skip_build/build_scripts" block is cut-and-paste from
+        # distutils.
+        if not self.skip_build:
+            self.run_command('build_scripts')
+
+        # Custom SCons installation stuff.
+        if Options.hardlink_scons:
+            create_basename_script = self.hardlink_scons
+        elif Options.symlink_scons:
+            create_basename_script = self.symlink_scons
+        elif Options.install_scons_script:
+            create_basename_script = self.copy_scons
+        else:
+            create_basename_script = self.do_nothing
+
+        if Options.install_version_script:
+            create_version_script = self.copy_scons
+        else:
+            create_version_script = self.do_nothing
+
+        inputs = self.get_inputs()
+        bat_scripts = filter(lambda x: x[-4:] == '.bat', inputs)
+        non_bat_scripts = filter(lambda x: x[-4:] != '.bat', inputs)
+
+        self.outfiles = []
+        self.mkpath(self.install_dir)
+
+        for src in non_bat_scripts:
+            base = os.path.basename(src)
+            scons = os.path.join(self.install_dir, base)
+            scons_ver = scons + '-' + Version
+            create_version_script(src, scons_ver)
+            create_basename_script(src, scons, scons_ver)
+
+        if Options.install_bat:
+            if is_win32:
+                bat_install_dir = get_scons_prefix(self.install_dir, is_win32)
+            else:
+                bat_install_dir = self.install_dir
+            for src in bat_scripts:
+                scons_bat = os.path.join(bat_install_dir, 'scons.bat')
+                scons_version_bat = os.path.join(bat_install_dir,
+                                                 'scons-' + Version + '.bat')
+                self.copy_scons(src, scons_bat)
+                self.copy_scons(src, scons_version_bat)
+
+        # This section is cut-and-paste from distutils, modulo being
+        # able 
+        if os.name == 'posix':
+            try: report = distutils.log.info
+            except AttributeError: report = self.report
+            # Set the executable bits (owner, group, and world) on
+            # all the scripts we just installed.
+            for file in self.get_outputs():
+                if self.dry_run:
+                    report("changing mode of %s", file)
+                else:
+                    mode = ((os.stat(file)[stat.ST_MODE]) | 0555) & 07777
+                    report("changing mode of %s", file)
+                    os.chmod(file, mode)
 
 class build_scripts(_build_scripts):
     def finalize_options(self):
 class install_data(_install_data):
     def initialize_options(self):
         _install_data.initialize_options(self)
-        global install_doc
-        self.install_doc = install_doc
     def finalize_options(self):
         _install_data.finalize_options(self)
-        if self.install_doc:
-            global installed_man_pages_dir
-            installed_man_pages_dir = self.install_dir + '/man/man1'
+        if Options.install_man:
+            if is_win32:
+                dir = 'Doc'
+            else:
+                dir = os.path.join('man', 'man1')
+            self.data_files = [(dir, ["scons.1", "sconsign.1"])]
+            man_dir = os.path.join(self.install_dir, dir)
+            msg = "Installed SCons man pages into %s" % man_dir
+            Installed.append(msg)
         else:
             self.data_files = []
 
 arguments = {
     'name'             : "scons",
-    'version'          : "__VERSION__",
+    'version'          : Version,
     'packages'         : ["SCons",
                           "SCons.Node",
                           "SCons.Optik",
                           "SCons.Sig",
                           "SCons.Tool"],
     'package_dir'      : {'' : 'engine'},
-    'scripts'          : ['script/scons', 'script/sconsign'],
+    'data_files'       : [('man/man1', ["scons.1", "sconsign.1"])],
+    'scripts'          : ['script/scons',
+                          'script/sconsign',
+                          'script/scons.bat'],
     'cmdclass'         : {'install'         : install,
                           'install_lib'     : install_lib,
                           'install_data'    : install_data,
                           'build_scripts'   : build_scripts}
 }
 
-is_win32 = 0
-if not sys.platform == 'win32':
-    try:
-        if sys.argv[1] == 'bdist_wininst':
-            is_win32 = 1
-    except IndexError:
-        pass
-else:
-    is_win32 = 1
-
-if is_win32:
-    arguments['data_files'] = [('.', ["script/scons.bat"])]
-else:
-    arguments['data_files'] = [('man/man1', ["scons.1", "sconsign.1"])]
-
 apply(distutils.core.setup, (), arguments)
 
-if installed_lib_dir:
-    print "Installed SCons library modules into %s" % installed_lib_dir
-if installed_man_pages_dir:
-    print "Installed SCons man pages into %s" % installed_man_pages_dir
-if installed_scripts_dir:
-    print "Installed SCons scripts into %s" % installed_scripts_dir
+if Installed:
+    print string.join(Installed, '\n')

File src/test_setup.py

 import string
 import sys
 
+try: WindowsError
+except NameError: WindowsError = OSError
+
 #try:
 #    version = os.environ['SCONS_VERSION']
 #except KeyError:
 
 class MyTestSCons(TestSCons.TestSCons):
 
-    scripts = [
+    _lib_modules = [
+        # A representative smattering of build engine modules.
+        '__init__.py',
+        'Action.py',
+        'Builder.py',
+        'Environment.py',
+        'Util.py',
+    ]
+
+    _base_scripts = [
         'scons',
         'sconsign',
     ]
 
-    man_pages = [
+    _version_scripts = [
+        'scons-%s' % version,
+        'sconsign-%s' % version,
+    ]
+
+    _bat_scripts = [
+        'scons.bat',
+    ]
+
+    _bat_version_scripts = [
+        'scons-%s.bat' % version,
+    ]
+
+    _man_pages = [
         'scons.1',
         'sconsign.1',
     ]
     def __init__(self):
         TestSCons.TestSCons.__init__(self)
         self.root = self.workpath('root')
-        self.prefix = self.root + sys.prefix
+        self.prefix = self.root + os.path.splitdrive(sys.prefix)[1]
 
-        self.lib_dir = os.path.join(self.prefix, 'lib')
-        self.standard_lib = os.path.join(self.lib_dir,
-                                         'python%s' % sys.version[:3],
-                                         'site-packages/')
-        self.standalone_lib = os.path.join(self.lib_dir, 'scons')
-        self.version_lib = os.path.join(self.lib_dir, scons_version)
+        if sys.platform == 'win32':
+            self.bin_dir = os.path.join(self.prefix, 'Scripts')
+            self.bat_dir = self.prefix
+            self.standalone_lib = os.path.join(self.prefix, 'scons')
+            self.standard_lib = os.path.join(self.prefix,
+                                             'Lib',
+                                             'site-packages',
+                                             '')
+            self.version_lib = os.path.join(self.prefix, scons_version)
+            self.man_dir = os.path.join(self.prefix, 'Doc')
+        else:
+            self.bin_dir = os.path.join(self.prefix, 'bin')
+            self.bat_dir = self.bin_dir
+            self.lib_dir = os.path.join(self.prefix, 'lib')
+            self.standalone_lib = os.path.join(self.lib_dir, 'scons')
+            self.standard_lib = os.path.join(self.lib_dir,
+                                             'python%s' % sys.version[:3],
+                                             'site-packages',
+                                             '')
+            self.version_lib = os.path.join(self.lib_dir, scons_version)
+            self.man_dir = os.path.join(self.prefix, 'man', 'man1')
 
-        self.bin_dir = os.path.join(self.prefix, 'bin')
-
-        self.man_dir = os.path.join(self.prefix, 'man', 'man1')
+	self.prepend_bin_dir = lambda p, d=self.bin_dir: os.path.join(d, p)
+	self.prepend_bat_dir = lambda p, d=self.bat_dir: os.path.join(d, p)
+	self.prepend_man_dir = lambda p, d=self.man_dir: os.path.join(d, p)
 
     def run(self, *args, **kw):
         kw['chdir'] = scons_version
         kw['stderr'] = None
         return apply(TestSCons.TestSCons.run, (self,)+args, kw)
 
-    def must_have_installed_lib(self, lib):
-        lines = string.split(self.stdout(), '\n')
-        line = 'Installed SCons library modules into %s' % lib
-        self.fail_test(not line in lines)
+    def remove(self, dir):
+        try: shutil.rmtree(dir)
+        except (OSError, WindowsError): pass
 
-    def must_have_installed_scripts(self):
-        lines = string.split(self.stdout(), '\n')
-        line = 'Installed SCons scripts into %s' % self.bin_dir
-        self.fail_test(not line in lines)
-        for script in self.scripts:
-            self.must_exist([self.bin_dir, script])
+    def stdout_lines(self):
+        return string.split(self.stdout(), '\n')
 
-    def must_have_installed_man_pages(self):
-        lines = string.split(self.stdout(), '\n')
-        line = 'Installed SCons man pages into %s' % self.man_dir
-        self.fail_test(not line in lines)
-        for mp in self.man_pages:
-            self.must_exist([self.man_dir, mp])
+
+    def lib_line(self, lib):
+        return 'Installed SCons library modules into %s' % lib
+
+    def lib_paths(self, lib_dir):
+        prepend_lib_dir = lambda p, d=lib_dir: os.path.join(d, 'SCons', p)
+        return map(prepend_lib_dir, self._lib_modules)
+
+    def scripts_line(self):
+        return 'Installed SCons scripts into %s' % self.bin_dir
+
+    def base_script_paths(self):
+        scripts = self._base_scripts
+        return map(self.prepend_bin_dir, scripts)
+
+    def version_script_paths(self):
+        scripts = self._version_scripts
+        return map(self.prepend_bin_dir, scripts)
+
+    def bat_script_paths(self):
+        scripts = self._bat_scripts + self._bat_version_scripts
+        return map(self.prepend_bat_dir, scripts)
+
+    def man_page_line(self):
+        return 'Installed SCons man pages into %s' % self.man_dir
+
+    def man_page_paths(self):
+	return map(self.prepend_man_dir, self._man_pages)
+
+
+    def must_have_installed(self, paths):
+        for p in paths:
+            self.must_exist(p)
+
+    def must_not_have_installed(self, paths):
+        for p in paths:
+            self.must_not_exist(p)
 
 try:
     cwd = os.environ['SCONS_CWD']
 test.subdir(test.root)
 
 tar_gz = os.path.join(cwd, 'build', 'dist', '%s.tar.gz' % scons_version)
+zip = os.path.join(cwd, 'build', 'dist', '%s.zip' % scons_version)
 
-if not os.path.isfile(tar_gz):
-    print "Did not find an SCons package `%s'." % tar_gz
+if os.path.isfile(zip):
+    try: import zipfile
+    except ImportError: pass
+    else:
+        zf = zipfile.ZipFile(zip, 'r')
+
+        for name in zf.namelist():
+            dir = os.path.dirname(name)
+            try: os.makedirs(dir)
+            except: pass
+            # if the file exists, then delete it before writing
+            # to it so that we don't end up trying to write to a symlink:
+            if os.path.isfile(name) or os.path.islink(name):
+                os.unlink(name)
+            if not os.path.isdir(name):
+                open(name, 'w').write(zf.read(name))
+
+if not os.path.isdir(scons_version) and os.path.isfile(tar_gz):
+    # Unpack the .tar.gz file.  This should create the scons_version/
+    # subdirectory from which we execute the setup.py script therein.
+    os.system("gunzip -c %s | tar xf -" % tar_gz)
+
+if not os.path.isdir(scons_version):
+    print "Found neither SCons package `%s' nor `%s'." % (tar_gz, zip)
     print "Cannot test package installation."
     test.no_result(1)
 
-# Unpack the .tar.gz file.  This should create the scons_version/
-# subdirectory from which we execute the setup.py script therein.
-os.system("gunzip -c %s | tar xf -" % tar_gz)
-
-# Verify that a virgin installation installs the standalone library,
-# the scripts and the man pages.
+# Verify that a virgin installation installs the version library,
+# the scripts and (on UNIX/Linux systems) the man pages.
 test.run(arguments = 'setup.py install --root=%s' % test.root)
-test.must_have_installed_lib(test.standalone_lib)
-test.must_have_installed_scripts()
-test.must_have_installed_man_pages()
+test.fail_test(not test.lib_line(test.version_lib) in test.stdout_lines())
+test.must_have_installed(test.lib_paths(test.version_lib))
 
 # Verify that --standard-lib installs into the Python standard library.
 test.run(arguments = 'setup.py install --root=%s --standard-lib' % test.root)
-test.must_have_installed_lib(test.standard_lib)
+test.fail_test(not test.lib_line(test.standard_lib) in test.stdout_lines())
+test.must_have_installed(test.lib_paths(test.standard_lib))
 
 # Verify that --standalone-lib installs the standalone library.
 test.run(arguments = 'setup.py install --root=%s --standalone-lib' % test.root)
-test.must_have_installed_lib(test.standalone_lib)
+test.fail_test(not test.lib_line(test.standalone_lib) in test.stdout_lines())
+test.must_have_installed(test.lib_paths(test.standalone_lib))
 
 # Verify that --version-lib installs into a version-specific library directory.
 test.run(arguments = 'setup.py install --root=%s --version-lib' % test.root)
-test.must_have_installed_lib(test.version_lib)
+test.fail_test(not test.lib_line(test.version_lib) in test.stdout_lines())
 
 # Now that all of the libraries are in place,
-# verify that a default installation finds the version-specific library first.
+# verify that a default installation still installs the version library.
 test.run(arguments = 'setup.py install --root=%s' % test.root)
-test.must_have_installed_lib(test.version_lib)
+test.fail_test(not test.lib_line(test.version_lib) in test.stdout_lines())
 
-shutil.rmtree(test.version_lib)
+test.remove(test.version_lib)
 
 # Now with only the standard and standalone libraries in place,
-# verify that a default installation finds the standalone library first.
+# verify that a default installation still installs the version library.
 test.run(arguments = 'setup.py install --root=%s' % test.root)
-test.must_have_installed_lib(test.standalone_lib)
+test.fail_test(not test.lib_line(test.version_lib) in test.stdout_lines())
 
-shutil.rmtree(test.standalone_lib)
+test.remove(test.version_lib)
+test.remove(test.standalone_lib)
 
 # Now with only the standard libraries in place,
-# verify that a default installation installs the standard library.
+# verify that a default installation still installs the version library.
 test.run(arguments = 'setup.py install --root=%s' % test.root)
-test.must_have_installed_lib(test.standard_lib)
+test.fail_test(not test.lib_line(test.version_lib) in test.stdout_lines())
+
+
+
+#
+test.run(arguments = 'setup.py install --root=%s' % test.root)
+test.fail_test(not test.scripts_line() in test.stdout_lines())
+if sys.platform == 'win32':
+    test.must_have_installed(test.base_script_paths())
+    test.must_have_installed(test.version_script_paths())
+    test.must_have_installed(test.bat_script_paths())
+else:
+    test.must_have_installed(test.base_script_paths())
+    test.must_have_installed(test.version_script_paths())
+    test.must_not_have_installed(test.bat_script_paths())
+
+test.remove(test.prefix)
+
+test.run(arguments = 'setup.py install --root=%s --no-install-bat' % test.root)
+test.fail_test(not test.scripts_line() in test.stdout_lines())
+test.must_have_installed(test.base_script_paths())
+test.must_have_installed(test.version_script_paths())
+test.must_not_have_installed(test.bat_script_paths())
+
+test.remove(test.prefix)
+
+test.run(arguments = 'setup.py install --root=%s --install-bat' % test.root)
+test.fail_test(not test.scripts_line() in test.stdout_lines())
+test.must_have_installed(test.base_script_paths())
+test.must_have_installed(test.version_script_paths())
+test.must_have_installed(test.bat_script_paths())
+
+test.remove(test.prefix)
+
+test.run(arguments = 'setup.py install --root=%s --no-scons-script' % test.root)
+test.fail_test(not test.scripts_line() in test.stdout_lines())
+test.must_not_have_installed(test.base_script_paths())
+test.must_have_installed(test.version_script_paths())
+# Doesn't matter whether we installed the .bat scripts or not.
+
+test.remove(test.prefix)
+
+test.run(arguments = 'setup.py install --root=%s --no-version-script' % test.root)
+test.fail_test(not test.scripts_line() in test.stdout_lines())
+test.must_have_installed(test.base_script_paths())
+test.must_not_have_installed(test.version_script_paths())
+# Doesn't matter whether we installed the .bat scripts or not.
+
+
+
+test.remove(test.man_dir)
+
+test.run(arguments = 'setup.py install --root=%s' % test.root)
+if sys.platform == 'win32':
+    test.fail_test(test.man_page_line() in test.stdout_lines())
+    test.must_not_have_installed(test.man_page_paths())
+else:
+    test.fail_test(not test.man_page_line() in test.stdout_lines())
+    test.must_have_installed(test.man_page_paths())
+
+test.remove(test.man_dir)
+
+test.run(arguments = 'setup.py install --root=%s --no-install-man' % test.root)
+test.fail_test(test.man_page_line() in test.stdout_lines())
+test.must_not_have_installed(test.man_page_paths())
+
+test.remove(test.man_dir)
+
+test.run(arguments = 'setup.py install --root=%s --install-man' % test.root)
+test.fail_test(not test.man_page_line() in test.stdout_lines())
+test.must_have_installed(test.man_page_paths())
+
+
 
 # Verify that we don't warn about the directory in which we've
 # installed the modules when using a non-standard prefix.