setup.py
(传统)
#
Prior to the introduction of pyproject.toml-based builds (in
PEP 517
and
PEP 518
), pip had only supported installing packages using
setup.py
files that were built using
setuptools
.
The interface documented here is retained currently solely for legacy purposes, until the migration to
pyproject.toml
-based builds can be completed.
Caution
The arguments and syntax of the various invocations of
setup.py
made by pip, are considered an implementation detail that is strongly coupled with
setuptools
. This build system interface is not meant to be used by any other build backend, which should be based on the
pyproject.toml
build system interface instead.
Further, projects should
not
expect to rely on there being any form of backward compatibility guarantees around the
setup.py
接口。
The overall process for building a package is:
Generate the package’s metadata.
Generate a wheel for the package.
If this fails and we’re trying to install the package, attempt a direct installation.
The wheel can then be used to perform an installation, if necessary.
As a first step,
pip
needs to get metadata about a package (name, version, dependencies, and more). It collects this by calling
setup.py egg_info
.
The
egg_info
command generates the metadata for the package, which pip can then consume and proceed to gather all the dependencies of the package. Once the dependency resolution process is complete, pip will proceed to the next stage of the build process for these packages.
When provided with a source distribution (or “sdist”) for a package, pip will attempt to build a wheel . Since wheel distributions can be cached , this can greatly speed up future installations for the package.
This is done by calling
setup.py bdist_wheel
which requires the
wheel
package to be installed.
If this wheel generation is successful (this can include compiling C/C++ code, depending on the package), the generated wheel is added to pip’s wheel cache and will be used for this installation. The built wheel is cached locally by pip to avoid repeated identical builds.
If this wheel generation fails, pip runs
setup.py clean
to clean up any build artifacts that may have been generated. After that, pip will attempt a direct installation.
When all else fails, pip will invoke
setup.py install
to install a package using setuptools’ mechanisms to perform the installation. This is currently the last-resort fallback for projects that cannot be built into wheels, and may not be supported in the future.
For installing packages in “editable” mode (
pip install --editable
), pip will invoke
setup.py develop
, which will use setuptools’ mechanisms to perform an editable/development installation.
To support projects that directly use
distutils
, pip injects
setuptools
into
sys.modules
before invoking
setup.py
. This injection should be transparent to
distutils
-based projects.
The
--global-option
and
--build-option
arguments to the
pip install
and
pip wheel
inject additional arguments into the
setup.py
命令 (
--build-option
is only available in
pip wheel
).
Attention
The use of
--global-option
and
--build-option
is highly setuptools specific, and is considered more an accident of the current implementation than a supported interface. It is documented here for completeness. These flags will not be supported, once this build system interface is dropped.
These arguments are included in the command as follows:
python setup.py <global_options> BUILD COMMAND <build_options>
The options are passed unmodified, and presently offer direct access to the distutils command line. For example:
$ python -m pip wheel --global-option bdist_ext --global-option -DFOO wheel
$ python -m pip wheel --global-option bdist_ext --global-option -DFOO wheel
C:> py -m pip wheel --global-option bdist_ext --global-option -DFOO wheel
will result in pip invoking:
setup.py bdist_ext -DFOO bdist_wheel -d TARGET
This passes a preprocessor symbol to the extension build.
Any output produced by the build system will be read by pip (for display to the user if requested). In order to correctly read the build system output, pip requires that the output is written in a well-defined encoding, specifically the encoding the user has configured for text output (which can be obtained in Python using
locale.getpreferredencoding
). If the configured encoding is ASCII, pip assumes UTF-8 (to account for the behaviour of some Unix systems).
Build systems should ensure that any tools they invoke (compilers, etc) produce output in the correct encoding. In practice - and in particular on Windows, where tools are inconsistent in their use of the “OEM” and “ANSI” codepages - this may not always be possible. pip will therefore attempt to recover cleanly if presented with incorrectly encoded build tool output, by translating unexpected byte sequences to Python-style hexadecimal escape sequences (
"\x80\xff"
, etc). However, it is still possible for output to be displayed using an incorrect encoding (mojibake).