762 lines
62 KiB
HTML
762 lines
62 KiB
HTML
|
||
<!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> » </li>
|
||
<li><a href="../pep-0000/">PEP Index</a> » </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 <rmcgibbo at gmail.com>, Nathaniel J. Smith <njs at pobox.com></dd>
|
||
<dt class="field-even">BDFL-Delegate<span class="colon">:</span></dt>
|
||
<dd class="field-even">Alyssa Coghlan <ncoghlan at gmail.com></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@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 manager’s 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"><=</span> <span class="mf">2.5</span>
|
||
<span class="n">CXXABI</span> <span class="o"><=</span> <span class="mf">3.4.8</span>
|
||
<span class="n">GLIBCXX</span> <span class="o"><=</span> <span class="mf">3.4.9</span>
|
||
<span class="n">GCC</span> <span class="o"><=</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 don’t 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 doesn’t 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 it’s 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 interpreter’s
|
||
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 don’t
|
||
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 PEP’s 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'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">"--no-binary"</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 doesn’t 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 they’re 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 Linux’s 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">"linux-x86_64"</span><span class="p">,</span> <span class="s2">"linux-i686"</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't exist -> 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 "2.5".</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">"ascii"</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">"."</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">></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">["manylinux1_x86_64",</span> <span class="pre">"centos5_x86_64",</span> <span class="pre">"linux_x86_64"]</span></code>. However,
|
||
this introduces several complications. For example, we want to be able
|
||
to distinguish between the state of “doesn’t 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 “doesn’t 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, it’s 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
|
||
we’re 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> |