Version installation of scripts.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 16 Mar 2005 17:15:19 +0000 (17:15 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 16 Mar 2005 17:15:19 +0000 (17:15 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@1254 fdb21ef1-2011-0410-befe-b5e4ea1792b1

README
SConstruct
src/README.txt
src/RELEASE.txt
src/setup.py
src/test_setup.py

diff --git a/README b/README
index 358cdc8da8d58aca9eece951bd92d18534a957ea..f34c9c297b789e1c6b0e71b7a3c69ea4e63640db 100644 (file)
--- a/README
+++ b/README
@@ -125,61 +125,75 @@ And on Windows:
         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);
-
-    --  on UNIX or Linux systems, the troff-formatted man pages in an
-        appropriate directory (/usr/share/man/man1 or /usr/man/man1,
+    --  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.
+
+    --  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:
-
-        # cd build/scons
-        # python setup.py install --version-lib
+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:
 
-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
 "Administrator") when running the setup.py script.  If you don't have
 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
index f928efb2af81dc340e2d5dd6653422e2bbd8c429..4ea2246b4b5d8a3e4fbb220cf6e33e4d200e0b72 100644 (file)
@@ -397,11 +397,16 @@ scons_script = {
                           ],
 
         '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,
@@ -525,6 +530,9 @@ for p in [ scons ]:
                 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():
@@ -631,7 +639,7 @@ for p in [ scons ]:
         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'),
         ])
 
@@ -704,7 +712,7 @@ for p in [ scons ]:
         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'),
         ])
 
@@ -823,7 +831,7 @@ for p in [ scons ]:
 
     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),
     ]
 
@@ -1011,7 +1019,7 @@ if change:
                     (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',
@@ -1067,7 +1075,7 @@ if change:
                     (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',
index 12645710923eaff4db54d64528cf1d065a8b610f..c821e9415c166633b381ed98060caa88b9f2cd82 100644 (file)
@@ -86,51 +86,70 @@ provided Python-standard setup script as follows:
 
         # 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);
-
-    --  on UNIX or Linux systems, the troff-formatted man pages in an
-        appropriate directory (/usr/share/man/man1 or /usr/man/man1,
+    --  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.
+
+    --  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
index 1c23c10110232aa3f612d89b6ee75481bd602d43..eabc4f60d925fb69322c64602be1307f22d1c87e 100644 (file)
@@ -64,6 +64,16 @@ RELEASE 0.97 - XXX
         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
index bec2b18382da9fc30d846ef33ed4b3e167251f36..2eed585a7d92a79a47a6092028aabb666925619e 100644 (file)
@@ -25,16 +25,30 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 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
@@ -57,14 +71,12 @@ _install_lib = distutils.command.install_lib.install_lib
 _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):
     """
@@ -88,38 +100,85 @@ 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):
     """
@@ -146,13 +205,6 @@ 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
@@ -161,43 +213,108 @@ class install_lib(_install_lib):
             # 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):
@@ -207,19 +324,23 @@ class build_scripts(_build_scripts):
 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",
@@ -230,7 +351,10 @@ arguments = {
                           "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,
@@ -238,26 +362,7 @@ arguments = {
                           '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')
index 73b6588d303d9e33b3dc28dbbe551312c62c261b..7d220e2a0c1fff4ce95406b43e9bd6a61d82769d 100644 (file)
@@ -37,6 +37,9 @@ import shutil
 import string
 import sys
 
+try: WindowsError
+except NameError: WindowsError = OSError
+
 #try:
 #    version = os.environ['SCONS_VERSION']
 #except KeyError:
@@ -51,12 +54,34 @@ python = TestSCons.python
 
 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',
     ]
@@ -64,18 +89,33 @@ class MyTestSCons(TestSCons.TestSCons):
     def __init__(self):
         TestSCons.TestSCons.__init__(self)
         self.root = self.workpath('root')
-        self.prefix = self.root + sys.prefix
-
-        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)
-
-        self.bin_dir = os.path.join(self.prefix, 'bin')
-
-        self.man_dir = os.path.join(self.prefix, 'man', 'man1')
+        self.prefix = self.root + os.path.splitdrive(sys.prefix)[1]
+
+        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.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
@@ -83,24 +123,50 @@ class MyTestSCons(TestSCons.TestSCons):
         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 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 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 remove(self, dir):
+        try: shutil.rmtree(dir)
+        except (OSError, WindowsError): pass
+
+    def stdout_lines(self):
+        return string.split(self.stdout(), '\n')
+
+
+    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']
@@ -112,53 +178,146 @@ test = MyTestSCons()
 test.subdir(test.root)
 
 tar_gz = os.path.join(cwd, 'build', 'dist', '%s.tar.gz' % scons_version)
-
-if not os.path.isfile(tar_gz):
-    print "Did not find an SCons package `%s'." % tar_gz
+zip = os.path.join(cwd, 'build', 'dist', '%s.zip' % scons_version)
+
+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.