Skip to content

musllinux support #430

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 16, 2022
Merged

musllinux support #430

merged 7 commits into from
Mar 16, 2022

Conversation

liath
Copy link
Contributor

@liath liath commented Sep 21, 2021

musllinux spec landed, let's get these wheels rollin 😎

@matthew-brett
Copy link
Collaborator

These look reasonable - how can I help?

Do you know of a good way to test? I guess we need a muslinux testing docker image.

@liath
Copy link
Contributor Author

liath commented Sep 22, 2021

Yeah looking at that now. Would you mind terribly if the alpine variants just pulled in pypa images like how the build step does? It'd really simplify things.

@matthew-brett
Copy link
Collaborator

The problem with that is that it is not a good test of whether the wheel really does work on another Linux.

Do you think it would be hard to make up another docker image like : https://github.com/multi-build/docker-images

@liath
Copy link
Contributor Author

liath commented Sep 22, 2021

Yeah that's what I'm looking at. Getting multiple parallel versions of python on Alpine is tedious. I think the only routes to doing so are compiling them yourself, as the pypa images do, or pyenv, which I do not know much about as I've always used it through asdf which would be even less indicative of normal environments :P

@liath
Copy link
Contributor Author

liath commented Sep 22, 2021

There's probably an argument there for just using what Alpine ships tbh, it is work to get other versions so most people will likely be using whatever is in apk.

@liath
Copy link
Contributor Author

liath commented Sep 22, 2021

Or I could quit complaining and just get started on porting the build script. :P

@matthew-brett
Copy link
Collaborator

Actually, I think you'll find the build script will work fine, with not much modification - it's just you'll have to compile nearly all your Python versions, not just some of them - but that's just taking stuff out, and tweaking a bit.

@liath
Copy link
Contributor Author

liath commented Sep 23, 2021

Yeah it seems fine (talking about this one right?). Just feels weird because it'll be exactly duplicating the pypa images and then why bother producing new images?

@liath
Copy link
Contributor Author

liath commented Sep 23, 2021

Another option would be to just pull the official images. Which is probably where most musl packages produced here will end up being run

@matthew-brett
Copy link
Collaborator

I was thinking of https://github.com/multi-build/docker-images/tree/focal/docker - but any scripts that will build Pythons for you, or images where you have Python you can test on, will be good. The point is to have images that have different, newer kernels and libraries, than the baseline from the Manylinux build image, to test that the wheels work OK with these kernels and libraries, as well as the ones they were compiled for.

@mattip
Copy link
Collaborator

mattip commented Sep 23, 2021

Do you think it would be hard to make up another docker image like : https://github.com/multi-build/docker-images

I think that makes sense. A PR to add alpine x86_64, i686, and arm64 images would be nice. I wouldn't worry about the build time to create python from source, after all these images are built only whenever a python version is released.

PyPy is not available for alpine linux, so attempts to use multibuild with it should report an error early on.

@liath
Copy link
Contributor Author

liath commented Sep 28, 2021

Alright, so I've been noodling on this for a bit and I think this last commit is going to give the most relevant experience for end users. By using the official python images for this we get support for a whole range of versions that we don't have to maintain and more importantly, we get to test in one of the most likely environments users will be running in.

@liath
Copy link
Contributor Author

liath commented Sep 28, 2021

The default interface is very simple and does what is expected at least. I think alpine:latest is probably the most likely end environment but that would mean we could only test against the major versions Alpine ships. It is possible, and probably should be documented as such, to use DOCKER_TEST_IMAGE="alpine:latest" with something in the config.sh hooks like:

function install_run {
    # get latest pip as apk delivers too old a version of packaging if you use theirs
    if [ -f "/etc/alpine-release" ]; then
      apk add python3 wget
      ln -s $(which python3) /bin/python
      wget "https://bootstrap.pypa.io/get-pip.py"
      python get-pip.py
    fi

    # Copypaste from multibuild/common_utils.sh:install_run
    install_wheel
    mkdir tmp_for_test
    (cd tmp_for_test && run_tests)
}

@matthew-brett
Copy link
Collaborator

matthew-brett commented Sep 28, 2021 via email

@liath
Copy link
Contributor Author

liath commented Sep 28, 2021

That's just to use alpine:latest, the commit I pushed does the right thing without having to mess with hooks.

@liath
Copy link
Contributor Author

liath commented Sep 28, 2021

Building pythons shouldn't be hard but I feel it wouldn't be representative of the environments people actually use. Just from what I've seen at my orgs and how I use it, when people are using musl python they're using it in docker. If you need a version other than what Alpine ships, you're probably going to google it and get the official docker images. Only after everything else has failed would a normal user try to compile their own but even then they're likely to switch to one of the debian based official images and be done with it.

@liath
Copy link
Contributor Author

liath commented Oct 1, 2021

Tested this with cffi builds and I think it's ready for for others to poke at so moving it outta draft now. For the record, this is how I've been testing:

#!/usr/bin/env bash

WORK_DIR=$(mktemp -d)
pushd "$WORK_DIR" || exit

