blob: 6154cf09431f72258638a927c1e360fd42c31ff3 [file] [log] [blame]
Benjamin Peterson1010bf32009-01-30 04:00:29 +00001"""distutils.command.install_lib
2
3Implements the Distutils 'install_lib' command
4(install all Python modules)."""
5
Tarek Ziadéc27aca72009-05-10 11:45:41 +00006import os
Brett Cannon61c35562013-06-15 12:59:53 -04007import importlib.util
Tarek Ziadé04fe7c02009-10-25 23:08:47 +00008import sys
9
Greg Ward13ae1c81999-03-22 14:55:25 +000010from distutils.core import Command
Greg Wardcb9c9ae2000-10-02 02:15:08 +000011from distutils.errors import DistutilsOptionError
Greg Ward13ae1c81999-03-22 14:55:25 +000012
Fred Drake25d88922004-07-28 14:55:10 +000013
14# Extension for Python source files.
Skip Montanaro7a98be22007-08-16 14:35:24 +000015PYTHON_SOURCE_EXTENSION = ".py"
Fred Drake25d88922004-07-28 14:55:10 +000016
Collin Winter5b7e9d72007-08-30 03:52:21 +000017class install_lib(Command):
Greg Ward13ae1c81999-03-22 14:55:25 +000018
Greg Wardd7ad5032000-05-23 01:55:16 +000019 description = "install all Python modules (extensions and pure Python)"
Greg Ward37bc8152000-01-30 18:34:15 +000020
Greg Wardcb9c9ae2000-10-02 02:15:08 +000021 # The byte-compilation options are a tad confusing. Here are the
22 # possible scenarios:
23 # 1) no compilation at all (--no-compile --no-optimize)
24 # 2) compile .pyc only (--compile --no-optimize; default)
Brett Cannonf299abd2015-04-13 14:21:02 -040025 # 3) compile .pyc and "opt-1" .pyc (--compile --optimize)
26 # 4) compile "opt-1" .pyc only (--no-compile --optimize)
27 # 5) compile .pyc and "opt-2" .pyc (--compile --optimize-more)
28 # 6) compile "opt-2" .pyc only (--no-compile --optimize-more)
Fred Drake21d45352001-12-06 21:01:19 +000029 #
Brett Cannonf299abd2015-04-13 14:21:02 -040030 # The UI for this is two options, 'compile' and 'optimize'.
Greg Wardcb9c9ae2000-10-02 02:15:08 +000031 # 'compile' is strictly boolean, and only decides whether to
32 # generate .pyc files. 'optimize' is three-way (0, 1, or 2), and
Brett Cannonf299abd2015-04-13 14:21:02 -040033 # decides both whether to generate .pyc files and what level of
Greg Wardcb9c9ae2000-10-02 02:15:08 +000034 # optimization to use.
35
Greg Wardbbeceea2000-02-18 00:25:39 +000036 user_options = [
37 ('install-dir=', 'd', "directory to install to"),
38 ('build-dir=','b', "build directory (where to install from)"),
Greg Ward3a0310a2000-09-13 01:02:25 +000039 ('force', 'f', "force installation (overwrite existing files)"),
Greg Wardcb9c9ae2000-10-02 02:15:08 +000040 ('compile', 'c', "compile .py to .pyc [default]"),
41 ('no-compile', None, "don't compile .py files"),
42 ('optimize=', 'O',
43 "also compile with optimization: -O1 for \"python -O\", "
44 "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
Gregory P. Smith74ead8f2000-05-12 01:46:47 +000045 ('skip-build', None, "skip the build steps"),
Greg Wardbbeceea2000-02-18 00:25:39 +000046 ]
Fred Drake21d45352001-12-06 21:01:19 +000047
Greg Wardcb9c9ae2000-10-02 02:15:08 +000048 boolean_options = ['force', 'compile', 'skip-build']
49 negative_opt = {'no-compile' : 'compile'}
Greg Ward99b032e2000-09-25 01:41:15 +000050
Collin Winter5b7e9d72007-08-30 03:52:21 +000051 def initialize_options(self):
Greg Ward13ae1c81999-03-22 14:55:25 +000052 # let the 'install' command dictate our installation directory
Greg Warde6ac2fc1999-09-29 12:38:18 +000053 self.install_dir = None
Greg Ward13ae1c81999-03-22 14:55:25 +000054 self.build_dir = None
Greg Ward3a0310a2000-09-13 01:02:25 +000055 self.force = 0
Greg Wardcb9c9ae2000-10-02 02:15:08 +000056 self.compile = None
57 self.optimize = None
Gregory P. Smith74ead8f2000-05-12 01:46:47 +000058 self.skip_build = None
Greg Ward13ae1c81999-03-22 14:55:25 +000059
Collin Winter5b7e9d72007-08-30 03:52:21 +000060 def finalize_options(self):
Greg Wardfa4eb181999-09-13 13:58:34 +000061 # Get all the information we need to install pure Python modules
62 # from the umbrella 'install' command -- build (source) directory,
63 # install (target) directory, and whether to compile .py files.
Greg Ward7b87c0e2000-09-23 01:10:10 +000064 self.set_undefined_options('install',
65 ('build_lib', 'build_dir'),
66 ('install_lib', 'install_dir'),
67 ('force', 'force'),
Greg Wardcb9c9ae2000-10-02 02:15:08 +000068 ('compile', 'compile'),
69 ('optimize', 'optimize'),
Greg Ward7b87c0e2000-09-23 01:10:10 +000070 ('skip_build', 'skip_build'),
71 )
Greg Ward13ae1c81999-03-22 14:55:25 +000072
Greg Wardcb9c9ae2000-10-02 02:15:08 +000073 if self.compile is None:
Collin Winter5b7e9d72007-08-30 03:52:21 +000074 self.compile = True
Greg Wardcb9c9ae2000-10-02 02:15:08 +000075 if self.optimize is None:
Collin Winter5b7e9d72007-08-30 03:52:21 +000076 self.optimize = False
Greg Wardcb9c9ae2000-10-02 02:15:08 +000077
Collin Winter5b7e9d72007-08-30 03:52:21 +000078 if not isinstance(self.optimize, int):
Greg Wardcb9c9ae2000-10-02 02:15:08 +000079 try:
80 self.optimize = int(self.optimize)
Tarek Ziadéda31a3f2009-05-12 07:06:42 +000081 if self.optimize not in (0, 1, 2):
82 raise AssertionError
Greg Wardcb9c9ae2000-10-02 02:15:08 +000083 except (ValueError, AssertionError):
Collin Winter5b7e9d72007-08-30 03:52:21 +000084 raise DistutilsOptionError("optimize must be 0, 1, or 2")
Greg Wardcb9c9ae2000-10-02 02:15:08 +000085
Collin Winter5b7e9d72007-08-30 03:52:21 +000086 def run(self):
Greg Warde5dfba52000-03-29 02:17:42 +000087 # Make sure we have built everything we need first
Greg Wardf84fb662000-09-23 01:20:19 +000088 self.build()
Fred Drake21d45352001-12-06 21:01:19 +000089
Greg Wardf84fb662000-09-23 01:20:19 +000090 # Install everything: simply dump the entire contents of the build
91 # directory to the installation directory (that's the beauty of
92 # having a build directory!)
93 outfiles = self.install()
94
95 # (Optionally) compile .py to .pyc
Greg Wardc1acc692000-10-01 23:50:13 +000096 if outfiles is not None and self.distribution.has_pure_modules():
Greg Wardcb9c9ae2000-10-02 02:15:08 +000097 self.byte_compile(outfiles)
Greg Wardf84fb662000-09-23 01:20:19 +000098
Greg Wardf84fb662000-09-23 01:20:19 +000099 # -- Top-level worker functions ------------------------------------
100 # (called from 'run()')
101
Collin Winter5b7e9d72007-08-30 03:52:21 +0000102 def build(self):
Gregory P. Smith74ead8f2000-05-12 01:46:47 +0000103 if not self.skip_build:
104 if self.distribution.has_pure_modules():
Greg Ward7b87c0e2000-09-23 01:10:10 +0000105 self.run_command('build_py')
Gregory P. Smith74ead8f2000-05-12 01:46:47 +0000106 if self.distribution.has_ext_modules():
Greg Ward7b87c0e2000-09-23 01:10:10 +0000107 self.run_command('build_ext')
Fred Drake21d45352001-12-06 21:01:19 +0000108
Collin Winter5b7e9d72007-08-30 03:52:21 +0000109 def install(self):
Greg Wardf355d472000-05-20 15:08:57 +0000110 if os.path.isdir(self.build_dir):
Greg Ward7b87c0e2000-09-23 01:10:10 +0000111 outfiles = self.copy_tree(self.build_dir, self.install_dir)
Greg Wardf355d472000-05-20 15:08:57 +0000112 else:
113 self.warn("'%s' does not exist -- no Python modules to install" %
114 self.build_dir)
115 return
Greg Wardf84fb662000-09-23 01:20:19 +0000116 return outfiles
Greg Warde5dfba52000-03-29 02:17:42 +0000117
Collin Winter5b7e9d72007-08-30 03:52:21 +0000118 def byte_compile(self, files):
Tarek Ziadé04fe7c02009-10-25 23:08:47 +0000119 if sys.dont_write_bytecode:
120 self.warn('byte-compiling is disabled, skipping.')
121 return
122
Greg Wardcb9c9ae2000-10-02 02:15:08 +0000123 from distutils.util import byte_compile
124
125 # Get the "--root" directory supplied to the "install" command,
126 # and use it as a prefix to strip off the purported filename
127 # encoded in bytecode files. This is far from complete, but it
128 # should at least generate usable bytecode in RPM distributions.
129 install_root = self.get_finalized_command('install').root
130
131 if self.compile:
132 byte_compile(files, optimize=0,
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000133 force=self.force, prefix=install_root,
134 dry_run=self.dry_run)
Greg Wardcb9c9ae2000-10-02 02:15:08 +0000135 if self.optimize > 0:
136 byte_compile(files, optimize=self.optimize,
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000137 force=self.force, prefix=install_root,
Greg Wardcb9c9ae2000-10-02 02:15:08 +0000138 verbose=self.verbose, dry_run=self.dry_run)
Greg Ward13ae1c81999-03-22 14:55:25 +0000139
Greg Warde5dfba52000-03-29 02:17:42 +0000140
Greg Wardf84fb662000-09-23 01:20:19 +0000141 # -- Utility methods -----------------------------------------------
142
Collin Winter5b7e9d72007-08-30 03:52:21 +0000143 def _mutate_outputs(self, has_any, build_cmd, cmd_option, output_dir):
Greg Warde5dfba52000-03-29 02:17:42 +0000144 if not has_any:
145 return []
146
Greg Ward7b87c0e2000-09-23 01:10:10 +0000147 build_cmd = self.get_finalized_command(build_cmd)
Greg Warde5dfba52000-03-29 02:17:42 +0000148 build_files = build_cmd.get_outputs()
Greg Ward7b87c0e2000-09-23 01:10:10 +0000149 build_dir = getattr(build_cmd, cmd_option)
Greg Warde5dfba52000-03-29 02:17:42 +0000150
Greg Ward7b87c0e2000-09-23 01:10:10 +0000151 prefix_len = len(build_dir) + len(os.sep)
Greg Warde5dfba52000-03-29 02:17:42 +0000152 outputs = []
153 for file in build_files:
Greg Ward7b87c0e2000-09-23 01:10:10 +0000154 outputs.append(os.path.join(output_dir, file[prefix_len:]))
Greg Warde5dfba52000-03-29 02:17:42 +0000155
156 return outputs
157
Collin Winter5b7e9d72007-08-30 03:52:21 +0000158 def _bytecode_filenames(self, py_filenames):
Gregory P. Smith11fb7832000-05-13 02:11:10 +0000159 bytecode_files = []
160 for py_file in py_filenames:
Fred Drake25d88922004-07-28 14:55:10 +0000161 # Since build_py handles package data installation, the
162 # list of outputs can contain more than just .py files.
163 # Make sure we only report bytecode for the .py files.
164 ext = os.path.splitext(os.path.normcase(py_file))[1]
165 if ext != PYTHON_SOURCE_EXTENSION:
166 continue
Greg Wardcb9c9ae2000-10-02 02:15:08 +0000167 if self.compile:
Brett Cannon61c35562013-06-15 12:59:53 -0400168 bytecode_files.append(importlib.util.cache_from_source(
Brett Cannonf299abd2015-04-13 14:21:02 -0400169 py_file, optimization=''))
Greg Ward02951812000-10-02 02:25:51 +0000170 if self.optimize > 0:
Brett Cannon61c35562013-06-15 12:59:53 -0400171 bytecode_files.append(importlib.util.cache_from_source(
Brett Cannonf299abd2015-04-13 14:21:02 -0400172 py_file, optimization=self.optimize))
Gregory P. Smith11fb7832000-05-13 02:11:10 +0000173
174 return bytecode_files
Fred Drake21d45352001-12-06 21:01:19 +0000175
Greg Wardf84fb662000-09-23 01:20:19 +0000176
177 # -- External interface --------------------------------------------
178 # (called by outsiders)
179
Collin Winter5b7e9d72007-08-30 03:52:21 +0000180 def get_outputs(self):
Greg Warde5dfba52000-03-29 02:17:42 +0000181 """Return the list of files that would be installed if this command
182 were actually run. Not affected by the "dry-run" flag or whether
Greg Ward7b87c0e2000-09-23 01:10:10 +0000183 modules have actually been built yet.
184 """
Greg Warde5dfba52000-03-29 02:17:42 +0000185 pure_outputs = \
Greg Ward7b87c0e2000-09-23 01:10:10 +0000186 self._mutate_outputs(self.distribution.has_pure_modules(),
187 'build_py', 'build_lib',
188 self.install_dir)
Gregory P. Smith11fb7832000-05-13 02:11:10 +0000189 if self.compile:
190 bytecode_outputs = self._bytecode_filenames(pure_outputs)
191 else:
192 bytecode_outputs = []
Greg Warde5dfba52000-03-29 02:17:42 +0000193
194 ext_outputs = \
Greg Ward7b87c0e2000-09-23 01:10:10 +0000195 self._mutate_outputs(self.distribution.has_ext_modules(),
196 'build_ext', 'build_lib',
197 self.install_dir)
Greg Warde5dfba52000-03-29 02:17:42 +0000198
Gregory P. Smith11fb7832000-05-13 02:11:10 +0000199 return pure_outputs + bytecode_outputs + ext_outputs
Greg Warde5dfba52000-03-29 02:17:42 +0000200
Collin Winter5b7e9d72007-08-30 03:52:21 +0000201 def get_inputs(self):
Greg Ward1aab6e92000-03-31 02:53:07 +0000202 """Get the list of files that are input to this command, ie. the
203 files that get installed as they are named in the build tree.
204 The files in this list correspond one-to-one to the output
Greg Ward7b87c0e2000-09-23 01:10:10 +0000205 filenames returned by 'get_outputs()'.
206 """
Greg Ward1aab6e92000-03-31 02:53:07 +0000207 inputs = []
Fred Drake21d45352001-12-06 21:01:19 +0000208
Greg Ward1aab6e92000-03-31 02:53:07 +0000209 if self.distribution.has_pure_modules():
Greg Ward7b87c0e2000-09-23 01:10:10 +0000210 build_py = self.get_finalized_command('build_py')
211 inputs.extend(build_py.get_outputs())
Greg Ward1aab6e92000-03-31 02:53:07 +0000212
213 if self.distribution.has_ext_modules():
Greg Ward7b87c0e2000-09-23 01:10:10 +0000214 build_ext = self.get_finalized_command('build_ext')
215 inputs.extend(build_ext.get_outputs())
Greg Ward1aab6e92000-03-31 02:53:07 +0000216
217 return inputs