<div dir="ltr">After I posted the PEP link on social media, a friend of mine, Kyle Beauchamp, asked: "I wonder if there are speed and correctness implications to always reverting to the lowest common denominator of glibc."<div><br></div><div>For speed, I believe there is some consequence, in that the maximum gcc version you can realistically use with glibc <= 2.5 is gcc 4.8.2, which is presumably somewhat (although not much) slower than the latest gcc release. As to correctness, it seems like a reasonable concern, and I don't know one way or the other. I thought maybe someone on the list would know.</div><div><br></div><div>There are also potential compatibility issues in wheels that use certain instruction set extensions (SSE 4, AVX, etc) that might not be available on certain platforms. I think policies on this issue are better left up to individual packages than set at a PEP-wide level, but it also may be worth talking about.</div><div><br></div><div>-Robert</div><div><div><span style="color:rgb(20,24,35);font-family:helvetica,arial,sans-serif;font-size:12px;line-height:16.08px;background-color:rgb(246,247,248)"><br></span></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jan 21, 2016 at 1:03 AM, M.-A. Lemburg <span dir="ltr"><<a href="mailto:mal@egenix.com" target="_blank">mal@egenix.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
Robert McGibbon: Thanks for writing up this PEP :-)<br>
<br>
Some comments below...<br>
<div><div class="h5"><br>
On 21.01.2016 04:55, Nathaniel Smith wrote:<br>
> The ``manylinux1`` policy<br>
> =========================<br>
><br>
> For these reasons, to achieve broad portability, Python wheels<br>
><br>
>  * should depend only on an extremely limited set of external shared<br>
>    libraries; and<br>
>  * should depend only on ``old`` symbol versions in those external shared<br>
>    libraries.<br>
><br>
> The ``manylinux1`` policy thus encompasses a standard for what the<br>
> permitted external shared libraries a wheel may depend on, and the maximum<br>
> depended-upon symbol versions therein.<br>
><br>
> The permitted external shared libraries are: ::<br>
><br>
>     libpanelw.so.5<br>
>     libncursesw.so.5<br>
>     libgcc_s.so.1<br>
>     libstdc++.so.6<br>
>     libm.so.6<br>
>     libdl.so.2<br>
>     librt.so.1<br>
>     libcrypt.so.1<br>
>     libc.so.6<br>
>     libnsl.so.1<br>
>     libutil.so.1<br>
>     libpthread.so.0<br>
>     libX11.so.6<br>
>     libXext.so.6<br>
>     libXrender.so.1<br>
>     libICE.so.6<br>
>     libSM.so.6<br>
>     libGL.so.1<br>
>     libgobject-2.0.so.0<br>
>     libgthread-2.0.so.0<br>
>     libglib-2.0.so.0<br>
<br>
</div></div>The list is good start, but limiting the possible external<br>
references to only these libraries will make it impossible<br>
to have manylinux1 wheels which link against other, similarly<br>
old, but very common libraries, or alternatively rather<br>
new ones, which are then optionally included via subpackage<br>
instead of being mandatory.<br>
<br>
At eGenix we have been tackling this problem for years with<br>
our extensions and the approach that's been the most<br>
successful was to simply use Linux build systems which<br>
are at least 5 years old. In our case, that's openSUSE 11.3.<br>
<br>
I think a better approach is to use the above list to<br>
test for used library *versions* and then apply the tag<br>
based on the findings.<br>
<br>
If a package includes binaries which link to e.g.<br>
later libc.so versions, it would be rejected. If it<br>
includes other libraries not listed in the above listing,<br>
that's fine, as long as these libraries also comply to<br>
the version limitation.<br>
<br>
What I'm getting at here is that incompatibilities are<br>
not caused by libraries being absent on the system<br>
(the package simply won't load, but that's not due to the<br>
the package being incompatible to the platform, only due<br>
to the system lacking a few packages), but instead by<br>
having the packages use more recent versions of these<br>
system libraries.<br>
<span class=""><br>
> Compilation and Tooling<br>
> =======================<br>
><br>
> To support the compilation of wheels meeting the ``manylinux1`` standard, we<br>
> provide initial drafts of two tools.<br>
><br>
> The first is a Docker image based on CentOS 5.11, which is recommended as an<br>
> easy to use self-contained build box for compiling ``manylinux1`` wheels [4]_.<br>
> Compiling on a more recently-released linux distribution will generally<br>
> introduce dependencies on too-new versioned symbols. The image comes with a<br>
> full compiler suite installed (``gcc``, ``g++``, and ``gfortran`` 4.8.2) as<br>
> well as the latest releases of Python and pip.<br>
><br>
> The second tool is a command line executable called ``auditwheel`` [5]_. First,<br>
> it inspects all of the ELF files inside a wheel to check for dependencies on<br>
> versioned symbols or external shared libraries, and verifies conformance with<br>
> the ``manylinux1`` policy. This includes the ability to add the new platform<br>
> tag to conforming wheels.<br>
><br>
> In addition, ``auditwheel`` has the ability to automatically modify wheels that<br>
> depend on external shared libraries by copying those shared libraries from<br>
> the system into the wheel itself, and modifying the appropriate RPATH entries<br>
> such that these libraries will be picked up at runtime. This accomplishes a<br>
> similar result as if the libraries had been statically linked without requiring<br>
> changes to the build system.<br>
<br>
</span>This approach has a few problems:<br>
<br>
* Libraries typically depend on a lot more context than just<br>
  the code that is provided in the libraries file, e.g. config<br>
  files, external resources, other libraries which are loaded<br>
  on demand, etc.<br>
