4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions:
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
40 (head, tail) = os.path.split(sys.argv[0])
47 if not sys.platform == 'win32':
49 if sys.argv[1] == 'bdist_wininst':
59 import distutils.command.install
60 import distutils.command.install_data
61 import distutils.command.install_lib
62 import distutils.command.install_scripts
63 import distutils.command.build_scripts
65 sys.stderr.write("""Could not import distutils.
67 Building or installing SCons from this package requires that the Python
68 distutils be installed. See the README or README.txt file from this
69 package for instructions on where to find distutils for installation on
70 your system, or on how to install SCons from a different package.
74 _install = distutils.command.install.install
75 _install_data = distutils.command.install_data.install_data
76 _install_lib = distutils.command.install_lib.install_lib
77 _install_scripts = distutils.command.install_scripts.install_scripts
78 _build_scripts = distutils.command.build_scripts.build_scripts
87 def set_explicitly(name, args):
89 Return if the installation directory was set explicitly by the
90 user on the command line. This is complicated by the fact that
91 "install --install-lib=/foo" gets turned into "install_lib
92 --install-dir=/foo" internally.
94 if args[0] == "install_" + name:
97 # The command is something else (usually "install")
98 s = "--install-%s=" % name
107 class install(_install):
108 user_options = _install.user_options + [
109 ('no-scons-script', None,
110 "don't install 'scons', only install 'scons-%s'" % Version),
111 ('no-version-script', None,
112 "don't install 'scons-%s', only install 'scons'" % Version),
113 ('install-bat', None,
114 "install 'scons.bat' script"),
115 ('no-install-bat', None,
116 "do not install 'scons.bat' script"),
117 ('install-man', None,
118 "install SCons man pages"),
119 ('no-install-man', None,
120 "do not install SCons man pages"),
121 ('standard-lib', None,
122 "install SCons library in standard Python location"),
123 ('standalone-lib', None,
124 "install SCons library in separate standalone directory"),
125 ('version-lib', None,
126 "install SCons library in version-numbered directory"),
128 boolean_options = _install.boolean_options + [
140 if hasattr(os, 'symlink'):
142 ('hardlink-scons', None,
143 "hard link 'scons' to the version-numbered script, don't make a separate 'scons' copy"),
145 boolean_options.append('hardlink-script')
147 if hasattr(os, 'symlink'):
149 ('symlink-scons', None,
150 "make 'scons' a symbolic link to the version-numbered script, don't make a separate 'scons' copy"),
152 boolean_options.append('symlink-script')
154 def initialize_options(self):
155 _install.initialize_options(self)
156 self.no_scons_script = 0
157 self.no_version_script = 0
159 self.no_install_bat = not is_win32
161 self.no_install_man = is_win32
162 self.standard_lib = 0
163 self.standalone_lib = 0
165 self.hardlink_scons = 0
166 self.symlink_scons = 0
167 # Don't warn about having to put the library directory in the
171 def finalize_options(self):
172 _install.finalize_options(self)
174 Options.install_bat = 1
176 Options.install_bat = not self.no_install_bat
178 Options.install_man = 1
180 Options.install_man = not self.no_install_man
181 Options.standard_lib = self.standard_lib
182 Options.standalone_lib = self.standalone_lib
183 Options.version_lib = self.version_lib
184 Options.install_scons_script = not self.no_scons_script
185 Options.install_version_script = not self.no_version_script
186 Options.hardlink_scons = self.hardlink_scons
187 Options.symlink_scons = self.symlink_scons
189 def get_scons_prefix(libdir, is_win32):
191 Return the right prefix for SCons library installation. Find
192 this by starting with the library installation directory
193 (.../site-packages, most likely) and crawling back up until we reach
194 a directory name beginning with "python" (or "Python").
196 drive, head = os.path.splitdrive(libdir)
200 head, tail = os.path.split(head)
201 if string.lower(tail)[:6] == "python":
202 # Found the Python library directory...
204 # ...on Win32 systems, "scons" goes in the directory:
205 # C:\PythonXX => C:\PythonXX\scons
206 return os.path.join(drive + head, tail)
208 # ...on other systems, "scons" goes above the directory:
209 # /usr/lib/pythonX.X => /usr/lib/scons
210 return os.path.join(drive + head)
213 class install_lib(_install_lib):
214 def finalize_options(self):
215 _install_lib.finalize_options(self)
216 args = self.distribution.script_args
217 if not set_explicitly("lib", args):
218 # They didn't explicitly specify the installation
219 # directory for libraries...
220 is_win32 = sys.platform == "win32" or args[0] == 'bdist_wininst'
221 prefix = get_scons_prefix(self.install_dir, is_win32)
222 if Options.standalone_lib:
223 # ...but they asked for a standalone directory.
224 self.install_dir = os.path.join(prefix, "scons")
225 elif Options.version_lib or not Options.standard_lib:
226 # ...they asked for a version-specific directory,
227 # or they get it by default.
228 self.install_dir = os.path.join(prefix, "scons-%s" % Version)
230 msg = "Installed SCons library modules into %s" % self.install_dir
231 Installed.append(msg)
233 class install_scripts(_install_scripts):
234 def finalize_options(self):
235 _install_scripts.finalize_options(self)
236 self.build_dir = os.path.join('build', 'scripts')
237 msg = "Installed SCons scripts into %s" % self.install_dir
238 Installed.append(msg)
240 def do_nothing(self, *args, **kw):
243 def hardlink_scons(self, src, dst, ver):
248 def symlink_scons(self, src, dst, ver):
251 os.symlink(os.path.split(ver)[1], dst)
253 def copy_scons(self, src, dst, *args):
256 self.copy_file(src, dst)
257 self.outfiles.append(dst)
259 def report(self, msg, args):
260 # Wrapper around self.announce, used by older distutils versions.
261 self.announce(msg % args)
264 # This "skip_build/build_scripts" block is cut-and-paste from
266 if not self.skip_build:
267 self.run_command('build_scripts')
269 # Custom SCons installation stuff.
270 if Options.hardlink_scons:
271 create_basename_script = self.hardlink_scons
272 elif Options.symlink_scons:
273 create_basename_script = self.symlink_scons
274 elif Options.install_scons_script:
275 create_basename_script = self.copy_scons
277 create_basename_script = self.do_nothing
279 if Options.install_version_script:
280 create_version_script = self.copy_scons
282 create_version_script = self.do_nothing
284 inputs = self.get_inputs()
285 bat_scripts = filter(lambda x: x[-4:] == '.bat', inputs)
286 non_bat_scripts = filter(lambda x: x[-4:] != '.bat', inputs)
289 self.mkpath(self.install_dir)
291 for src in non_bat_scripts:
292 base = os.path.basename(src)
293 scons = os.path.join(self.install_dir, base)
294 scons_ver = scons + '-' + Version
295 create_version_script(src, scons_ver)
296 create_basename_script(src, scons, scons_ver)
298 if Options.install_bat:
300 bat_install_dir = get_scons_prefix(self.install_dir, is_win32)
302 bat_install_dir = self.install_dir
303 for src in bat_scripts:
304 scons_bat = os.path.join(bat_install_dir, 'scons.bat')
305 scons_version_bat = os.path.join(bat_install_dir,
306 'scons-' + Version + '.bat')
307 self.copy_scons(src, scons_bat)
308 self.copy_scons(src, scons_version_bat)
310 # This section is cut-and-paste from distutils, modulo being
312 if os.name == 'posix':
313 try: report = distutils.log.info
314 except AttributeError: report = self.report
315 # Set the executable bits (owner, group, and world) on
316 # all the scripts we just installed.
317 for file in self.get_outputs():
319 report("changing mode of %s", file)
321 mode = ((os.stat(file)[stat.ST_MODE]) | 0555) & 07777
322 report("changing mode of %s", file)
325 class build_scripts(_build_scripts):
326 def finalize_options(self):
327 _build_scripts.finalize_options(self)
328 self.build_dir = os.path.join('build', 'scripts')
330 class install_data(_install_data):
331 def initialize_options(self):
332 _install_data.initialize_options(self)
333 def finalize_options(self):
334 _install_data.finalize_options(self)
335 if Options.install_man:
339 dir = os.path.join('man', 'man1')
340 self.data_files = [(dir, man_pages)]
341 man_dir = os.path.join(self.install_dir, dir)
342 msg = "Installed SCons man pages into %s" % man_dir
343 Installed.append(msg)
347 description = """Open Source next-generation build tool.
348 Improved, cross-platform substitute for the classic Make
349 utility. In short, SCons is an easier, more reliable
350 and faster way to build software."""
357 # We include scons.bat in the list of scripts, even on UNIX systems,
358 # because we provide an option to allow it be installed explicitly,
359 # for example if you're installing from UNIX on a share that's
360 # accessible to Windows and you want the scons.bat.
365 # scripts = scripts + [
366 # 'script/scons-post-install.py'
372 'description' : description,
373 'author' : 'Steven Knight',
374 'author_email' : 'knight@baldmt.com',
375 'url' : "http://www.scons.org/",
376 'packages' : ["SCons",
386 'package_dir' : {'' : 'engine'},
387 'data_files' : [('man/man1', man_pages)],
389 'cmdclass' : {'install' : install,
390 'install_lib' : install_lib,
391 'install_data' : install_data,
392 'install_scripts' : install_scripts,
393 'build_scripts' : build_scripts}
396 apply(distutils.core.setup, (), arguments)
399 print string.join(Installed, '\n')