python-peps/pep-0513/index.html

762 lines
62 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 513 A Platform Tag for Portable Linux Built Distributions | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0513/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 513 A Platform Tag for Portable Linux Built Distributions | peps.python.org'>
<meta property="og:description" content="This PEP proposes the creation of a new platform tag for Python package built distributions, such as wheels, called manylinux1_{x86_64,i686} with external dependencies limited to a standardized, restricted subset of the Linux kernel and core userspace A...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0513/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP proposes the creation of a new platform tag for Python package built distributions, such as wheels, called manylinux1_{x86_64,i686} with external dependencies limited to a standardized, restricted subset of the Linux kernel and core userspace A...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 513</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 513 A Platform Tag for Portable Linux Built Distributions</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Robert T. McGibbon &lt;rmcgibbo&#32;&#97;t&#32;gmail.com&gt;, Nathaniel J. Smith &lt;njs&#32;&#97;t&#32;pobox.com&gt;</dd>
<dt class="field-even">BDFL-Delegate<span class="colon">:</span></dt>
<dd class="field-even">Alyssa Coghlan &lt;ncoghlan&#32;&#97;t&#32;gmail.com&gt;</dd>
<dt class="field-odd">Discussions-To<span class="colon">:</span></dt>
<dd class="field-odd"><a class="reference external" href="https://mail.python.org/archives/list/distutils-sig&#64;python.org/">Distutils-SIG list</a></dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Replaced by another succeeding PEP">Superseded</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd>
<dt class="field-even">Topic<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="../topic/packaging/">Packaging</a></dd>
<dt class="field-odd">Created<span class="colon">:</span></dt>
<dd class="field-odd">19-Jan-2016</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">19-Jan-2016, 25-Jan-2016, 29-Jan-2016</dd>
<dt class="field-odd">Superseded-By<span class="colon">:</span></dt>
<dd class="field-odd"><a class="reference external" href="../pep-0600/">600</a></dd>
<dt class="field-even">Resolution<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="https://mail.python.org/pipermail/distutils-sig/2016-January/028211.html">Distutils-SIG message</a></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#key-causes-of-inter-linux-binary-incompatibility">Key Causes of Inter-Linux Binary Incompatibility</a><ul>
<li><a class="reference internal" href="#external-shared-libraries">External Shared Libraries</a></li>
<li><a class="reference internal" href="#versioning-of-core-shared-libraries">Versioning of Core Shared Libraries</a></li>
</ul>
</li>
<li><a class="reference internal" href="#the-manylinux1-policy">The <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> policy</a><ul>
<li><a class="reference internal" href="#libpythonx-y-so-1">libpythonX.Y.so.1</a></li>
<li><a class="reference internal" href="#ucs-2-vs-ucs-4-builds">UCS-2 vs UCS-4 builds</a></li>
<li><a class="reference internal" href="#fpectl-builds-vs-no-fpectl-builds">fpectl builds vs. no fpectl builds</a></li>
</ul>
</li>
<li><a class="reference internal" href="#compilation-of-compliant-wheels">Compilation of Compliant Wheels</a><ul>
<li><a class="reference internal" href="#docker-image">Docker Image</a></li>
<li><a class="reference internal" href="#auditwheel">Auditwheel</a></li>
</ul>
</li>
<li><a class="reference internal" href="#bundled-wheels-on-linux">Bundled Wheels on Linux</a><ul>
<li><a class="reference internal" href="#security-implications">Security Implications</a></li>
</ul>
</li>
<li><a class="reference internal" href="#platform-detection-for-installers">Platform Detection for Installers</a></li>
<li><a class="reference internal" href="#pypi-support">PyPI Support</a></li>
<li><a class="reference internal" href="#rejected-alternatives">Rejected Alternatives</a></li>
<li><a class="reference internal" href="#future-updates">Future updates</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP proposes the creation of a new platform tag for Python package built
distributions, such as wheels, called <code class="docutils literal notranslate"><span class="pre">manylinux1_{x86_64,i686}</span></code> with
external dependencies limited to a standardized, restricted subset of
the Linux kernel and core userspace ABI. It proposes that PyPI support
uploading and distributing wheels with this platform tag, and that <code class="docutils literal notranslate"><span class="pre">pip</span></code>
support downloading and installing these packages on compatible platforms.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>Currently, distribution of binary Python extensions for Windows and OS X is
straightforward. Developers and packagers build wheels (<a class="pep reference internal" href="../pep-0427/" title="PEP 427 The Wheel Binary Package Format 1.0">PEP 427</a>, <a class="pep reference internal" href="../pep-0491/" title="PEP 491 The Wheel Binary Package Format 1.9">PEP 491</a>),
which are
assigned platform tags such as <code class="docutils literal notranslate"><span class="pre">win32</span></code> or <code class="docutils literal notranslate"><span class="pre">macosx_10_6_intel</span></code>, and upload
these wheels to PyPI. Users can download and install these wheels using tools
such as <code class="docutils literal notranslate"><span class="pre">pip</span></code>.</p>
<p>For Linux, the situation is much more delicate. In general, compiled Python
extension modules built on one Linux distribution will not work on other Linux
distributions, or even on different machines running the same Linux
distribution with different system libraries installed.</p>
<p>Build tools using <a class="pep reference internal" href="../pep-0425/" title="PEP 425 Compatibility Tags for Built Distributions">PEP 425</a> platform tags do not track information about the
particular Linux distribution or installed system libraries, and instead assign
all wheels the too-vague <code class="docutils literal notranslate"><span class="pre">linux_i686</span></code> or <code class="docutils literal notranslate"><span class="pre">linux_x86_64</span></code> tags. Because of
this ambiguity, there is no expectation that <code class="docutils literal notranslate"><span class="pre">linux</span></code>-tagged built
distributions compiled on one machine will work properly on another, and for
this reason, PyPI has not permitted the uploading of wheels for Linux.</p>
<p>It would be ideal if wheel packages could be compiled that would work on <em>any</em>
linux system. But, because of the incredible diversity of Linux systems from
PCs to Android to embedded systems with custom libcs this cannot
be guaranteed in general.</p>
<p>Instead, we define a standard subset of the kernel+core userspace ABI that,
in practice, is compatible enough that packages conforming to this standard
will work on <em>many</em> linux systems, including essentially all of the desktop
and server distributions in common use. We know this because there are
companies who have been distributing such widely-portable pre-compiled Python
extension modules for Linux e.g. Enthought with Canopy <a class="footnote-reference brackets" href="#id16" id="id1">[4]</a> and Continuum
Analytics with Anaconda <a class="footnote-reference brackets" href="#id17" id="id2">[5]</a>.</p>
<p>Building on the compatibility lessons learned from these companies, we thus
define a baseline <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> platform tag for use by binary Python
wheels, and introduce the implementation of preliminary tools to aid in the
construction of these <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> wheels.</p>
</section>
<section id="key-causes-of-inter-linux-binary-incompatibility">
<h2><a class="toc-backref" href="#key-causes-of-inter-linux-binary-incompatibility" role="doc-backlink">Key Causes of Inter-Linux Binary Incompatibility</a></h2>
<p>To properly define a standard that will guarantee that wheel packages meeting
this specification will operate on <em>many</em> linux platforms, it is necessary to
understand the root causes which often prevent portability of pre-compiled
binaries on Linux. The two key causes are dependencies on shared libraries
which are not present on users systems, and dependencies on particular
versions of certain core libraries like <code class="docutils literal notranslate"><span class="pre">glibc</span></code>.</p>
<section id="external-shared-libraries">
<h3><a class="toc-backref" href="#external-shared-libraries" role="doc-backlink">External Shared Libraries</a></h3>
<p>Most desktop and server linux distributions come with a system package manager
(examples include <code class="docutils literal notranslate"><span class="pre">APT</span></code> on Debian-based systems, <code class="docutils literal notranslate"><span class="pre">yum</span></code> on
<code class="docutils literal notranslate"><span class="pre">RPM</span></code>-based systems, and <code class="docutils literal notranslate"><span class="pre">pacman</span></code> on Arch linux) that manages, among other
responsibilities, the installation of shared libraries installed to system
directories such as <code class="docutils literal notranslate"><span class="pre">/usr/lib</span></code>. Most non-trivial Python extensions will depend
on one or more of these shared libraries, and thus function properly only on
systems where the user has the proper libraries (and the proper
versions thereof), either installed using their package manager, or installed
manually by setting certain environment variables such as <code class="docutils literal notranslate"><span class="pre">LD_LIBRARY_PATH</span></code>
to notify the runtime linker of the location of the depended-upon shared
libraries.</p>
</section>
<section id="versioning-of-core-shared-libraries">
<h3><a class="toc-backref" href="#versioning-of-core-shared-libraries" role="doc-backlink">Versioning of Core Shared Libraries</a></h3>
<p>Even if the developers a Python extension module wish to use no
external shared libraries, the modules will generally have a dynamic runtime
dependency on the GNU C library, <code class="docutils literal notranslate"><span class="pre">glibc</span></code>. While it is possible, statically
linking <code class="docutils literal notranslate"><span class="pre">glibc</span></code> is usually a bad idea because certain important C functions
like <code class="docutils literal notranslate"><span class="pre">dlopen()</span></code> cannot be called from code that statically links <code class="docutils literal notranslate"><span class="pre">glibc</span></code>. A
runtime shared library dependency on a system-provided <code class="docutils literal notranslate"><span class="pre">glibc</span></code> is unavoidable
in practice.</p>
<p>The maintainers of the GNU C library follow a strict symbol versioning scheme
for backward compatibility. This ensures that binaries compiled against an older
version of <code class="docutils literal notranslate"><span class="pre">glibc</span></code> can run on systems that have a newer <code class="docutils literal notranslate"><span class="pre">glibc</span></code>. The
opposite is generally not true binaries compiled on newer Linux
distributions tend to rely upon versioned functions in <code class="docutils literal notranslate"><span class="pre">glibc</span></code> that are not
available on older systems.</p>
<p>This generally prevents wheels compiled on the latest Linux distributions
from being portable.</p>
</section>
</section>
<section id="the-manylinux1-policy">
<h2><a class="toc-backref" href="#the-manylinux1-policy" role="doc-backlink">The <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> policy</a></h2>
<p>For these reasons, to achieve broad portability, Python wheels</p>
<ul class="simple">
<li>should depend only on an extremely limited set of external shared
libraries; and</li>
<li>should depend only on “old” symbol versions in those external shared
libraries; and</li>
<li>should depend only on a widely-compatible kernel ABI.</li>
</ul>
<p>To be eligible for the <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> platform tag, a Python wheel must
therefore both (a) contain binary executables and compiled code that links
<em>only</em> to libraries with SONAMEs
included in the following list:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">libpanelw</span><span class="o">.</span><span class="n">so</span><span class="mf">.5</span>
<span class="n">libncursesw</span><span class="o">.</span><span class="n">so</span><span class="mf">.5</span>
<span class="n">libgcc_s</span><span class="o">.</span><span class="n">so</span><span class="mf">.1</span>
<span class="n">libstdc</span><span class="o">++.</span><span class="n">so</span><span class="mf">.6</span>
<span class="n">libm</span><span class="o">.</span><span class="n">so</span><span class="mf">.6</span>
<span class="n">libdl</span><span class="o">.</span><span class="n">so</span><span class="mf">.2</span>
<span class="n">librt</span><span class="o">.</span><span class="n">so</span><span class="mf">.1</span>
<span class="n">libc</span><span class="o">.</span><span class="n">so</span><span class="mf">.6</span>
<span class="n">libnsl</span><span class="o">.</span><span class="n">so</span><span class="mf">.1</span>
<span class="n">libutil</span><span class="o">.</span><span class="n">so</span><span class="mf">.1</span>
<span class="n">libpthread</span><span class="o">.</span><span class="n">so</span><span class="mf">.0</span>
<span class="n">libresolv</span><span class="o">.</span><span class="n">so</span><span class="mf">.2</span>
<span class="n">libX11</span><span class="o">.</span><span class="n">so</span><span class="mf">.6</span>
<span class="n">libXext</span><span class="o">.</span><span class="n">so</span><span class="mf">.6</span>
<span class="n">libXrender</span><span class="o">.</span><span class="n">so</span><span class="mf">.1</span>
<span class="n">libICE</span><span class="o">.</span><span class="n">so</span><span class="mf">.6</span>
<span class="n">libSM</span><span class="o">.</span><span class="n">so</span><span class="mf">.6</span>
<span class="n">libGL</span><span class="o">.</span><span class="n">so</span><span class="mf">.1</span>
<span class="n">libgobject</span><span class="o">-</span><span class="mf">2.0</span><span class="o">.</span><span class="n">so</span><span class="mf">.0</span>
<span class="n">libgthread</span><span class="o">-</span><span class="mf">2.0</span><span class="o">.</span><span class="n">so</span><span class="mf">.0</span>
<span class="n">libglib</span><span class="o">-</span><span class="mf">2.0</span><span class="o">.</span><span class="n">so</span><span class="mf">.0</span>
</pre></div>
</div>
<p>and, (b) work on a stock CentOS 5.11 <a class="footnote-reference brackets" href="#id18" id="id3">[6]</a> system that contains the system
package managers provided versions of these libraries.</p>
<p><code class="docutils literal notranslate"><span class="pre">libcrypt.so.1</span></code> was retrospectively removed from the whitelist after
Fedora 30 was released with <code class="docutils literal notranslate"><span class="pre">libcrypt.so.2</span></code> instead.</p>
<p>Because CentOS 5 is only available for x86_64 and i686 architectures,
these are the only architectures currently supported by the <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code>
policy.</p>
<p>On Debian-based systems, these libraries are provided by the packages</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">libncurses5</span> <span class="n">libgcc1</span> <span class="n">libstdc</span><span class="o">++</span><span class="mi">6</span> <span class="n">libc6</span> <span class="n">libx11</span><span class="o">-</span><span class="mi">6</span> <span class="n">libxext6</span>
<span class="n">libxrender1</span> <span class="n">libice6</span> <span class="n">libsm6</span> <span class="n">libgl1</span><span class="o">-</span><span class="n">mesa</span><span class="o">-</span><span class="n">glx</span> <span class="n">libglib2</span><span class="mf">.0</span><span class="o">-</span><span class="mi">0</span>
</pre></div>
</div>
<p>On RPM-based systems, these libraries are provided by the packages</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ncurses</span> <span class="n">libgcc</span> <span class="n">libstdc</span><span class="o">++</span> <span class="n">glibc</span> <span class="n">libXext</span> <span class="n">libXrender</span>
<span class="n">libICE</span> <span class="n">libSM</span> <span class="n">mesa</span><span class="o">-</span><span class="n">libGL</span> <span class="n">glib2</span>
</pre></div>
</div>
<p>This list was compiled by checking the external shared library dependencies of
the Canopy <a class="footnote-reference brackets" href="#id16" id="id4">[4]</a> and Anaconda <a class="footnote-reference brackets" href="#id17" id="id5">[5]</a> distributions, which both include a wide array
of the most popular Python modules and have been confirmed in practice to work
across a wide swath of Linux systems in the wild.</p>
<p>Many of the permitted system libraries listed above use symbol versioning
schemes for backward compatibility. The latest symbol versions provided with
the CentOS 5.11 versions of these libraries are:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">GLIBC_2</span><span class="mf">.5</span>
<span class="n">CXXABI_3</span><span class="mf">.4.8</span>
<span class="n">GLIBCXX_3</span><span class="mf">.4.9</span>
<span class="n">GCC_4</span><span class="mf">.2.0</span>
</pre></div>
</div>
<p>Therefore, as a consequence of requirement (b), any wheel that depends on
versioned symbols from the above shared libraries may depend only on symbols
with the following versions:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">GLIBC</span> <span class="o">&lt;=</span> <span class="mf">2.5</span>
<span class="n">CXXABI</span> <span class="o">&lt;=</span> <span class="mf">3.4.8</span>
<span class="n">GLIBCXX</span> <span class="o">&lt;=</span> <span class="mf">3.4.9</span>
<span class="n">GCC</span> <span class="o">&lt;=</span> <span class="mf">4.2.0</span>
</pre></div>
</div>
<p>These recommendations are the outcome of the relevant discussions in January
2016 <a class="footnote-reference brackets" href="#id19" id="id6">[7]</a>, <a class="footnote-reference brackets" href="#id20" id="id7">[8]</a>.</p>
<p>Note that in our recommendations below, we do not suggest that <code class="docutils literal notranslate"><span class="pre">pip</span></code>
or PyPI should attempt to check for and enforce the details of this
policy (just as they dont check for and enforce the details of
existing platform tags like <code class="docutils literal notranslate"><span class="pre">win32</span></code>). The text above is provided (a)
as advice to package builders, and (b) as a method for allocating
blame if a given wheel doesnt work on some system: if it satisfies
the policy above, then this is a bug in the spec or the installation
tool; if it does not satisfy the policy above, then its a bug in the
wheel. One useful consequence of this approach is that it leaves open
the possibility of further updates and tweaks as we gain more
experience, e.g., we could have a “manylinux 1.1” policy which targets
the same systems and uses the same <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> platform tag (and
thus requires no further changes to <code class="docutils literal notranslate"><span class="pre">pip</span></code> or PyPI), but that adjusts
the list above to remove libraries that have turned out to be
problematic or add libraries that have turned out to be safe.</p>
<section id="libpythonx-y-so-1">
<h3><a class="toc-backref" href="#libpythonx-y-so-1" role="doc-backlink">libpythonX.Y.so.1</a></h3>
<p>Note that <code class="docutils literal notranslate"><span class="pre">libpythonX.Y.so.1</span></code> is <em>not</em> on the list of libraries that
a <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> extension is allowed to link to. Explicitly linking
to <code class="docutils literal notranslate"><span class="pre">libpythonX.Y.so.1</span></code> is unnecessary in almost all cases: the way
ELF linking works, extension modules that are loaded into the
interpreter automatically get access to all of the interpreters
symbols, regardless of whether or not the extension itself is
explicitly linked against libpython. Furthermore, explicit linking to
libpython creates problems in the common configuration where Python is
not built with <code class="docutils literal notranslate"><span class="pre">--enable-shared</span></code>. In particular, on Debian and
Ubuntu systems, <code class="docutils literal notranslate"><span class="pre">apt</span> <span class="pre">install</span> <span class="pre">pythonX.Y</span></code> does not even install
<code class="docutils literal notranslate"><span class="pre">libpythonX.Y.so.1</span></code>, meaning that any wheel that <em>did</em> depend on
<code class="docutils literal notranslate"><span class="pre">libpythonX.Y.so.1</span></code> could fail to import.</p>
<p>There is one situation where extensions that are linked in this way
can fail to work: if a host program (e.g., <code class="docutils literal notranslate"><span class="pre">apache2</span></code>) uses
<code class="docutils literal notranslate"><span class="pre">dlopen()</span></code> to load a module (e.g., <code class="docutils literal notranslate"><span class="pre">mod_wsgi</span></code>) that embeds the
CPython interpreter, and the host program does <em>not</em> pass the
<code class="docutils literal notranslate"><span class="pre">RTLD_GLOBAL</span></code> flag to <code class="docutils literal notranslate"><span class="pre">dlopen()</span></code>, then the embedded CPython will
be unable to load any extension modules that do not themselves link
explicitly to <code class="docutils literal notranslate"><span class="pre">libpythonX.Y.so.1</span></code>. Fortunately, <code class="docutils literal notranslate"><span class="pre">apache2</span></code> <em>does</em>
set the <code class="docutils literal notranslate"><span class="pre">RTLD_GLOBAL</span></code> flag, as do all the other programs that
embed-CPython-via-a-dlopened-plugin that we could locate, so this does
not seem to be a serious problem in practice. The incompatibility with
Debian/Ubuntu is more of an issue than the theoretical incompatibility
with a rather obscure corner case.</p>
<p>This is a rather complex and subtle issue that extends beyond
the scope of <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code>; for more discussion see: <a class="footnote-reference brackets" href="#id21" id="id8">[9]</a>, <a class="footnote-reference brackets" href="#id22" id="id9">[10]</a>,
<a class="footnote-reference brackets" href="#id23" id="id10">[11]</a>.</p>
</section>
<section id="ucs-2-vs-ucs-4-builds">
<h3><a class="toc-backref" href="#ucs-2-vs-ucs-4-builds" role="doc-backlink">UCS-2 vs UCS-4 builds</a></h3>
<p>All versions of CPython 2.x, plus CPython 3.0-3.2 inclusive, can be
built in two ABI-incompatible modes: builds using the
<code class="docutils literal notranslate"><span class="pre">--enable-unicode=ucs2</span></code> configure flag store Unicode data in UCS-2
(or really UTF-16) format, while builds using the
<code class="docutils literal notranslate"><span class="pre">--enable-unicode=ucs4</span></code> configure flag store Unicode data in
UCS-4. (CPython 3.3 and greater use a different storage method that
always supports UCS-4.) If we want to make sure <code class="docutils literal notranslate"><span class="pre">ucs2</span></code> wheels dont
get installed into <code class="docutils literal notranslate"><span class="pre">ucs4</span></code> CPythons and vice-versa, then something
must be done.</p>
<p>An earlier version of this PEP included a requirement that
<code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> wheels targeting these older CPython versions should
always use the <code class="docutils literal notranslate"><span class="pre">ucs4</span></code> ABI. But then, in between the PEPs initial
acceptance and its implementation, <code class="docutils literal notranslate"><span class="pre">pip</span></code> and <code class="docutils literal notranslate"><span class="pre">wheel</span></code> gained
first-class support for tracking and checking this aspect of ABI
compatibility for the relevant CPython versions, which is a better
solution. So we now allow the <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> platform tags to be used
in combination with any ABI tag. However, to maintain compatibility it
is crucial to ensure that all <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> wheels include a
non-trivial abi tag. For example, a wheel built against a <code class="docutils literal notranslate"><span class="pre">ucs4</span></code>
CPython might have a name like:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>PKG-VERSION-cp27-cp27mu-manylinux1_x86_64.whl
^^^^^^ Good!
</pre></div>
</div>
<p>While a wheel built against the <code class="docutils literal notranslate"><span class="pre">ucs2</span></code> ABI might have a name like:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>PKG-VERSION-cp27-cp27m-manylinux1_x86_64.whl
^^^^^ Okay!
</pre></div>
</div>
<p>But you should never have a wheel with a name like:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>PKG-VERSION-cp27-none-manylinux1_x86_64.whl
^^^^ BAD! Don&#39;t do this!
</pre></div>
</div>
<p>This wheel claims to be simultaneously compatible with <em>both</em> ucs2 and
ucs4 builds, which is bad.</p>
<p>We note for information that the <code class="docutils literal notranslate"><span class="pre">ucs4</span></code> ABI appears to be much more
widespread among Linux CPython distributors.</p>
</section>
<section id="fpectl-builds-vs-no-fpectl-builds">
<h3><a class="toc-backref" href="#fpectl-builds-vs-no-fpectl-builds" role="doc-backlink">fpectl builds vs. no fpectl builds</a></h3>
<p>All extant versions of CPython can be built either with or without the
<code class="docutils literal notranslate"><span class="pre">--with-fpectl</span></code> flag to <code class="docutils literal notranslate"><span class="pre">configure</span></code>. It turns out that this
changes the CPython ABI: extensions that are built against a
no-<code class="docutils literal notranslate"><span class="pre">fpectl</span></code> CPython are always compatible with yes-<code class="docutils literal notranslate"><span class="pre">fpectl</span></code>
CPython, but the reverse is not necessarily true. (Symptom: errors at
import time complaining about <code class="docutils literal notranslate"><span class="pre">undefined</span> <span class="pre">symbol:</span> <span class="pre">PyFPE_jbuf</span></code>.) See:
<a class="footnote-reference brackets" href="#id28" id="id11">[16]</a>.</p>
<p>For maximum compatibility, therefore, the CPython used to build
manylinux1 wheels must be compiled <em>without</em> the <code class="docutils literal notranslate"><span class="pre">--with-fpectl</span></code>
flag, and manylinux1 extensions must not reference the symbol
<code class="docutils literal notranslate"><span class="pre">PyFPE_jbuf</span></code>.</p>
</section>
</section>
<section id="compilation-of-compliant-wheels">
<h2><a class="toc-backref" href="#compilation-of-compliant-wheels" role="doc-backlink">Compilation of Compliant Wheels</a></h2>
<p>The way glibc, libgcc, and libstdc++ manage their symbol versioning
means that in practice, the compiler toolchains that most developers
use to do their daily work are incapable of building
<code class="docutils literal notranslate"><span class="pre">manylinux1</span></code>-compliant wheels. Therefore, we do not attempt to change
the default behavior of <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">wheel</span></code> / <code class="docutils literal notranslate"><span class="pre">bdist_wheel</span></code>: they will
continue to generate regular <code class="docutils literal notranslate"><span class="pre">linux_*</span></code> platform tags, and developers
who wish to use them to generate <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code>-tagged wheels will
have to change the tag as a second post-processing step.</p>
<p>To support the compilation of wheels meeting the <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> standard, we
provide initial drafts of two tools.</p>
<section id="docker-image">
<h3><a class="toc-backref" href="#docker-image" role="doc-backlink">Docker Image</a></h3>
<p>The first tool is a Docker image based on CentOS 5.11, which is recommended as
an easy to use self-contained build box for compiling <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> wheels
<a class="footnote-reference brackets" href="#id24" id="id12">[12]</a>. Compiling on a more recently-released linux distribution will generally
introduce dependencies on too-new versioned symbols. The image comes with a
full compiler suite installed (<code class="docutils literal notranslate"><span class="pre">gcc</span></code>, <code class="docutils literal notranslate"><span class="pre">g++</span></code>, and <code class="docutils literal notranslate"><span class="pre">gfortran</span></code> 4.8.2) as
well as the latest releases of Python and <code class="docutils literal notranslate"><span class="pre">pip</span></code>.</p>
</section>
<section id="auditwheel">
<h3><a class="toc-backref" href="#auditwheel" role="doc-backlink">Auditwheel</a></h3>
<p>The second tool is a command line executable called <code class="docutils literal notranslate"><span class="pre">auditwheel</span></code> <a class="footnote-reference brackets" href="#id25" id="id13">[13]</a> that
may aid in package maintainers in dealing with third-party external
dependencies.</p>
<p>There are at least three methods for building wheels that use third-party
external libraries in a way that meets the above policy.</p>
<ol class="arabic simple">
<li>The third-party libraries can be statically linked.</li>
<li>The third-party shared libraries can be distributed in
separate packages on PyPI which are depended upon by the wheel.</li>
<li>The third-party shared libraries can be bundled inside the wheel
libraries, linked with a relative path.</li>
</ol>
<p>All of these are valid option which may be effectively used by different
packages and communities. Statically linking generally requires
package-specific modifications to the build system, and distributing
third-party dependencies on PyPI may require some coordination of the
community of users of the package.</p>
<p>As an often-automatic alternative to these options, we introduce <code class="docutils literal notranslate"><span class="pre">auditwheel</span></code>.
The tool inspects all of the ELF files inside a wheel to check for
dependencies on versioned symbols or external shared libraries, and verifies
conformance with the <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> policy. This includes the ability to add
the new platform tag to conforming wheels. More importantly, <code class="docutils literal notranslate"><span class="pre">auditwheel</span></code> has
the ability to automatically modify wheels that depend on external shared
libraries by copying those shared libraries from the system into the wheel
itself, and modifying the appropriate <code class="docutils literal notranslate"><span class="pre">RPATH</span></code> entries such that these
libraries will be picked up at runtime. This accomplishes a similar result as
if the libraries had been statically linked without requiring changes to the
build system. Packagers are advised that bundling, like static linking, may
implicate copyright concerns.</p>
</section>
</section>
<section id="bundled-wheels-on-linux">
<h2><a class="toc-backref" href="#bundled-wheels-on-linux" role="doc-backlink">Bundled Wheels on Linux</a></h2>
<p>While we acknowledge many approaches for dealing with third-party library
dependencies within <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> wheels, we recognize that the <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code>
policy encourages bundling external dependencies, a practice
which runs counter to the package management policies of many linux
distributions system package managers <a class="footnote-reference brackets" href="#id26" id="id14">[14]</a>, <a class="footnote-reference brackets" href="#id27" id="id15">[15]</a>. The primary purpose of
this is cross-distro compatibility. Furthermore, <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> wheels on PyPI
occupy a different niche than the Python packages available through the
system package manager.</p>
<p>The decision in this PEP to encourage departure from general Linux distribution
unbundling policies is informed by the following concerns:</p>
<ol class="arabic simple">
<li>In these days of automated continuous integration and deployment
pipelines, publishing new versions and updating dependencies is easier
than it was when those policies were defined.</li>
<li><code class="docutils literal notranslate"><span class="pre">pip</span></code> users remain free to use the <code class="docutils literal notranslate"><span class="pre">&quot;--no-binary&quot;</span></code> option if they want
to force local builds rather than using pre-built wheel files.</li>
<li>The popularity of modern container based deployment and “immutable
infrastructure” models involve substantial bundling at the application
layer anyway.</li>
<li>Distribution of bundled wheels through PyPI is currently the norm for
Windows and OS X.</li>
<li>This PEP doesnt rule out the idea of offering more targeted binaries for
particular Linux distributions in the future.</li>
</ol>
<p>The model described in this PEP is most ideally suited for cross-platform
Python packages, because it means they can reuse much of the
work that theyre already doing to make static Windows and OS X wheels. We
recognize that it is less optimal for Linux-specific packages that might
prefer to interact more closely with Linuxs unique package management
functionality and only care about targeting a small set of particular distos.</p>
<section id="security-implications">
<h3><a class="toc-backref" href="#security-implications" role="doc-backlink">Security Implications</a></h3>
<p>One of the advantages of dependencies on centralized libraries in Linux is
that bugfixes and security updates can be deployed system-wide, and
applications which depend on these libraries will automatically feel the
effects of these patches when the underlying libraries are updated. This can
be particularly important for security updates in packages engaged in
communication across the network or cryptography.</p>
<p><code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> wheels distributed through PyPI that bundle security-critical
libraries like OpenSSL will thus assume responsibility for prompt updates in
response disclosed vulnerabilities and patches. This closely parallels the
security implications of the distribution of binary wheels on Windows that,
because the platform lacks a system package manager, generally bundle their
dependencies. In particular, because it lacks a stable ABI, OpenSSL cannot be
included in the <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> profile.</p>
</section>
</section>
<section id="platform-detection-for-installers">
<h2><a class="toc-backref" href="#platform-detection-for-installers" role="doc-backlink">Platform Detection for Installers</a></h2>
<p>Above, we defined what it means for a <em>wheel</em> to be
<code class="docutils literal notranslate"><span class="pre">manylinux1</span></code>-compatible. Here we discuss what it means for a <em>Python
installation</em> to be <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code>-compatible. In particular, this is
important for tools like <code class="docutils literal notranslate"><span class="pre">pip</span></code> to know when deciding whether or not
they should consider <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code>-tagged wheels for installation.</p>
<p>Because the <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> profile is already known to work for the
many thousands of users of popular commercial Python distributions, we
suggest that installation tools should error on the side of assuming
that a system <em>is</em> compatible, unless there is specific reason to
think otherwise.</p>
<p>We know of four main sources of potential incompatibility that are
likely to arise in practice:</p>
<ul class="simple">
<li>Eventually, in the future, there may exist distributions that break
compatibility with this profile (e.g., if one of the libraries in
the profile changes its ABI in a backwards-incompatible way)</li>
<li>A linux distribution that is too old (e.g. RHEL 4)</li>
<li>A linux distribution that does not use <code class="docutils literal notranslate"><span class="pre">glibc</span></code> (e.g. Alpine Linux, which is
based on musl <code class="docutils literal notranslate"><span class="pre">libc</span></code>, or Android)</li>
</ul>
<p>To address these we propose a two-pronged
approach. To handle potential future incompatibilities, we standardize
a mechanism for a Python distributor to signal that a particular
Python install definitely is or is not compatible with <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code>:
this is done by installing a module named <code class="docutils literal notranslate"><span class="pre">_manylinux</span></code>, and setting
its <code class="docutils literal notranslate"><span class="pre">manylinux1_compatible</span></code> attribute. We do not propose adding any
such module to the standard library this is merely a well-known
name by which distributors and installation tools can
rendezvous. However, if a distributor does add this module, <em>they
should add it to the standard library</em> rather than to a
<code class="docutils literal notranslate"><span class="pre">site-packages/</span></code> directory, because the standard library is
inherited by virtualenvs (which we want), and <code class="docutils literal notranslate"><span class="pre">site-packages/</span></code> in
general is not.</p>
<p>Then, to handle the last two cases for existing Python
distributions, we suggest a simple and reliable method to check for
the presence and version of <code class="docutils literal notranslate"><span class="pre">glibc</span></code> (basically using it as a “clock”
for the overall age of the distribution).</p>
<p>Specifically, the algorithm we propose is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">is_manylinux1_compatible</span><span class="p">():</span>
<span class="c1"># Only Linux, and only x86-64 / i686</span>
<span class="kn">from</span> <span class="nn">distutils.util</span> <span class="kn">import</span> <span class="n">get_platform</span>
<span class="k">if</span> <span class="n">get_platform</span><span class="p">()</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">&quot;linux-x86_64&quot;</span><span class="p">,</span> <span class="s2">&quot;linux-i686&quot;</span><span class="p">]:</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="c1"># Check for presence of _manylinux module</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">_manylinux</span>
<span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="n">_manylinux</span><span class="o">.</span><span class="n">manylinux1_compatible</span><span class="p">)</span>
<span class="k">except</span> <span class="p">(</span><span class="ne">ImportError</span><span class="p">,</span> <span class="ne">AttributeError</span><span class="p">):</span>
<span class="c1"># Fall through to heuristic check below</span>
<span class="k">pass</span>
<span class="c1"># Check glibc version. CentOS 5 uses glibc 2.5.</span>
<span class="k">return</span> <span class="n">have_compatible_glibc</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">have_compatible_glibc</span><span class="p">(</span><span class="n">major</span><span class="p">,</span> <span class="n">minimum_minor</span><span class="p">):</span>
<span class="kn">import</span> <span class="nn">ctypes</span>
<span class="n">process_namespace</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">gnu_get_libc_version</span> <span class="o">=</span> <span class="n">process_namespace</span><span class="o">.</span><span class="n">gnu_get_libc_version</span>
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
<span class="c1"># Symbol doesn&#39;t exist -&gt; therefore, we are not linked to</span>
<span class="c1"># glibc.</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="c1"># Call gnu_get_libc_version, which returns a string like &quot;2.5&quot;.</span>
<span class="n">gnu_get_libc_version</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span>
<span class="n">version_str</span> <span class="o">=</span> <span class="n">gnu_get_libc_version</span><span class="p">()</span>
<span class="c1"># py2 / py3 compatibility:</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">version_str</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
<span class="n">version_str</span> <span class="o">=</span> <span class="n">version_str</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">&quot;ascii&quot;</span><span class="p">)</span>
<span class="c1"># Parse string and check against requested version.</span>
<span class="n">version</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">piece</span><span class="p">)</span> <span class="k">for</span> <span class="n">piece</span> <span class="ow">in</span> <span class="n">version_str</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;.&quot;</span><span class="p">)]</span>
<span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">version</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span>
<span class="k">if</span> <span class="n">major</span> <span class="o">!=</span> <span class="n">version</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">if</span> <span class="n">minimum_minor</span> <span class="o">&gt;</span> <span class="n">version</span><span class="p">[</span><span class="mi">1</span><span class="p">]:</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">return</span> <span class="kc">True</span>
</pre></div>
</div>
<p><strong>Rejected alternatives:</strong> We also considered using a configuration
file, e.g. <code class="docutils literal notranslate"><span class="pre">/etc/python/compatibility.cfg</span></code>. The problem with this is
that a single filesystem might contain many different interpreter
environments, each with their own ABI profile the <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code>
compatibility of a system-installed x86_64 CPython might not tell us
much about the <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> compatibility of a user-installed i686
PyPy. Locating this configuration information within the Python
environment itself ensures that it remains attached to the correct
binary, and dramatically simplifies lookup code.</p>
<p>We also considered using a more elaborate structure, like a list of
all platform tags that should be considered compatible, together with
their preference ordering, for example: <code class="docutils literal notranslate"><span class="pre">_binary_compat.compatible</span> <span class="pre">=</span>
<span class="pre">[&quot;manylinux1_x86_64&quot;,</span> <span class="pre">&quot;centos5_x86_64&quot;,</span> <span class="pre">&quot;linux_x86_64&quot;]</span></code>. However,
this introduces several complications. For example, we want to be able
to distinguish between the state of “doesnt support <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code>
(or eventually <code class="docutils literal notranslate"><span class="pre">manylinux2</span></code>, etc.) versus “doesnt specify either
way whether it supports <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code>”, which is not entirely obvious
in the above representation; and, its not at all clear what features
are really needed vis a vis preference ordering given that right now
the only possible platform tags are <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> and <code class="docutils literal notranslate"><span class="pre">linux</span></code>. So
were deferring a more complete solution here for a separate PEP, when
/ if Linux gets more platform tags.</p>
<p>For the library compatibility check, we also considered much more
elaborate checks (e.g. checking the kernel version, searching for and
checking the versions of all the individual libraries listed in the
<code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> profile, etc.), but ultimately decided that this would
be more likely to introduce confusing bugs than actually help the
user. (For example: different distributions vary in where they
actually put these libraries, and if our checking code failed to use
the correct path search then it could easily return incorrect
answers.)</p>
</section>
<section id="pypi-support">
<h2><a class="toc-backref" href="#pypi-support" role="doc-backlink">PyPI Support</a></h2>
<p>PyPI should permit wheels containing the <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> platform tag to be
uploaded. PyPI should not attempt to formally verify that wheels containing
the <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> platform tag adhere to the <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> policy described
in this document. This verification tasks should be left to other tools, like
<code class="docutils literal notranslate"><span class="pre">auditwheel</span></code>, that are developed separately.</p>
</section>
<section id="rejected-alternatives">
<h2><a class="toc-backref" href="#rejected-alternatives" role="doc-backlink">Rejected Alternatives</a></h2>
<p>One alternative would be to provide separate platform tags for each Linux
distribution (and each version thereof), e.g. <code class="docutils literal notranslate"><span class="pre">RHEL6</span></code>, <code class="docutils literal notranslate"><span class="pre">ubuntu14_10</span></code>,
<code class="docutils literal notranslate"><span class="pre">debian_jessie</span></code>, etc. Nothing in this proposal rules out the possibility of
adding such platform tags in the future, or of further extensions to wheel
metadata that would allow wheels to declare dependencies on external
system-installed packages. However, such extensions would require substantially
more work than this proposal, and still might not be appreciated by package
developers who would prefer not to have to maintain multiple build environments
and build multiple wheels in order to cover all the common Linux distributions.
Therefore, we consider such proposals to be out-of-scope for this PEP.</p>
</section>
<section id="future-updates">
<h2><a class="toc-backref" href="#future-updates" role="doc-backlink">Future updates</a></h2>
<p>We anticipate that at some point in the future there will be a
<code class="docutils literal notranslate"><span class="pre">manylinux2</span></code> specifying a more modern baseline environment (perhaps
based on CentOS 6), and someday a <code class="docutils literal notranslate"><span class="pre">manylinux3</span></code> and so forth, but we
defer specifying these until we have more experience with the initial
<code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> proposal.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id16" role="doc-footnote">
<dt class="label" id="id16">[4]<em> (<a href='#id1'>1</a>, <a href='#id4'>2</a>) </em></dt>
<dd>Enthought Canopy Python Distribution
(<a class="reference external" href="https://store.enthought.com/downloads/">https://store.enthought.com/downloads/</a>)</aside>
<aside class="footnote brackets" id="id17" role="doc-footnote">
<dt class="label" id="id17">[5]<em> (<a href='#id2'>1</a>, <a href='#id5'>2</a>) </em></dt>
<dd>Continuum Analytics Anaconda Python Distribution
(<a class="reference external" href="https://www.continuum.io/downloads">https://www.continuum.io/downloads</a>)</aside>
<aside class="footnote brackets" id="id18" role="doc-footnote">
<dt class="label" id="id18">[<a href="#id3">6</a>]</dt>
<dd>CentOS 5.11 Release Notes
(<a class="reference external" href="https://wiki.centos.org/Manuals/ReleaseNotes/CentOS5.11">https://wiki.centos.org/Manuals/ReleaseNotes/CentOS5.11</a>)</aside>
<aside class="footnote brackets" id="id19" role="doc-footnote">
<dt class="label" id="id19">[<a href="#id6">7</a>]</dt>
<dd>manylinux-discuss mailing list discussion
(<a class="reference external" href="https://groups.google.com/forum/#!topic/manylinux-discuss/-4l3rrjfr9U">https://groups.google.com/forum/#!topic/manylinux-discuss/-4l3rrjfr9U</a>)</aside>
<aside class="footnote brackets" id="id20" role="doc-footnote">
<dt class="label" id="id20">[<a href="#id7">8</a>]</dt>
<dd>distutils-sig discussion
(<a class="reference external" href="https://mail.python.org/pipermail/distutils-sig/2016-January/027997.html">https://mail.python.org/pipermail/distutils-sig/2016-January/027997.html</a>)</aside>
<aside class="footnote brackets" id="id21" role="doc-footnote">
<dt class="label" id="id21">[<a href="#id8">9</a>]</dt>
<dd>distutils-sig discussion
(<a class="reference external" href="https://mail.python.org/pipermail/distutils-sig/2016-February/028275.html">https://mail.python.org/pipermail/distutils-sig/2016-February/028275.html</a>)</aside>
<aside class="footnote brackets" id="id22" role="doc-footnote">
<dt class="label" id="id22">[<a href="#id9">10</a>]</dt>
<dd>github issue discussion
(<a class="reference external" href="https://github.com/pypa/manylinux/issues/30">https://github.com/pypa/manylinux/issues/30</a>)</aside>
<aside class="footnote brackets" id="id23" role="doc-footnote">
<dt class="label" id="id23">[<a href="#id10">11</a>]</dt>
<dd>python bug tracker discussion
(<a class="reference external" href="https://bugs.python.org/issue21536">https://bugs.python.org/issue21536</a>)</aside>
<aside class="footnote brackets" id="id24" role="doc-footnote">
<dt class="label" id="id24">[<a href="#id12">12</a>]</dt>
<dd>manylinux1 docker images
(Source: <a class="reference external" href="https://github.com/pypa/manylinux">https://github.com/pypa/manylinux</a>;
x86-64: <a class="reference external" href="https://quay.io/repository/pypa/manylinux1_x86_64">https://quay.io/repository/pypa/manylinux1_x86_64</a>;
x86-32: <a class="reference external" href="https://quay.io/repository/pypa/manylinux1_i686">https://quay.io/repository/pypa/manylinux1_i686</a>)</aside>
<aside class="footnote brackets" id="id25" role="doc-footnote">
<dt class="label" id="id25">[<a href="#id13">13</a>]</dt>
<dd>auditwheel tool
(<a class="reference external" href="https://pypi.python.org/pypi/auditwheel">https://pypi.python.org/pypi/auditwheel</a>)</aside>
<aside class="footnote brackets" id="id26" role="doc-footnote">
<dt class="label" id="id26">[<a href="#id14">14</a>]</dt>
<dd>Fedora Bundled Software Policy
(<a class="reference external" href="https://fedoraproject.org/wiki/Bundled_Software_policy">https://fedoraproject.org/wiki/Bundled_Software_policy</a>)</aside>
<aside class="footnote brackets" id="id27" role="doc-footnote">
<dt class="label" id="id27">[<a href="#id15">15</a>]</dt>
<dd>Debian Policy Manual 4.13: Convenience copies of code
(<a class="reference external" href="https://www.debian.org/doc/debian-policy/ch-source.html#s-embeddedfiles">https://www.debian.org/doc/debian-policy/ch-source.html#s-embeddedfiles</a>)</aside>
<aside class="footnote brackets" id="id28" role="doc-footnote">
<dt class="label" id="id28">[<a href="#id11">16</a>]</dt>
<dd>numpy bug report:
<a class="reference external" href="https://github.com/numpy/numpy/issues/8415#issuecomment-269095235">https://github.com/numpy/numpy/issues/8415#issuecomment-269095235</a></aside>
</aside>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed into the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0513.rst">https://github.com/python/peps/blob/main/peps/pep-0513.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0513.rst">2023-10-11 12:05:51 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#key-causes-of-inter-linux-binary-incompatibility">Key Causes of Inter-Linux Binary Incompatibility</a><ul>
<li><a class="reference internal" href="#external-shared-libraries">External Shared Libraries</a></li>
<li><a class="reference internal" href="#versioning-of-core-shared-libraries">Versioning of Core Shared Libraries</a></li>
</ul>
</li>
<li><a class="reference internal" href="#the-manylinux1-policy">The <code class="docutils literal notranslate"><span class="pre">manylinux1</span></code> policy</a><ul>
<li><a class="reference internal" href="#libpythonx-y-so-1">libpythonX.Y.so.1</a></li>
<li><a class="reference internal" href="#ucs-2-vs-ucs-4-builds">UCS-2 vs UCS-4 builds</a></li>
<li><a class="reference internal" href="#fpectl-builds-vs-no-fpectl-builds">fpectl builds vs. no fpectl builds</a></li>
</ul>
</li>
<li><a class="reference internal" href="#compilation-of-compliant-wheels">Compilation of Compliant Wheels</a><ul>
<li><a class="reference internal" href="#docker-image">Docker Image</a></li>
<li><a class="reference internal" href="#auditwheel">Auditwheel</a></li>
</ul>
</li>
<li><a class="reference internal" href="#bundled-wheels-on-linux">Bundled Wheels on Linux</a><ul>
<li><a class="reference internal" href="#security-implications">Security Implications</a></li>
</ul>
</li>
<li><a class="reference internal" href="#platform-detection-for-installers">Platform Detection for Installers</a></li>
<li><a class="reference internal" href="#pypi-support">PyPI Support</a></li>
<li><a class="reference internal" href="#rejected-alternatives">Rejected Alternatives</a></li>
<li><a class="reference internal" href="#future-updates">Future updates</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0513.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>