Nixpkgs: Python on Nix claims to be manylinux compatible

Created on 10 Sep 2016  路  12Comments  路  Source: NixOS/nixpkgs

Issue description

thanks to the rules in https://www.python.org/dev/peps/pep-0513/#platform-detection-for-installers
python on nix is considered to be manylinux compatible

in order to elevate the issue it is necessary to create a _manylinux python module that contains manylinux1_compatible = False

bug python

Most helpful comment

I think it makes little sense to disable manylinux1 compatibility in the name of trying to avoid inconsistent linking / external dependencies. The practical reality is that any package installed with pip -- whether manylinux1 or not -- could link to external libraries. If a user intends to use pip, they are already exiting the comfort of nix-managed packaging and should be treated as assuming those risks.

Nonetheless, for users looking for a workaround, the compatibility flag can be overridden manually within a virtualenv (though perhaps not with python3.5's native venv module):

python3.5 -m virtualenv venv
echo "manylinux1_compatible = True" > venv/lib/python3.5/_manylinux.py
source venv/bin/activate
python -c 'import _manylinux; print(_manylinux.manylinux1_compatible)'

All 12 comments

That should be a matter of a simple patch to the interpreters adding that file.

do you have a script I could run to test whether our Python is not anymore manylinux compatible?

@FRidh just typed this one up - it can be pulled into a single command

import _manylinux
assert not _manylinux.manylinux1_compatible

I've pushed a fix to staging (63ec006). As soon as staging is merged into master the unstable channel will have the fix.

Could someone explain why it's not manylinux compatible? It would be nice to be able to use manylinux1 wheels on Nix.

Is it because of https://www.python.org/dev/peps/pep-0513/#the-manylinux1-policy or something deeper?

Good question. I am not sure anymore the exact reason (we should have documented that) but if I am correct the main issue is that wheels can depend on certain libraries which we can provide, but which will be at a different location. When we build from source we hardcode the path to these shared libraries. In the case of a compiled wheel, we would have to patch after installation or pass LD_LIBRARY_PATH.

nixos doesn't provide the requested libraries/symbol versions off-hand, also the more strict/save shared object location pinning requires exact library locations - so the only way to try and support manylinux1 would be a patched python that correctly sets up the linker, but at the same time that would weaken one of the benefits of nix/nixos - exact and consistent linkage

Many manylinux1 binaries don't actually link to any external libraries. The declaration in Nix's _manylinux prevents even these from being installed. pip itself takes the stance that as long as libc is compatible it will go ahead and do the installation - and if additional libraries are linked against, it's the user's responsibility to deal with it. It would be a lot more convenient of Nix to take a stance like this.

I think it makes little sense to disable manylinux1 compatibility in the name of trying to avoid inconsistent linking / external dependencies. The practical reality is that any package installed with pip -- whether manylinux1 or not -- could link to external libraries. If a user intends to use pip, they are already exiting the comfort of nix-managed packaging and should be treated as assuming those risks.

Nonetheless, for users looking for a workaround, the compatibility flag can be overridden manually within a virtualenv (though perhaps not with python3.5's native venv module):

python3.5 -m virtualenv venv
echo "manylinux1_compatible = True" > venv/lib/python3.5/_manylinux.py
source venv/bin/activate
python -c 'import _manylinux; print(_manylinux.manylinux1_compatible)'

Is there a way of overriding this restriction without using a virtualenv? I'd like to just take responsibility for fixing up the linkage of a downloaded wheel during a regular nix build.

EDIT: I figured this out for myself, sorry for the noise. I just copied the normal installPhase, but added a line to write a _manylinux.py file as suggested above, and tacked that on to PYTHONPATH before the pip install call.

What do you guys think of actually adding manylinux1 support to Nix-generated Python environments?

I created a derivation which gathers together all the required libraries here.

I would envision adding an option enableManylinux1 to mk-python-derivation.nix which adds this bundle of libraries to the LD_LIBRARY_PATH for the resulting Python binaries. (python.withPackages is a thin wrapper around this so you could easily supply the option when setting up a Python env.)

Even without further plumbing, you can use it like this:

myWithPackages = f: let packages = f pythonPackages; in
  python.buildEnv.override {
    extraLibs = packages;
    makeWrapperArgs = ["--set" "LD_LIBRARY_PATH" (makeLibraryPath [(callPackage ./manylinux1.nix {}).package])];
  };

If there's interest I can put together a PR.

at first glance this looks interesting, i'd suggest to open a issue and/or pr with what you have (but i currently also dont use nix for personal reasons

Was this page helpful?
0 / 5 - 0 ratings

Related issues

domenkozar picture domenkozar  路  3Comments

ghost picture ghost  路  3Comments

edolstra picture edolstra  路  3Comments

retrry picture retrry  路  3Comments

langston-barrett picture langston-barrett  路  3Comments