<br>
* By including the libraries in the wheel you are distributing<br>
  the binary, which can lead to licensing problems, esp. with<br>
  GPLed or LGPLed code.<br>
<span class=""><br>
> Neither of these tools are necessary to build wheels which conform with the<br>
> ``manylinux1`` policy. Similar results can usually be achieved by statically<br>
> linking external dependencies and/or using certain inline assembly constructs<br>
> to instruct the linker to prefer older symbol versions, however these tricks<br>
> can be quite esoteric.<br>
<br>
</span>Static linking only helps in very few cases, where the context<br>
needed for the external library to work is minimal.<br>
<span class=""><br>
> Platform Detection for Installers<br>
> =================================<br>
><br>
> Because the ``manylinux1`` profile is already known to work for the many<br>
> thousands of users of popular commercial Python distributions, we suggest that<br>
> installation tools like ``pip`` should error on the side of assuming that a<br>
> system *is* compatible, unless there is specific reason to think otherwise.<br>
><br>
> We know of three main sources of potential incompatibility that are likely to<br>
> arise in practice:<br>
><br>
> * A linux distribution that is too old (e.g. RHEL 4)<br>
> * A linux distribution that does not use glibc (e.g. Alpine Linux, which is<br>
>   based on musl libc, or Android)<br>
> * Eventually, in the future, there may exist distributions that break<br>
>   compatibility with this profile<br>
><br>
> To handle the first two cases, we propose the following simple and reliable<br>
> check: ::<br>
>     def have_glibc_version(major, minimum_minor):<br>
</span>>         [...]<br>
<br>
It would be better to use platform.libc_ver() for this.<br>
<span class=""><br>
> ``manylinux1`` wheels distributed through PyPI that bundle security-critical<br>
> libraries like OpenSSL will thus assume responsibility for prompt updates in<br>
> response disclosed vulnerabilities and patches. This closely parallels the<br>
> security implications of the distribution of binary wheels on Windows that,<br>
> because the platform lacks a system package manager, generally bundle their<br>
> dependencies. In particular, because its lacks a stable ABI, OpenSSL cannot be<br>
> included in the ``manylinux1`` profile.<br>
<br>
</span>The OpenSSL ABI has been quite stable in recent years (unlike in the<br>
days of 0.9.7 and earlier).<br>
<br>
Since many libraries do link against OpenSSL (basically everything<br>
that uses network connections nowadays), using the fixed scheme<br>
outlined in the PEP would severely limited the usefulness.<br>
<br>
By using the version based approach, we'd not run into this<br>
problem and gain a lot more.<br>
<br>
--<br>
Marc-Andre Lemburg<br>
eGenix.com<br>
<br>
Professional Python Services directly from the Experts (#1, Jan 21 2016)<br>
>>> Python Projects, Coaching and Consulting ...  <a href="http://www.egenix.com/" rel="noreferrer" target="_blank">http://www.egenix.com/</a><br>
>>> Python Database Interfaces ...           <a href="http://products.egenix.com/" rel="noreferrer" target="_blank">http://products.egenix.com/</a><br>
>>> Plone/Zope Database Interfaces ...           <a href="http://zope.egenix.com/" rel="noreferrer" target="_blank">http://zope.egenix.com/</a><br>
________________________________________________________________________<br>
<br>
::: We implement business ideas - efficiently in both time and costs :::<br>
<br>
   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48<br>
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg<br>
           Registered at Amtsgericht Duesseldorf: HRB 46611<br>
               <a href="http://www.egenix.com/company/contact/" rel="noreferrer" target="_blank">http://www.egenix.com/company/contact/</a><br>
                      <a href="http://www.malemburg.com/" rel="noreferrer" target="_blank">http://www.malemburg.com/</a><br>
<br>
</blockquote></div><br></div>