diff --git a/bin/update_docker.py b/bin/update_docker.py index e090f3f0f..9217e7596 100755 --- a/bin/update_docker.py +++ b/bin/update_docker.py @@ -20,55 +20,69 @@ class Image: tag: str | None # Set this to pin the image +class PyPAImage(Image): + def __init__(self, manylinux_version: str, platform: str, tag: str | None): + platform_no_pypy = platform[5:] if platform.startswith("pypy_") else platform + image_name = f"quay.io/pypa/{manylinux_version}_{platform_no_pypy}" + super().__init__(manylinux_version, platform, image_name, tag) + + images = [ - # manylinux1 images - Image("manylinux1", "x86_64", "quay.io/pypa/manylinux1_x86_64", None), - Image("manylinux1", "i686", "quay.io/pypa/manylinux1_i686", None), - # manylinux2010 images - Image("manylinux2010", "x86_64", "quay.io/pypa/manylinux2010_x86_64", None), - Image("manylinux2010", "i686", "quay.io/pypa/manylinux2010_i686", None), - Image("manylinux2010", "pypy_x86_64", "quay.io/pypa/manylinux2010_x86_64", None), - Image("manylinux2010", "pypy_i686", "quay.io/pypa/manylinux2010_i686", None), + # manylinux1 images, EOL -> use tag + PyPAImage("manylinux1", "x86_64", "2024-04-29-76807b8"), + PyPAImage("manylinux1", "i686", "2024-04-29-76807b8"), + # manylinux2010 images, EOL -> use tag + PyPAImage("manylinux2010", "x86_64", "2022-08-05-4535177"), + PyPAImage("manylinux2010", "i686", "2022-08-05-4535177"), + PyPAImage("manylinux2010", "pypy_x86_64", "2022-08-05-4535177"), + PyPAImage("manylinux2010", "pypy_i686", "2022-08-05-4535177"), # manylinux2014 images - Image("manylinux2014", "x86_64", "quay.io/pypa/manylinux2014_x86_64", None), - Image("manylinux2014", "i686", "quay.io/pypa/manylinux2014_i686", None), - Image("manylinux2014", "aarch64", "quay.io/pypa/manylinux2014_aarch64", None), - Image("manylinux2014", "ppc64le", "quay.io/pypa/manylinux2014_ppc64le", None), - Image("manylinux2014", "s390x", "quay.io/pypa/manylinux2014_s390x", None), - Image("manylinux2014", "pypy_x86_64", "quay.io/pypa/manylinux2014_x86_64", None), - Image("manylinux2014", "pypy_i686", "quay.io/pypa/manylinux2014_i686", None), - Image("manylinux2014", "pypy_aarch64", "quay.io/pypa/manylinux2014_aarch64", None), - # manylinux_2_24 images - Image("manylinux_2_24", "x86_64", "quay.io/pypa/manylinux_2_24_x86_64", None), - Image("manylinux_2_24", "i686", "quay.io/pypa/manylinux_2_24_i686", None), - Image("manylinux_2_24", "aarch64", "quay.io/pypa/manylinux_2_24_aarch64", None), - Image("manylinux_2_24", "ppc64le", "quay.io/pypa/manylinux_2_24_ppc64le", None), - Image("manylinux_2_24", "s390x", "quay.io/pypa/manylinux_2_24_s390x", None), - Image("manylinux_2_24", "pypy_x86_64", "quay.io/pypa/manylinux_2_24_x86_64", None), - Image("manylinux_2_24", "pypy_i686", "quay.io/pypa/manylinux_2_24_i686", None), - Image("manylinux_2_24", "pypy_aarch64", "quay.io/pypa/manylinux_2_24_aarch64", None), + PyPAImage("manylinux2014", "x86_64", None), + PyPAImage("manylinux2014", "i686", None), + PyPAImage("manylinux2014", "aarch64", None), + PyPAImage("manylinux2014", "ppc64le", None), + PyPAImage("manylinux2014", "s390x", None), + PyPAImage("manylinux2014", "pypy_x86_64", None), + PyPAImage("manylinux2014", "pypy_i686", None), + PyPAImage("manylinux2014", "pypy_aarch64", None), + # manylinux_2_24 images, EOL -> use tag + PyPAImage("manylinux_2_24", "x86_64", "2022-12-26-0d38463"), + PyPAImage("manylinux_2_24", "i686", "2022-12-26-0d38463"), + PyPAImage("manylinux_2_24", "aarch64", "2022-12-26-0d38463"), + PyPAImage("manylinux_2_24", "ppc64le", "2022-12-26-0d38463"), + PyPAImage("manylinux_2_24", "s390x", "2022-12-26-0d38463"), + PyPAImage("manylinux_2_24", "pypy_x86_64", "2022-12-26-0d38463"), + PyPAImage("manylinux_2_24", "pypy_i686", "2022-12-26-0d38463"), + PyPAImage("manylinux_2_24", "pypy_aarch64", "2022-12-26-0d38463"), # manylinux_2_28 images - Image("manylinux_2_28", "x86_64", "quay.io/pypa/manylinux_2_28_x86_64", None), - Image("manylinux_2_28", "aarch64", "quay.io/pypa/manylinux_2_28_aarch64", None), - Image("manylinux_2_28", "ppc64le", "quay.io/pypa/manylinux_2_28_ppc64le", None), - Image("manylinux_2_28", "s390x", "quay.io/pypa/manylinux_2_28_s390x", None), - Image("manylinux_2_28", "pypy_x86_64", "quay.io/pypa/manylinux_2_28_x86_64", None), - Image("manylinux_2_28", "pypy_aarch64", "quay.io/pypa/manylinux_2_28_aarch64", None), + PyPAImage("manylinux_2_28", "x86_64", None), + PyPAImage("manylinux_2_28", "aarch64", None), + PyPAImage("manylinux_2_28", "ppc64le", None), + PyPAImage("manylinux_2_28", "s390x", None), + PyPAImage("manylinux_2_28", "pypy_x86_64", None), + PyPAImage("manylinux_2_28", "pypy_aarch64", None), # manylinux_2_31 images Image("manylinux_2_31", "armv7l", "ghcr.io/mayeut/manylinux_2_31", None), - # musllinux_1_1 images - Image("musllinux_1_1", "x86_64", "quay.io/pypa/musllinux_1_1_x86_64", None), - Image("musllinux_1_1", "i686", "quay.io/pypa/musllinux_1_1_i686", None), - Image("musllinux_1_1", "aarch64", "quay.io/pypa/musllinux_1_1_aarch64", None), - Image("musllinux_1_1", "ppc64le", "quay.io/pypa/musllinux_1_1_ppc64le", None), - Image("musllinux_1_1", "s390x", "quay.io/pypa/musllinux_1_1_s390x", None), + # manylinux_2_34 images + PyPAImage("manylinux_2_34", "x86_64", None), + PyPAImage("manylinux_2_34", "aarch64", None), + PyPAImage("manylinux_2_34", "ppc64le", None), + PyPAImage("manylinux_2_34", "s390x", None), + PyPAImage("manylinux_2_34", "pypy_x86_64", None), + PyPAImage("manylinux_2_34", "pypy_aarch64", None), + # musllinux_1_1 images, EOL -> use tag + PyPAImage("musllinux_1_1", "x86_64", "2024.10.26-1"), + PyPAImage("musllinux_1_1", "i686", "2024.10.26-1"), + PyPAImage("musllinux_1_1", "aarch64", "2024.10.26-1"), + PyPAImage("musllinux_1_1", "ppc64le", "2024.10.26-1"), + PyPAImage("musllinux_1_1", "s390x", "2024.10.26-1"), # musllinux_1_2 images - Image("musllinux_1_2", "x86_64", "quay.io/pypa/musllinux_1_2_x86_64", None), - Image("musllinux_1_2", "i686", "quay.io/pypa/musllinux_1_2_i686", None), - Image("musllinux_1_2", "aarch64", "quay.io/pypa/musllinux_1_2_aarch64", None), - Image("musllinux_1_2", "ppc64le", "quay.io/pypa/musllinux_1_2_ppc64le", None), - Image("musllinux_1_2", "s390x", "quay.io/pypa/musllinux_1_2_s390x", None), - Image("musllinux_1_2", "armv7l", "quay.io/pypa/musllinux_1_2_armv7l", None), + PyPAImage("musllinux_1_2", "x86_64", None), + PyPAImage("musllinux_1_2", "i686", None), + PyPAImage("musllinux_1_2", "aarch64", None), + PyPAImage("musllinux_1_2", "ppc64le", None), + PyPAImage("musllinux_1_2", "s390x", None), + PyPAImage("musllinux_1_2", "armv7l", None), ] config = configparser.ConfigParser() diff --git a/cibuildwheel/resources/pinned_docker_images.cfg b/cibuildwheel/resources/pinned_docker_images.cfg index 063b5b54d..06c827634 100644 --- a/cibuildwheel/resources/pinned_docker_images.cfg +++ b/cibuildwheel/resources/pinned_docker_images.cfg @@ -4,6 +4,7 @@ manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-08-05-4535177 manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2024.11.24-1 manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2022-12-26-0d38463 manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2024.11.24-1 +manylinux_2_34 = quay.io/pypa/manylinux_2_34_x86_64:2024.11.24-1 musllinux_1_1 = quay.io/pypa/musllinux_1_1_x86_64:2024.10.26-1 musllinux_1_2 = quay.io/pypa/musllinux_1_2_x86_64:2024.11.24-1 @@ -20,6 +21,7 @@ manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-08-05-4535177 manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2024.11.24-1 manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2022-12-26-0d38463 manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2024.11.24-1 +manylinux_2_34 = quay.io/pypa/manylinux_2_34_x86_64:2024.11.24-1 [pypy_i686] manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-08-05-4535177 @@ -30,6 +32,7 @@ manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-12-26-0d38463 manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2024.11.24-1 manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-12-26-0d38463 manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2024.11.24-1 +manylinux_2_34 = quay.io/pypa/manylinux_2_34_aarch64:2024.11.24-1 musllinux_1_1 = quay.io/pypa/musllinux_1_1_aarch64:2024.10.26-1 musllinux_1_2 = quay.io/pypa/musllinux_1_2_aarch64:2024.11.24-1 @@ -37,6 +40,7 @@ musllinux_1_2 = quay.io/pypa/musllinux_1_2_aarch64:2024.11.24-1 manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2024.11.24-1 manylinux_2_24 = quay.io/pypa/manylinux_2_24_ppc64le:2022-12-26-0d38463 manylinux_2_28 = quay.io/pypa/manylinux_2_28_ppc64le:2024.11.24-1 +manylinux_2_34 = quay.io/pypa/manylinux_2_34_ppc64le:2024.11.24-1 musllinux_1_1 = quay.io/pypa/musllinux_1_1_ppc64le:2024.10.26-1 musllinux_1_2 = quay.io/pypa/musllinux_1_2_ppc64le:2024.11.24-1 @@ -44,6 +48,7 @@ musllinux_1_2 = quay.io/pypa/musllinux_1_2_ppc64le:2024.11.24-1 manylinux2014 = quay.io/pypa/manylinux2014_s390x:2024.11.24-1 manylinux_2_24 = quay.io/pypa/manylinux_2_24_s390x:2022-12-26-0d38463 manylinux_2_28 = quay.io/pypa/manylinux_2_28_s390x:2024.11.24-1 +manylinux_2_34 = quay.io/pypa/manylinux_2_34_s390x:2024.11.24-1 musllinux_1_1 = quay.io/pypa/musllinux_1_1_s390x:2024.10.26-1 musllinux_1_2 = quay.io/pypa/musllinux_1_2_s390x:2024.11.24-1 @@ -51,6 +56,7 @@ musllinux_1_2 = quay.io/pypa/musllinux_1_2_s390x:2024.11.24-1 manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2024.11.24-1 manylinux_2_24 = quay.io/pypa/manylinux_2_24_aarch64:2022-12-26-0d38463 manylinux_2_28 = quay.io/pypa/manylinux_2_28_aarch64:2024.11.24-1 +manylinux_2_34 = quay.io/pypa/manylinux_2_34_aarch64:2024.11.24-1 [armv7l] manylinux_2_31 = ghcr.io/mayeut/manylinux_2_31:2024.11.24-1 diff --git a/docs/options.md b/docs/options.md index b150a0eda..a1452e17a 100644 --- a/docs/options.md +++ b/docs/options.md @@ -1211,14 +1211,14 @@ The available options are: Set the Docker image to be used for building [manylinux / musllinux](https://github.com/pypa/manylinux) wheels. For `CIBW_MANYLINUX_*_IMAGE`, except `CIBW_MANYLINUX_ARMV7L_IMAGE`, the value of this option can either be set to `manylinux1`, `manylinux2010`, `manylinux2014`, `manylinux_2_24` or `manylinux_2_28` to use a pinned version of the [official manylinux images](https://github.com/pypa/manylinux). Alternatively, set these options to any other valid Docker image name. For PyPy, the `manylinux1` image is not available. For architectures other -than x86 (x86\_64 and i686) `manylinux2014`, `manylinux_2_24` or `manylinux_2_28` must be used, because the first version of the manylinux specification that supports additional architectures is `manylinux2014`. `manylinux_2_28` is not supported for `i686` architecture. +than x86 (x86\_64 and i686) `manylinux2014`, `manylinux_2_24`, `manylinux_2_28` or `manylinux_2_34` must be used, because the first version of the manylinux specification that supports additional architectures is `manylinux2014`. `manylinux_2_28` and `manylinux_2_34` are not supported for `i686` architecture. For `CIBW_MANYLINUX_ARMV7L_IMAGE`, the value of this option can either be set to `manylinux_2_31` or a custom image. Support is experimental for now. The `manylinux_2_31` value is only available for `armv7`. For `CIBW_MUSLLINUX_*_IMAGE`, the value of this option can either be set to `musllinux_1_1` or `musllinux_1_2` to use a pinned version of the [official musllinux images](https://github.com/pypa/musllinux). Alternatively, set these options to any other valid Docker image name. If this option is blank, it will fall though to the next available definition (environment variable -> pyproject.toml -> default). -If setting a custom image, you'll need to make sure it can be used in the same way as the default images: all necessary Python and pip versions need to be present in `/opt/python/`, and the auditwheel tool needs to be present for cibuildwheel to work. Apart from that, the architecture and relevant shared system libraries need to be compatible to the relevant standard to produce valid manylinux1/manylinux2010/manylinux2014/manylinux_2_24/manylinux_2_28/musllinux_1_1/musllinux_1_2 wheels (see [pypa/manylinux on GitHub](https://github.com/pypa/manylinux), [PEP 513](https://www.python.org/dev/peps/pep-0513/), [PEP 571](https://www.python.org/dev/peps/pep-0571/), [PEP 599](https://www.python.org/dev/peps/pep-0599/), [PEP 600](https://www.python.org/dev/peps/pep-0600/) and [PEP 656](https://www.python.org/dev/peps/pep-0656/) for more details). +If setting a custom image, you'll need to make sure it can be used in the same way as the default images: all necessary Python and pip versions need to be present in `/opt/python/`, and the auditwheel tool needs to be present for cibuildwheel to work. Apart from that, the architecture and relevant shared system libraries need to be compatible to the relevant standard to produce valid manylinux1/manylinux2010/manylinux2014/manylinux_2_24/manylinux_2_28/manylinux_2_34/musllinux_1_1/musllinux_1_2 wheels (see [pypa/manylinux on GitHub](https://github.com/pypa/manylinux), [PEP 513](https://www.python.org/dev/peps/pep-0513/), [PEP 571](https://www.python.org/dev/peps/pep-0571/), [PEP 599](https://www.python.org/dev/peps/pep-0599/), [PEP 600](https://www.python.org/dev/peps/pep-0600/) and [PEP 656](https://www.python.org/dev/peps/pep-0656/) for more details). Auditwheel detects the version of the manylinux / musllinux standard in the image through the `AUDITWHEEL_PLAT` environment variable, as cibuildwheel has no way of detecting the correct `--plat` command line argument to pass to auditwheel for a custom image. If a custom image does not correctly set this `AUDITWHEEL_PLAT` environment variable, the `CIBW_ENVIRONMENT` option can be used to do so (e.g., `CIBW_ENVIRONMENT='AUDITWHEEL_PLAT="manylinux2010_$(uname -m)"'`). diff --git a/test/test_manylinuxXXXX_only.py b/test/test_manylinuxXXXX_only.py index 3bc6820fa..030ec88f9 100644 --- a/test/test_manylinuxXXXX_only.py +++ b/test/test_manylinuxXXXX_only.py @@ -15,6 +15,7 @@ #include #include #include + #include #if !defined(__GLIBC_PREREQ) #error "Must run on a glibc linux environment" @@ -31,9 +32,16 @@ ), spam_c_function_add=textwrap.dedent( r""" - #if __GLIBC_PREREQ(2, 28) + #if __GLIBC_PREREQ(2, 34) + // pthread_mutexattr_init was moved to libc.so.6 in manylinux_2_34+ + pthread_mutexattr_t attr; + sts = pthread_mutexattr_init(&attr); + if (sts == 0) { + pthread_mutexattr_destroy(&attr); + } + #elif __GLIBC_PREREQ(2, 28) // thrd_equal & thrd_current are only available in manylinux_2_28+ - sts = thrd_equal(thrd_current(), thrd_current()) ? 0 : 1;; + sts = thrd_equal(thrd_current(), thrd_current()) ? 0 : 1; #elif __GLIBC_PREREQ(2, 24) // nextupf is only available in manylinux_2_24+ sts = (int)nextupf(0.0F); @@ -51,17 +59,24 @@ @pytest.mark.parametrize( "manylinux_image", - ["manylinux1", "manylinux2010", "manylinux2014", "manylinux_2_24", "manylinux_2_28"], + [ + "manylinux1", + "manylinux2010", + "manylinux2014", + "manylinux_2_24", + "manylinux_2_28", + "manylinux_2_34", + ], ) @pytest.mark.usefixtures("docker_cleanup") def test(manylinux_image, tmp_path): if utils.platform != "linux": pytest.skip("the container image test is only relevant to the linux build") - elif platform.machine() not in ["x86_64", "i686"]: - if manylinux_image in ["manylinux1", "manylinux2010"]: - pytest.skip("manylinux1 and 2010 doesn't exist for non-x86 architectures") - elif manylinux_image == "manylinux_2_28" and platform.machine() == "i686": - pytest.skip("manylinux_2_28 doesn't exist for i686 architecture") + elif platform.machine() not in {"x86_64", "i686"}: + if manylinux_image in {"manylinux1", "manylinux2010"}: + pytest.skip(f"{manylinux_image} doesn't exist for non-x86 architectures") + elif manylinux_image in {"manylinux_2_28", "manylinux_2_34"} and platform.machine() == "i686": + pytest.skip(f"{manylinux_image} doesn't exist for i686 architecture") project_dir = tmp_path / "project" project_with_manylinux_symbols.generate(project_dir) @@ -90,8 +105,8 @@ def test(manylinux_image, tmp_path): if manylinux_image in {"manylinux_2_24"}: # We don't have a manylinux_2_24 image for PyPy 3.10+, CPython 3.12+ add_env["CIBW_SKIP"] = "pp31* cp312* cp313*" - if manylinux_image == "manylinux_2_28" and platform.machine() == "x86_64": - # We don't have a manylinux_2_28 image for i686 + if manylinux_image in {"manylinux_2_28", "manylinux_2_34"} and platform.machine() == "x86_64": + # We don't have a manylinux_2_28+ image for i686 add_env["CIBW_ARCHS"] = "x86_64" actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env) @@ -131,8 +146,8 @@ def test(manylinux_image, tmp_path): if "-pp31" not in w and "-cp312" not in w and "-cp313" not in w ] - if manylinux_image == "manylinux_2_28" and platform.machine() == "x86_64": - # We don't have a manylinux_2_28 image for i686 + if manylinux_image in {"manylinux_2_28", "manylinux_2_34"} and platform.machine() == "x86_64": + # We don't have a manylinux_2_28+ image for i686 expected_wheels = [w for w in expected_wheels if "i686" not in w] assert set(actual_wheels) == set(expected_wheels) diff --git a/unit_test/main_tests/main_options_test.py b/unit_test/main_tests/main_options_test.py index 849dbe3ba..fe3b21189 100644 --- a/unit_test/main_tests/main_options_test.py +++ b/unit_test/main_tests/main_options_test.py @@ -84,6 +84,7 @@ def test_empty_selector(monkeypatch): ("x86_64", "manylinux2014", "quay.io/pypa/manylinux2014_x86_64:*"), ("x86_64", "manylinux_2_24", "quay.io/pypa/manylinux_2_24_x86_64:*"), ("x86_64", "manylinux_2_28", "quay.io/pypa/manylinux_2_28_x86_64:*"), + ("x86_64", "manylinux_2_34", "quay.io/pypa/manylinux_2_34_x86_64:*"), ("x86_64", "custom_image", "custom_image"), ("i686", None, "quay.io/pypa/manylinux2014_i686:*"), ("i686", "manylinux1", "quay.io/pypa/manylinux1_i686:*"), @@ -97,6 +98,7 @@ def test_empty_selector(monkeypatch): ("pypy_x86_64", "manylinux2014", "quay.io/pypa/manylinux2014_x86_64:*"), ("pypy_x86_64", "manylinux_2_24", "quay.io/pypa/manylinux_2_24_x86_64:*"), ("pypy_x86_64", "manylinux_2_28", "quay.io/pypa/manylinux_2_28_x86_64:*"), + ("pypy_x86_64", "manylinux_2_34", "quay.io/pypa/manylinux_2_34_x86_64:*"), ("pypy_x86_64", "custom_image", "custom_image"), ], )