git clone https://github.com/liath/cffi-travis-wheel .
hg clone https://foss.heptapod.net/pypy/cffi
git clone https://github.com/liath/multibuild --branch musllinux

source multibuild/common_utils.sh
source multibuild/travis_linux_steps.sh

export MB_PYTHON_VERSION=3.6 MB_ML_LIBC="musllinux" MB_ML_VER="_1_1"

before_install && build_wheel cffi

rm -rf "$WORK_DIR"

@liath liath marked this pull request as ready for review October 1, 2021 18:23
Copy link
Collaborator

@matthew-brett matthew-brett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few first thoughts.

@@ -308,6 +313,7 @@ function build_wheel_cmd {
local repo_dir=${2:-$REPO_DIR}
[ -z "$repo_dir" ] && echo "repo_dir not defined" && exit 1
local wheelhouse=$(abspath ${WHEEL_SDIR:-wheelhouse})
mkdir -p "$wheelhouse"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this necessary? Did you get an error without it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, without it the wheel gets saved as a file at that path vs inside a folder.

@@ -2,6 +2,17 @@
# Install and test steps on Linux
set -e

# shim for python:alpine not having bash
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the kind of thing that really should go in the test image, not in the invocation script. Does sh / ash not work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should but I was trying to go for as small a patch as possible instead of running around tweaking every script

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right - but the point is, here we have stuff which should be in the test image, and because it's not, it add maintenance burden to the multibuild code, as the reviewer tries to work out what it is about the test image you are trying to fix.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, bash should be in the test image? Does multibuild assume /bin/sh is bash?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it required in the build image as well? Then the fix should be in pypya/manylinux. If it is only the test image, it should be fixed in multi-build/docker-images

@@ -132,5 +140,6 @@ function install_run {
-e MANYLINUX_URL="$MANYLINUX_URL" \
-e TEST_DEPENDS="$TEST_DEPENDS" \
-v $PWD:/io \
--entrypoint sh \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again - I think this should go in the test image itself. It should set its default entrypoint.

@matthew-brett
Copy link
Collaborator

@liath - there is now a docker test image for Alpine - it should soon be available at https://hub.docker.com/u/multibuild - it's being built now. Can you refactor to use that? Or would you like me to take this over?

@mattip
Copy link
Collaborator

mattip commented Oct 13, 2021

The image is up, but the name focal_alpine feels weird
xref multi-build/docker-images#21.

@liath
Copy link
Contributor Author

liath commented Oct 22, 2021

I still maintain that testing in the images people will be running these wheels on is the better solution, but I've switched to your test image as requested.

For the record, the hassle of installing bash on python:alpine gets you images that are:

  • exactly the same image where the wheels you're testing will likely run because they're the official images
  • updated weekly
  • available at any version of python with-in recent history
  • available for every platform that alpine runs on
  • you don't have to do a thing to manage

@liath
Copy link
Contributor Author

liath commented Oct 25, 2021

Heck, if the shim is the issue we could just build from the official image inline with something like this in travis_linux_steps.sh:

     local plat=${1:-${PLAT:-x86_64}}
     if [ -z "$DOCKER_TEST_IMAGE" ]; then
         if [ "$MB_ML_LIBC" == "musllinux" ]; then
-          local docker_image="multibuild/alpine3.14_$plat"
+          docker pull "python:$MB_PYTHON_VERSION-alpine"
+          local docker_image="multibuild_alpine:latest"
+          docker build -t "$docker_image" -f "$MULTIBUILD_DIR/alpine.Dockerfile" \
+            --build-arg "PYTHON_VERSION=$MB_PYTHON_VERSION"  .
         else
           local bitness=$([ "$plat" == i686 ] && echo 32 || echo 64)
           local docker_image="matthewbrett/trusty:$bitness"
+          docker pull $docker_image
         fi
     else
         # aarch64 is called arm64v8 in Ubuntu
         local plat_subst=$([ "$plat" == aarch64 ] && echo arm64v8 || echo $plat)
         local docker_image="${DOCKER_TEST_IMAGE/\{PLAT\}/$plat_subst}"
+        docker pull $docker_image
     fi
# Moved the `docker pull` around because we want to pull `python:alpine` not the inline image.
-    docker pull $docker_image
     docker run --rm \
         -e PYTHON_VERSION="$MB_PYTHON_VERSION" \
         -e MB_PYTHON_VERSION="$MB_PYTHON_VERSION" \

And alpine.Dockerfile:

ARG PYTHON_VERSION="3.9"
FROM python:$PYTHON_VERSION-alpine

RUN apk update && apk add bash
ENTRYPOINT ["bash"]

@mattip
Copy link
Collaborator

mattip commented Mar 16, 2022

Is this waiting for more review? The NumPy builds use openblas compiled using multibuild, so in order to get numpy musl wheels we need musl support in multibuild.

@matthew-brett
Copy link
Collaborator

Looks good to me - let's get it in.

@matthew-brett matthew-brett merged commit 4b6eb06 into multi-build:devel Mar 16, 2022
@liath liath deleted the musllinux branch March 19, 2022 06:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants