Updated for 2.1a3
[python/dscho.git] / Lib / distutils / command / install_lib.py
blob6c4c7fe9935a7957412e452ed6c60071fe6942af
1 # created 1999/03/13, Greg Ward
3 __revision__ = "$Id$"
5 import sys, os, string
6 from types import IntType
7 from distutils.core import Command
8 from distutils.errors import DistutilsOptionError
9 from distutils.dir_util import copy_tree
11 class install_lib (Command):
13 description = "install all Python modules (extensions and pure Python)"
15 # The byte-compilation options are a tad confusing. Here are the
16 # possible scenarios:
17 # 1) no compilation at all (--no-compile --no-optimize)
18 # 2) compile .pyc only (--compile --no-optimize; default)
19 # 3) compile .pyc and "level 1" .pyo (--compile --optimize)
20 # 4) compile "level 1" .pyo only (--no-compile --optimize)
21 # 5) compile .pyc and "level 2" .pyo (--compile --optimize-more)
22 # 6) compile "level 2" .pyo only (--no-compile --optimize-more)
24 # The UI for this is two option, 'compile' and 'optimize'.
25 # 'compile' is strictly boolean, and only decides whether to
26 # generate .pyc files. 'optimize' is three-way (0, 1, or 2), and
27 # decides both whether to generate .pyo files and what level of
28 # optimization to use.
30 user_options = [
31 ('install-dir=', 'd', "directory to install to"),
32 ('build-dir=','b', "build directory (where to install from)"),
33 ('force', 'f', "force installation (overwrite existing files)"),
34 ('compile', 'c', "compile .py to .pyc [default]"),
35 ('no-compile', None, "don't compile .py files"),
36 ('optimize=', 'O',
37 "also compile with optimization: -O1 for \"python -O\", "
38 "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
39 ('skip-build', None, "skip the build steps"),
42 boolean_options = ['force', 'compile', 'skip-build']
43 negative_opt = {'no-compile' : 'compile'}
46 def initialize_options (self):
47 # let the 'install' command dictate our installation directory
48 self.install_dir = None
49 self.build_dir = None
50 self.force = 0
51 self.compile = None
52 self.optimize = None
53 self.skip_build = None
55 def finalize_options (self):
57 # Get all the information we need to install pure Python modules
58 # from the umbrella 'install' command -- build (source) directory,
59 # install (target) directory, and whether to compile .py files.
60 self.set_undefined_options('install',
61 ('build_lib', 'build_dir'),
62 ('install_lib', 'install_dir'),
63 ('force', 'force'),
64 ('compile', 'compile'),
65 ('optimize', 'optimize'),
66 ('skip_build', 'skip_build'),
69 if self.compile is None:
70 self.compile = 1
71 if self.optimize is None:
72 self.optimize = 0
74 if type(self.optimize) is not IntType:
75 try:
76 self.optimize = int(self.optimize)
77 assert 0 <= self.optimize <= 2
78 except (ValueError, AssertionError):
79 raise DistutilsOptionError, "optimize must be 0, 1, or 2"
81 def run (self):
83 # Make sure we have built everything we need first
84 self.build()
86 # Install everything: simply dump the entire contents of the build
87 # directory to the installation directory (that's the beauty of
88 # having a build directory!)
89 outfiles = self.install()
91 # (Optionally) compile .py to .pyc
92 if outfiles is not None and self.distribution.has_pure_modules():
93 self.byte_compile(outfiles)
95 # run ()
98 # -- Top-level worker functions ------------------------------------
99 # (called from 'run()')
101 def build (self):
102 if not self.skip_build:
103 if self.distribution.has_pure_modules():
104 self.run_command('build_py')
105 if self.distribution.has_ext_modules():
106 self.run_command('build_ext')
108 def install (self):
109 if os.path.isdir(self.build_dir):
110 outfiles = self.copy_tree(self.build_dir, self.install_dir)
111 else:
112 self.warn("'%s' does not exist -- no Python modules to install" %
113 self.build_dir)
114 return
115 return outfiles
117 def byte_compile (self, files):
118 from distutils.util import byte_compile
120 # Get the "--root" directory supplied to the "install" command,
121 # and use it as a prefix to strip off the purported filename
122 # encoded in bytecode files. This is far from complete, but it
123 # should at least generate usable bytecode in RPM distributions.
124 install_root = self.get_finalized_command('install').root
126 if self.compile:
127 byte_compile(files, optimize=0,
128 force=self.force,
129 prefix=install_root,
130 verbose=self.verbose, dry_run=self.dry_run)
131 if self.optimize > 0:
132 byte_compile(files, optimize=self.optimize,
133 force=self.force,
134 prefix=install_root,
135 verbose=self.verbose, dry_run=self.dry_run)
138 # -- Utility methods -----------------------------------------------
140 def _mutate_outputs (self, has_any, build_cmd, cmd_option, output_dir):
142 if not has_any:
143 return []
145 build_cmd = self.get_finalized_command(build_cmd)
146 build_files = build_cmd.get_outputs()
147 build_dir = getattr(build_cmd, cmd_option)
149 prefix_len = len(build_dir) + len(os.sep)
150 outputs = []
151 for file in build_files:
152 outputs.append(os.path.join(output_dir, file[prefix_len:]))
154 return outputs
156 # _mutate_outputs ()
158 def _bytecode_filenames (self, py_filenames):
159 bytecode_files = []
160 for py_file in py_filenames:
161 if self.compile:
162 bytecode_files.append(py_file + "c")
163 if self.optimize > 0:
164 bytecode_files.append(py_file + "o")
166 return bytecode_files
169 # -- External interface --------------------------------------------
170 # (called by outsiders)
172 def get_outputs (self):
173 """Return the list of files that would be installed if this command
174 were actually run. Not affected by the "dry-run" flag or whether
175 modules have actually been built yet.
177 pure_outputs = \
178 self._mutate_outputs(self.distribution.has_pure_modules(),
179 'build_py', 'build_lib',
180 self.install_dir)
181 if self.compile:
182 bytecode_outputs = self._bytecode_filenames(pure_outputs)
183 else:
184 bytecode_outputs = []
186 ext_outputs = \
187 self._mutate_outputs(self.distribution.has_ext_modules(),
188 'build_ext', 'build_lib',
189 self.install_dir)
191 return pure_outputs + bytecode_outputs + ext_outputs
193 # get_outputs ()
195 def get_inputs (self):
196 """Get the list of files that are input to this command, ie. the
197 files that get installed as they are named in the build tree.
198 The files in this list correspond one-to-one to the output
199 filenames returned by 'get_outputs()'.
201 inputs = []
203 if self.distribution.has_pure_modules():
204 build_py = self.get_finalized_command('build_py')
205 inputs.extend(build_py.get_outputs())
207 if self.distribution.has_ext_modules():
208 build_ext = self.get_finalized_command('build_ext')
209 inputs.extend(build_ext.get_outputs())
211 return inputs
213 # class install_lib