|
| 1 | +PEP: 599 |
| 2 | +Title: The manylinux2014 Platform Tag |
| 3 | +Version: $Revision$ |
| 4 | +Last-Modified: $Date$ |
| 5 | +Author: Dustin Ingram < [email protected]> |
| 6 | +Sponsor: Paul Moore < [email protected]> |
| 7 | +BDFL-Delegate: Paul Moore < [email protected]> |
| 8 | +Discussions-To: https://discuss.python.org/t/the-next-manylinux-specification/ |
| 9 | +Status: Draft |
| 10 | +Type: Informational |
| 11 | +Content-Type: text/x-rst |
| 12 | +Created: 29-April-2019 |
| 13 | +Post-History: 29-April-2019 |
| 14 | + |
| 15 | + |
| 16 | +Abstract |
| 17 | +======== |
| 18 | + |
| 19 | +This PEP proposes the creation of a ``manylinux2014`` platform tag to |
| 20 | +succeed the ``manylinux2010`` tag introduced by :pep:`513`. It also |
| 21 | +proposes that PyPI and ``pip`` both be updated to support uploading, |
| 22 | +downloading, and installing ``manylinux2014`` distributions on |
| 23 | +compatible platforms. |
| 24 | + |
| 25 | +Rationale |
| 26 | +========= |
| 27 | + |
| 28 | +CentOS 6 is now the oldest supported CentOS release, and will receive |
| 29 | +maintenance updates through November 30th, 2020, [1]_ at which point |
| 30 | +it will reach end-of-life, and no further updates such as security |
| 31 | +patches will be made available. All wheels built under the |
| 32 | +``manylinux2010`` images will remain at obsolete versions after that |
| 33 | +point. |
| 34 | + |
| 35 | +Therefore, we propose the continuation of the existing manylinux |
| 36 | +standard, and that a new PEP 425-style [2]_ platform tag called |
| 37 | +``manylinux2014`` be derived from CentOS 7 and that the ``manylinux`` |
| 38 | +toolchain, PyPI, and ``pip`` be updated to support it. |
| 39 | + |
| 40 | +Similar to how :pep:`571` and :pep:`513` drew allowed shared |
| 41 | +libraries and their symbol versions from CentOS 5.11 and CentOS 6, |
| 42 | +respectively, a ``manylinux2014`` platform tag will draw its libraries |
| 43 | +and symbol versions from CentOS 7, which will reach end-of-life on |
| 44 | +June 30th, 2024. [1]_ |
| 45 | + |
| 46 | +The ``manylinuxYYYY`` pattern has a number of advantages that motivate |
| 47 | +continuing with the current status quo: |
| 48 | + |
| 49 | +- Well-defined Docker images with clearly specified compatible |
| 50 | + libraries; |
| 51 | +- No need to survey for compatibility issues across multiple releases; |
| 52 | +- A single build image and ``auditwheel`` profile per architecture. |
| 53 | + |
| 54 | +There are also some disadvantages: |
| 55 | + |
| 56 | +- Requires drafting a new PEP for every new standard; |
| 57 | +- Requires adding the new platform tag to installers (e.g., ``pip``); |
| 58 | +- Installers are unable to install a platform tag which predates a |
| 59 | + given release. |
| 60 | + |
| 61 | +There are also challenges which would exist for any proposal, |
| 62 | +including the time and effort it takes to define, prepare and release |
| 63 | +the Docker images and corresponding ``auditwheel`` profiles. These |
| 64 | +challenges were experienced in the long rollout period for |
| 65 | +``manylinux2010``, which took approximately 1 year from PEP acceptance |
| 66 | +to compatible build environment published. [3]_ |
| 67 | + |
| 68 | +However, if this PEP can be an indicator, the process is now |
| 69 | +well-defined and easily repeatable, which should increase the timeline |
| 70 | +for rollout of a newer, updated platform tag. |
| 71 | + |
| 72 | +The ``manylinux2014`` policy |
| 73 | +============================ |
| 74 | + |
| 75 | +The following criteria determine a ``linux`` wheel's eligibility for |
| 76 | +the ``manylinux2014`` tag: |
| 77 | + |
| 78 | +1. The wheel may only contain binary executables and shared objects |
| 79 | + compiled for one of the following architectures supported by CentOS |
| 80 | + 7, or a CentOS 7 compatible base image (such as ubi7): [4]_ :: |
| 81 | + |
| 82 | + x86_64 |
| 83 | + i686 |
| 84 | + aarch64 |
| 85 | + armhfp |
| 86 | + ppc64 |
| 87 | + ppc64le |
| 88 | + s390x |
| 89 | + |
| 90 | + This list adds support for ARM (aarch64, armhfp) and PowerPC |
| 91 | + (ppc64, ppc64le) architectures supported by the CentOS Alternative |
| 92 | + Architecture Special Interest Group, as well as the IBM Z (s390x) |
| 93 | + architecture. [5]_ |
| 94 | + |
| 95 | +2. The wheel's binary executables or shared objects may not link |
| 96 | + against externally-provided libraries except those in the following |
| 97 | + list: :: |
| 98 | + |
| 99 | + libgcc_s.so.1 |
| 100 | + libstdc++.so.6 |
| 101 | + libm.so.6 |
| 102 | + libdl.so.2 |
| 103 | + librt.so.1 |
| 104 | + libc.so.6 |
| 105 | + libnsl.so.1 |
| 106 | + libutil.so.1 |
| 107 | + libpthread.so.0 |
| 108 | + libresolv.so.2 |
| 109 | + libX11.so.6 |
| 110 | + libXext.so.6 |
| 111 | + libXrender.so.1 |
| 112 | + libICE.so.6 |
| 113 | + libSM.so.6 |
| 114 | + libGL.so.1 |
| 115 | + libgobject-2.0.so.0 |
| 116 | + libgthread-2.0.so.0 |
| 117 | + libglib-2.0.so.0 |
| 118 | + |
| 119 | + This list is identical to the externally-provided libraries |
| 120 | + originally allowed for ``manylinux2010``, with one exception: |
| 121 | + ``libcrypt.so.1`` was removed due to being deprecated in Fedora 30. |
| 122 | + ``libpythonX.Y`` remains ineligible for inclusion for the same |
| 123 | + reasons outlined in :pep:`513`. |
| 124 | + |
| 125 | + On Debian-based systems, these libraries are provided by the |
| 126 | + packages: |
| 127 | + |
| 128 | + ============ ======================================================= |
| 129 | + Package Libraries |
| 130 | + ============ ======================================================= |
| 131 | + libc6 libdl.so.2, libresolv.so.2, librt.so.1, libc.so.6, |
| 132 | + libpthread.so.0, libm.so.6, libutil.so.1, libnsl.so.1 |
| 133 | + libgcc1 libgcc_s.so.1 |
| 134 | + libgl1 libGL.so.1 |
| 135 | + libglib2.0-0 libgobject-2.0.so.0, libgthread-2.0.so.0, libglib-2.0.so.0 |
| 136 | + libice6 libICE.so.6 |
| 137 | + libsm6 libSM.so.6 |
| 138 | + libstdc++6 libstdc++.so.6 |
| 139 | + libx11-6 libX11.so.6 |
| 140 | + libxext6 libXext.so.6 |
| 141 | + libxrender1 libXrender.so.1 |
| 142 | + ============ ======================================================= |
| 143 | + |
| 144 | + On RPM-based systems, they are provided by these packages: |
| 145 | + |
| 146 | + ============ ======================================================= |
| 147 | + Package Libraries |
| 148 | + ============ ======================================================= |
| 149 | + glib2 libglib-2.0.so.0, libgthread-2.0.so.0, libgobject-2.0.so.0 |
| 150 | + glibc libresolv.so.2, libutil.so.1, libnsl.so.1, librt.so.1, |
| 151 | + libpthread.so.0, libdl.so.2, libm.so.6, libc.so.6 |
| 152 | + libICE libICE.so.6 |
| 153 | + libX11 libX11.so.6 |
| 154 | + libXext: libXext.so.6 |
| 155 | + libXrender libXrender.so.1 |
| 156 | + libgcc: libgcc_s.so.1 |
| 157 | + libstdc++ libstdc++.so.6 |
| 158 | + mesa libGL.so.1 |
| 159 | + ============ ======================================================= |
| 160 | + |
| 161 | +3. If the wheel contains binary executables or shared objects linked |
| 162 | + against any allowed libraries that also export versioned symbols, |
| 163 | + they may only depend on the following maximum versions:: |
| 164 | + |
| 165 | + GLIBC_2.17 |
| 166 | + CXXABI_1.3.7 |
| 167 | + GLIBCXX_3.4.19 |
| 168 | + GCC_4.8.5 |
| 169 | + |
| 170 | + As an example, ``manylinux2014`` wheels may include binary |
| 171 | + artifacts that require ``glibc`` symbols at version ``GLIBC_2.12``, |
| 172 | + because this an earlier version than the maximum of ``GLIBC_2.17``. |
| 173 | +4. If a wheel is built for any version of CPython 2 or CPython |
| 174 | + versions 3.0 up to and including 3.2, it *must* include a CPython |
| 175 | + ABI tag indicating its Unicode ABI. A ``manylinux2014`` wheel |
| 176 | + built against Python 2, then, must include either the ``cpy27mu`` |
| 177 | + tag indicating it was built against an interpreter with the UCS-4 |
| 178 | + ABI or the ``cpy27m`` tag indicating an interpreter with the UCS-2 |
| 179 | + ABI. [6]_ [7]_ |
| 180 | +5. A wheel *must not* require the ``PyFPE_jbuf`` symbol. This is |
| 181 | + achieved by building it against a Python compiled *without* the |
| 182 | + ``--with-fpectl`` ``configure`` flag. |
| 183 | + |
| 184 | +Compilation of Compliant Wheels |
| 185 | +=============================== |
| 186 | + |
| 187 | +Like ``manylinux1``, the ``auditwheel`` tool adds ``manylinux2014`` |
| 188 | +platform tags to ``linux`` wheels built by ``pip wheel`` or |
| 189 | +``bdist_wheel`` in a ``manylinux2014`` Docker container. |
| 190 | + |
| 191 | +Docker Images |
| 192 | +------------- |
| 193 | + |
| 194 | +A ``manylinux2014`` Docker image based on CentOS 7 x86_64 should be |
| 195 | +provided for building binary ``linux`` wheels that can reliably be |
| 196 | +converted to ``manylinux2014`` wheels. This image will come with a |
| 197 | +full compiler suite installed (``gcc``, ``g++``, and ``gfortran`` |
| 198 | +4.8.5) as well as the latest releases of Python and ``pip``. |
| 199 | + |
| 200 | +Compatibility with kernels that lack ``vsyscall`` |
| 201 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 202 | + |
| 203 | +Similar to CentOS 6, CentOS 7 includes a version of ``glibc`` that |
| 204 | +depends on the ``vsyscall`` page. As described in :pep:`571`, this |
| 205 | +breaks the assumption that a Docker containers userland is compatible |
| 206 | +wtih its host's kernel. Similar to ``manylinux2010``, Docker images |
| 207 | +for ``manylinux2014`` require patching ``glibc`` to remove all |
| 208 | +dependencies on ``vsyscall`` in the version of ``glibc`` included with |
| 209 | +our Docker image. |
| 210 | + |
| 211 | +Auditwheel |
| 212 | +---------- |
| 213 | + |
| 214 | +The ``auditwheel`` tool will also be updated to produce |
| 215 | +``manylinux2014`` wheels. [8]_ Its behavior and purpose will be |
| 216 | +otherwise unchanged from :pep:`513`. |
| 217 | + |
| 218 | +Platform Detection for Installers |
| 219 | +================================= |
| 220 | + |
| 221 | +Platforms may define a ``manylinux2014_compatible`` boolean attribute |
| 222 | +on the ``_manylinux`` module described in :pep:`513`. A platform is |
| 223 | +considered incompatible with ``manylinux2014`` if the attribute is |
| 224 | +``False``. |
| 225 | + |
| 226 | +If the ``_manylinux`` module is not found, or it does not have the |
| 227 | +attribute ``manylinux2014_compatible``, tools may fall back to |
| 228 | +checking for glibc. If the platform has glibc 2.17 or newer, it is |
| 229 | +assumed to be compatible unless the ``_manylinux`` module says |
| 230 | +otherwise. |
| 231 | + |
| 232 | +Specifically, the algorithm we propose is:: |
| 233 | + |
| 234 | + def is_manylinux2014_compatible(): |
| 235 | + # Only Linux, and only supported architectures |
| 236 | + from distutils.util import get_platform |
| 237 | + |
| 238 | + if get_platform() not in [ |
| 239 | + "linux-x86_64", |
| 240 | + "linux-i686", |
| 241 | + "linux-aarch64", |
| 242 | + "linux-armhfp", |
| 243 | + "linux-ppc64", |
| 244 | + "linux-ppc64le", |
| 245 | + "linux-s390x", |
| 246 | + ]: |
| 247 | + return False |
| 248 | + |
| 249 | + # Check for presence of _manylinux module |
| 250 | + try: |
| 251 | + import _manylinux |
| 252 | + |
| 253 | + return bool(_manylinux.manylinux2014_compatible) |
| 254 | + except (ImportError, AttributeError): |
| 255 | + # Fall through to heuristic check below |
| 256 | + pass |
| 257 | + |
| 258 | + # Check glibc version. CentOS 7 uses glibc 2.17. |
| 259 | + # PEP 513 contains an implementation of this function. |
| 260 | + return have_compatible_glibc(2, 17) |
| 261 | + |
| 262 | +Backwards compatibility with ``manylinux2010`` wheels |
| 263 | +===================================================== |
| 264 | + |
| 265 | +As explained in :pep:`513`, the specified symbol versions for |
| 266 | +``manylinux1`` allowed libraries constitute an *upper bound*. The |
| 267 | +same is true for the symbol versions defined for ``manylinux2014`` in |
| 268 | +this PEP. As a result, ``manylinux1`` and ``manylinux2010`` wheels |
| 269 | +are considered ``manylinux2014`` wheels. A ``pip`` that recognizes |
| 270 | +the ``manylinux2014`` platform tag will thus install ``manylinux2010`` |
| 271 | +wheels for ``manylinux2014`` platforms -- even when explicitly set -- |
| 272 | +when no ``manylinux2014`` wheels are available. |
| 273 | + |
| 274 | +PyPI Support |
| 275 | +============ |
| 276 | + |
| 277 | +PyPI should permit wheels containing the ``manylinux2014`` platform |
| 278 | +tag to be uploaded in the same way that it permits ``manylinux2010``. |
| 279 | +It should not attempt to verify the compatibility of ``manylinux2014`` |
| 280 | +wheels. |
| 281 | + |
| 282 | +References |
| 283 | +========== |
| 284 | + |
| 285 | +.. [1] CentOS Product Specifications |
| 286 | + (https://wiki.centos.org/About/Product) |
| 287 | +.. [2] PEP 425 -- Compatibility Tags for Built Distributions |
| 288 | + (https://www.python.org/dev/peps/pep-0425/) |
| 289 | +.. [3] Tracking issue for manylinux2010 rollout |
| 290 | + (https://github.com/pypa/manylinux/issues/179) |
| 291 | +.. [4] Red Hat Universal Base Image 7 |
| 292 | + (https://access.redhat.com/containers/?tab=overview#/registry.access.redhat.com/ubi7) |
| 293 | + (https://wiki.centos.org/SpecialInterestGroup/AltArch) |
| 294 | +.. [5] The CentOS Alternative Architecture Special Interest Group |
| 295 | + (https://wiki.centos.org/SpecialInterestGroup/AltArch) |
| 296 | +.. [6] PEP 3149 |
| 297 | + https://www.python.org/dev/peps/pep-3149/ |
| 298 | +.. [7] SOABI support for Python 2.X and PyPy |
| 299 | + https://github.com/pypa/pip/pull/3075 |
| 300 | +.. [8] auditwheel |
| 301 | + (https://github.com/pypa/auditwheel/) |
| 302 | +
|
| 303 | +Copyright |
| 304 | +========= |
| 305 | + |
| 306 | +This document is placed in the public domain or under the |
| 307 | +CC0-1.0-Universal license, whichever is more permissive. |
| 308 | + |
| 309 | +.. |
| 310 | + Local Variables: |
| 311 | + mode: indented-text |
| 312 | + indent-tabs-mode: nil |
| 313 | + sentence-end-double-space: t |
| 314 | + fill-column: 70 |
| 315 | + coding: utf-8 |
| 316 | + End: |
0 commit comments