diff --git a/bin/update_docker.py b/bin/update_docker.py index 11c3de18d..3f23d75da 100755 --- a/bin/update_docker.py +++ b/bin/update_docker.py @@ -14,74 +14,45 @@ @dataclass(frozen=True) class Image: manylinux_version: str - platform: str + platforms: list[str] image_name: str - tag: str | None # Set this to pin the image + tag: str | None = None # Set this to pin the image + use_platform_suffix: bool = False class PyPAImage(Image): - def __init__(self, manylinux_version: str, platform: str, tag: str | None): - platform_no_pypy = platform.removeprefix("pypy_") - image_name = f"quay.io/pypa/{manylinux_version}_{platform_no_pypy}" - super().__init__(manylinux_version, platform, image_name, tag) + def __init__(self, manylinux_version: str, platforms: list[str], tag: str | None = None): + image_name = f"quay.io/pypa/{manylinux_version}" + super().__init__(manylinux_version, platforms, image_name, tag, True) images = [ - # 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 - 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"), + PyPAImage( + "manylinux2014", + [ + "x86_64", + "i686", + "aarch64", + "ppc64le", + "s390x", + "pypy_x86_64", + "pypy_i686", + "pypy_aarch64", + ], + ), # manylinux_2_28 images - 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), + PyPAImage( + "manylinux_2_28", ["x86_64", "aarch64", "ppc64le", "s390x", "pypy_x86_64", "pypy_aarch64"] + ), # manylinux_2_31 images - PyPAImage("manylinux_2_31", "armv7l", None), + PyPAImage("manylinux_2_31", ["armv7l"]), # 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"), + PyPAImage( + "manylinux_2_34", ["x86_64", "aarch64", "ppc64le", "s390x", "pypy_x86_64", "pypy_aarch64"] + ), # musllinux_1_2 images - 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), + PyPAImage("musllinux_1_2", ["x86_64", "i686", "aarch64", "ppc64le", "s390x", "armv7l"]), ] config = configparser.ConfigParser() @@ -137,10 +108,13 @@ def __init__(self, manylinux_version: str, platform: str, tag: str | None): ) tag_name = pinned_tag["name"] - if not config.has_section(image.platform): - config[image.platform] = {} - - config[image.platform][image.manylinux_version] = f"{image.image_name}:{tag_name}" + for platform in image.platforms: + if not config.has_section(platform): + config[platform] = {} + suffix = "" + if image.use_platform_suffix: + suffix = f"_{platform.removeprefix('pypy_')}" + config[platform][image.manylinux_version] = f"{image.image_name}{suffix}:{tag_name}" with open(RESOURCES / "pinned_docker_images.cfg", "w") as f: config.write(f) diff --git a/cibuildwheel/options.py b/cibuildwheel/options.py index fa7605343..5ab256232 100644 --- a/cibuildwheel/options.py +++ b/cibuildwheel/options.py @@ -673,10 +673,18 @@ def globals(self) -> GlobalOptions: ) def _check_pinned_image(self, value: str, pinned_images: Mapping[str, str]) -> None: - if ( - value in {"manylinux1", "manylinux2010", "manylinux_2_24", "musllinux_1_1"} - and value not in self._image_warnings - ): + error_set = {"manylinux1", "manylinux2010", "manylinux_2_24", "musllinux_1_1"} + warning_set: set[str] = set() + + if value in error_set: + msg = ( + f"cibuildwheel 3.x does not support the image {value!r}. Either upgrade to a " + "supported image or continue using the image by pinning it directly with" + " its full OCI registry '{:|@}'." + ) + raise errors.DeprecationError(msg) + + if value in warning_set and value not in self._image_warnings: self._image_warnings.add(value) msg = ( f"Deprecated image {value!r}. This value will not work" @@ -783,35 +791,29 @@ def _compute_build_options(self, identifier: str | None) -> BuildOptions: for build_platform in MANYLINUX_ARCHS: pinned_images = all_pinned_container_images[build_platform] - config_value = self.reader.get( f"manylinux-{build_platform}-image", ignore_empty=True ) - + self._check_pinned_image(config_value, pinned_images) if not config_value: # default to manylinux2014 image = pinned_images["manylinux2014"] elif config_value in pinned_images: - self._check_pinned_image(config_value, pinned_images) image = pinned_images[config_value] else: image = config_value - manylinux_images[build_platform] = image for build_platform in MUSLLINUX_ARCHS: pinned_images = all_pinned_container_images[build_platform] - config_value = self.reader.get(f"musllinux-{build_platform}-image") - + self._check_pinned_image(config_value, pinned_images) if not config_value: image = pinned_images["musllinux_1_2"] elif config_value in pinned_images: - self._check_pinned_image(config_value, pinned_images) image = pinned_images[config_value] else: image = config_value - musllinux_images[build_platform] = image container_engine_str = self.reader.get( diff --git a/cibuildwheel/resources/pinned_docker_images.cfg b/cibuildwheel/resources/pinned_docker_images.cfg index a4e2e2964..7edb7380f 100644 --- a/cibuildwheel/resources/pinned_docker_images.cfg +++ b/cibuildwheel/resources/pinned_docker_images.cfg @@ -1,60 +1,41 @@ [x86_64] -manylinux1 = quay.io/pypa/manylinux1_x86_64:2024-04-29-76807b8 -manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-08-05-4535177 manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2025.03.15-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:2025.03.15-1 manylinux_2_34 = quay.io/pypa/manylinux_2_34_x86_64:2025.03.15-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:2025.03.15-1 [i686] -manylinux1 = quay.io/pypa/manylinux1_i686:2024-04-29-76807b8 -manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-08-05-4535177 manylinux2014 = quay.io/pypa/manylinux2014_i686:2025.03.15-1 -manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-12-26-0d38463 -musllinux_1_1 = quay.io/pypa/musllinux_1_1_i686:2024.10.26-1 musllinux_1_2 = quay.io/pypa/musllinux_1_2_i686:2025.03.15-1 -[pypy_x86_64] -manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2022-08-05-4535177 -manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2025.03.15-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:2025.03.15-1 -manylinux_2_34 = quay.io/pypa/manylinux_2_34_x86_64:2025.03.15-1 - -[pypy_i686] -manylinux2010 = quay.io/pypa/manylinux2010_i686:2022-08-05-4535177 -manylinux2014 = quay.io/pypa/manylinux2014_i686:2025.03.15-1 -manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2022-12-26-0d38463 - [aarch64] manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2025.03.15-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:2025.03.15-1 manylinux_2_34 = quay.io/pypa/manylinux_2_34_aarch64:2025.03.15-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:2025.03.15-1 [ppc64le] manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2025.03.15-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:2025.03.15-1 manylinux_2_34 = quay.io/pypa/manylinux_2_34_ppc64le:2025.03.15-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:2025.03.15-1 [s390x] manylinux2014 = quay.io/pypa/manylinux2014_s390x:2025.03.15-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:2025.03.15-1 manylinux_2_34 = quay.io/pypa/manylinux_2_34_s390x:2025.03.15-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:2025.03.15-1 +[pypy_x86_64] +manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2025.03.15-1 +manylinux_2_28 = quay.io/pypa/manylinux_2_28_x86_64:2025.03.15-1 +manylinux_2_34 = quay.io/pypa/manylinux_2_34_x86_64:2025.03.15-1 + +[pypy_i686] +manylinux2014 = quay.io/pypa/manylinux2014_i686:2025.03.15-1 + [pypy_aarch64] manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2025.03.15-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:2025.03.15-1 manylinux_2_34 = quay.io/pypa/manylinux_2_34_aarch64:2025.03.15-1 diff --git a/docs/cpp_standards.md b/docs/cpp_standards.md index ac820300a..3b49481ee 100644 --- a/docs/cpp_standards.md +++ b/docs/cpp_standards.md @@ -7,10 +7,11 @@ title: Modern C++ standards Building Python wheels with modern C++ standards (C++11 and later) requires a few tricks. -## manylinux1 and C++14 -The past end-of-life `manylinux1` image (based on CentOS 5) contains a version of GCC and libstdc++ that only supports C++11 and earlier standards. There are however ways to compile wheels with the C++14 standard (and later): https://github.com/pypa/manylinux/issues/118 +## manylinux2014 and C++20 -`manylinux2010` and `manylinux2014` are newer and support all C++ standards (up to C++17). +The past end-of-life `manylinux2014` image (based on CentOS 7) contains a version of GCC and libstdc++ that only supports C++17 and earlier standards. + +`manylinux_2_28` are newer and support all C++ standards (up to C++20). ## macOS and deployment target versions diff --git a/docs/faq.md b/docs/faq.md index 7ef36636d..7ec410d59 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -10,7 +10,7 @@ title: Tips and tricks Linux wheels are built in [`manylinux`/`musllinux` containers](https://github.com/pypa/manylinux) to provide binary compatible wheels on Linux, according to [PEP 600](https://www.python.org/dev/peps/pep-0600/) / [PEP 656](https://www.python.org/dev/peps/pep-0656/). Because of this, when building with `cibuildwheel` on Linux, a few things should be taken into account: -- Programs and libraries are not installed on the CI runner host, but rather should be installed inside the container - using `yum` for `manylinux2010` or `manylinux2014`, `apt-get` for `manylinux_2_24`/`manylinux_2_31`, `dnf` for `manylinux_2_28` and `apk` for `musllinux_1_1` or `musllinux_1_2`, or manually. The same goes for environment variables that are potentially needed to customize the wheel building. +- Programs and libraries are not installed on the CI runner host, but rather should be installed inside the container - using `yum` for `manylinux2014`, `apt-get` for `manylinux_2_31`, `dnf` for `manylinux_2_28` and `apk` for `musllinux_1_1` or `musllinux_1_2`, or manually. The same goes for environment variables that are potentially needed to customize the wheel building. `cibuildwheel` supports this by providing the [`CIBW_ENVIRONMENT`](options.md#environment) and [`CIBW_BEFORE_ALL`](options.md#before-all) options to setup the build environment inside the running container. diff --git a/docs/options.md b/docs/options.md index 080c66bb8..a54a28007 100644 --- a/docs/options.md +++ b/docs/options.md @@ -158,19 +158,19 @@ which means it can be given multiple times. ```toml [tool.cibuildwheel] # Normal options, etc. -manylinux-x86_64-image = "manylinux2014" +manylinux-x86_64-image = "manylinux_2_34" [[tool.cibuildwheel.overrides]] select = "cp38-*" -manylinux-x86_64-image = "manylinux1" +manylinux-x86_64-image = "manylinux2014" [[tool.cibuildwheel.overrides]] select = "cp3{9,10}-*" -manylinux-x86_64-image = "manylinux2010" +manylinux-x86_64-image = "manylinux_2_28" ``` -This example will build CPython 3.8 wheels on manylinux1, CPython 3.9-3.10 -wheels on manylinux2010, and manylinux2014 wheels for any newer Python +This example will build CPython 3.8 wheels on manylinux2014, CPython 3.9-3.10 +wheels on manylinux_2_28, and manylinux_2_34 wheels for any newer Python (like 3.10). ```toml @@ -955,10 +955,9 @@ Platform-specific environment variables also available:
In configuration files, you can use a TOML array, and each line will be run sequentially - joined with `&&`. -Note that manylinux_2_24/manylinux_2_31 builds occur inside a debian derivative docker container, where -manylinux2010 and manylinux2014 builds occur inside a CentOS one. So for -`manylinux_2_24`/`manylinux_2_31` the `CIBW_BEFORE_ALL_LINUX` command must use `apt-get -y` -instead. +Note that manylinux_2_31 builds occur inside a debian derivative docker container, where +manylinux2014 builds occur inside a CentOS one. So for `manylinux_2_31` the `CIBW_BEFORE_ALL_LINUX` command +must use `apt-get -y` instead. ### `CIBW_BEFORE_BUILD` {: #before-build} > Execute a shell command preparing each wheel's build @@ -1191,17 +1190,18 @@ 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`, `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_*_IMAGE`, except `CIBW_MANYLINUX_ARMV7L_IMAGE`, the value of this option can either be set to `manylinux2014`, `manylinux_2_28` or `manylinux_2_34` 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. +`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. +For `CIBW_MUSLLINUX_*_IMAGE`, the value of this option can either be set to `musllinux_1_2` or a custom image. 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/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). +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 manylinux2014/manylinux_2_28/manylinux_2_34/musllinux_1_2 wheels (see [pypa/manylinux on GitHub](https://github.com/pypa/manylinux), [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)"'`). +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="manylinux2014_$(uname -m)"'`). !!! warning On x86_64, `manylinux_2_34` is using [x86-64-v2](https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels) target architecture. @@ -1224,50 +1224,38 @@ Auditwheel detects the version of the manylinux / musllinux standard in the imag !!! tab examples "Environment variables" ```yaml - # Build using the manylinux1 image to ensure manylinux1 wheels are produced - # Not setting PyPy to manylinux1, since there is no manylinux1 PyPy image. - CIBW_MANYLINUX_X86_64_IMAGE: manylinux1 - CIBW_MANYLINUX_I686_IMAGE: manylinux1 - # Build using the manylinux2014 image CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014 CIBW_MANYLINUX_I686_IMAGE: manylinux2014 CIBW_MANYLINUX_PYPY_X86_64_IMAGE: manylinux2014 CIBW_MANYLINUX_PYPY_I686_IMAGE: manylinux2014 - # Build using the latest manylinux2014 release, instead of the cibuildwheel - # pinned version - CIBW_MANYLINUX_X86_64_IMAGE: quay.io/pypa/manylinux2014_x86_64:latest - CIBW_MANYLINUX_I686_IMAGE: quay.io/pypa/manylinux2014_i686:latest - CIBW_MANYLINUX_PYPY_X86_64_IMAGE: quay.io/pypa/manylinux2014_x86_64:latest - CIBW_MANYLINUX_PYPY_I686_IMAGE: quay.io/pypa/manylinux2014_i686:latest + # Build using the latest manylinux2010 release + CIBW_MANYLINUX_X86_64_IMAGE: quay.io/pypa/manylinux2010_x86_64:latest + CIBW_MANYLINUX_I686_IMAGE: quay.io/pypa/manylinux2010_i686:latest + CIBW_MANYLINUX_PYPY_X86_64_IMAGE: quay.io/pypa/manylinux2010_x86_64:latest + CIBW_MANYLINUX_PYPY_I686_IMAGE: quay.io/pypa/manylinux2010_i686:latest # Build using a different image from the docker registry CIBW_MANYLINUX_X86_64_IMAGE: dockcross/manylinux-x64 CIBW_MANYLINUX_I686_IMAGE: dockcross/manylinux-x86 # Build musllinux wheels using the musllinux_1_1 image - CIBW_MUSLLINUX_X86_64_IMAGE: musllinux_1_1 - CIBW_MUSLLINUX_I686_IMAGE: musllinux_1_1 + CIBW_MUSLLINUX_X86_64_IMAGE: quay.io/pypa/musllinux_1_1_x86_64:latest + CIBW_MUSLLINUX_I686_IMAGE: quay.io/pypa/musllinux_1_1_i686:latest ``` !!! tab examples "pyproject.toml" ```toml [tool.cibuildwheel] - # Build using the manylinux1 image to ensure manylinux1 wheels are produced - # Not setting PyPy to manylinux1, since there is no manylinux1 PyPy image. - manylinux-x86_64-image = "manylinux1" - manylinux-i686-image = "manylinux1" - # Build using the manylinux2014 image manylinux-x86_64-image = "manylinux2014" manylinux-i686-image = "manylinux2014" manylinux-pypy_x86_64-image = "manylinux2014" manylinux-pypy_i686-image = "manylinux2014" - # Build using the latest manylinux2010 release, instead of the cibuildwheel - # pinned version + # Build using the latest manylinux2010 release manylinux-x86_64-image = "quay.io/pypa/manylinux2010_x86_64:latest" manylinux-i686-image = "quay.io/pypa/manylinux2010_i686:latest" manylinux-pypy_x86_64-image = "quay.io/pypa/manylinux2010_x86_64:latest" @@ -1278,8 +1266,8 @@ Auditwheel detects the version of the manylinux / musllinux standard in the imag manylinux-i686-image = "dockcross/manylinux-x86" # Build musllinux wheels using the musllinux_1_1 image - musllinux-x86_64-image = "musllinux_1_1" - musllinux-i686-image = "musllinux_1_1" + musllinux-x86_64-image = "quay.io/pypa/musllinux_1_1_x86_64:latest" + musllinux-i686-image = "quay.io/pypa/musllinux_1_1_i686:latest" ``` Like any other option, these can be placed in `[tool.cibuildwheel.linux]` diff --git a/test/test_container_images.py b/test/test_container_images.py index 60517a0f7..17626a2ef 100644 --- a/test/test_container_images.py +++ b/test/test_container_images.py @@ -11,7 +11,7 @@ import os # check that we're running in the correct docker image as specified in the - # environment options CIBW_MANYLINUX1_*_IMAGE + # environment options CIBW_MANYLINUX_*_IMAGE if "linux" in sys.platform and not os.path.exists("/dockcross"): raise Exception( "/dockcross directory not found. Is this test running in the correct docker image?" diff --git a/test/test_linux_python.py b/test/test_linux_python.py index c4e7f4e53..7c5f58a56 100644 --- a/test/test_linux_python.py +++ b/test/test_linux_python.py @@ -19,12 +19,14 @@ def test_python_exist(tmp_path, capfd): basic_project = test_projects.new_c_project() basic_project.generate(project_dir) + image = f"quay.io/pypa/manylinux2010_{machine}:2022-08-05-4535177" + with pytest.raises(subprocess.CalledProcessError): utils.cibuildwheel_run( project_dir, add_env={ - "CIBW_MANYLINUX_X86_64_IMAGE": "manylinux2010", - "CIBW_MANYLINUX_I686_IMAGE": "manylinux2010", + "CIBW_MANYLINUX_X86_64_IMAGE": image, + "CIBW_MANYLINUX_I686_IMAGE": image, "CIBW_BUILD": "cp3{10,11}-manylinux*", }, ) @@ -35,7 +37,6 @@ def test_python_exist(tmp_path, capfd): assert f" to build 'cp310-manylinux_{machine}'." not in captured.err message = ( "'/opt/python/cp311-cp311/bin/python' executable doesn't exist" - f" in image 'quay.io/pypa/manylinux2010_{machine}:2022-08-05-4535177'" - f" to build 'cp311-manylinux_{machine}'." + f" in image '{image}' to build 'cp311-manylinux_{machine}'." ) assert message in captured.err diff --git a/test/test_manylinuxXXXX_only.py b/test/test_manylinuxXXXX_only.py index 41e78ad3d..c8d2c6d99 100644 --- a/test/test_manylinuxXXXX_only.py +++ b/test/test_manylinuxXXXX_only.py @@ -19,7 +19,7 @@ #error "Must run on a glibc linux environment" #endif - #if !__GLIBC_PREREQ(2, 5) /* manylinux1 is glibc 2.5 */ + #if !__GLIBC_PREREQ(2, 17) /* manylinux2014 is glibc 2.17 */ #error "Must run on a glibc >= 2.5 linux environment" #endif @@ -46,9 +46,6 @@ #elif __GLIBC_PREREQ(2, 17) /* manylinux2014 is glibc 2.17 */ // secure_getenv is only available in manylinux2014+ sts = (int)(intptr_t)secure_getenv("NON_EXISTING_ENV_VARIABLE"); - #elif __GLIBC_PREREQ(2, 10) /* manylinux2010 is glibc 2.12 */ - // malloc_info is only available on manylinux2010+ - sts = malloc_info(0, stdout); #endif """ ), @@ -58,10 +55,7 @@ @pytest.mark.parametrize( "manylinux_image", [ - "manylinux1", - "manylinux2010", "manylinux2014", - "manylinux_2_24", "manylinux_2_28", "manylinux_2_34", ], @@ -70,9 +64,6 @@ 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(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") @@ -80,7 +71,7 @@ def test(manylinux_image, tmp_path): project_with_manylinux_symbols.generate(project_dir) # build the wheels - # CFLAGS environment variable is necessary to fail on 'malloc_info' (on manylinux1) during compilation/linking, + # CFLAGS environment variable is necessary to fail at build time, # rather than when dynamically loading the Python add_env = { "CIBW_BUILD": "*-manylinux*", @@ -94,15 +85,6 @@ def test(manylinux_image, tmp_path): "CIBW_MANYLINUX_PYPY_AARCH64_IMAGE": manylinux_image, "CIBW_MANYLINUX_PYPY_I686_IMAGE": manylinux_image, } - if manylinux_image == "manylinux1": - # We don't have a manylinux1 image for PyPy & CPython 3.10 and above - add_env["CIBW_SKIP"] = "pp* cp31*" - if manylinux_image == "manylinux2010": - # We don't have a manylinux2010 image for PyPy 3.9+, CPython 3.11+ - add_env["CIBW_SKIP"] = "pp39* pp31* cp311* cp312* cp313*" - if manylinux_image == "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 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" @@ -113,8 +95,6 @@ def test(manylinux_image, tmp_path): actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env) platform_tag_map = { - "manylinux1": ["manylinux_2_5", "manylinux1"], - "manylinux2010": ["manylinux_2_12", "manylinux2010"], "manylinux2014": ["manylinux_2_17", "manylinux2014"], } expected_wheels = utils.expected_wheels( @@ -123,29 +103,6 @@ def test(manylinux_image, tmp_path): manylinux_versions=platform_tag_map.get(manylinux_image, [manylinux_image]), musllinux_versions=[], ) - if manylinux_image == "manylinux1": - # remove PyPy & CPython 3.10 and above - expected_wheels = [w for w in expected_wheels if "-pp" not in w and "-cp31" not in w] - - if manylinux_image == "manylinux2010": - # remove PyPy 3.9+ & CPython 3.11 - expected_wheels = [ - w - for w in expected_wheels - if "-pp39" not in w - and "-pp31" not in w - and "-cp311" not in w - and "-cp312" not in w - and "-cp313" not in w - ] - - if manylinux_image == "manylinux_2_24": - # remove PyPy 3.10+ & CPython 3.11 and above - expected_wheels = [ - w - for w in expected_wheels - if "-pp31" not in w and "-cp312" not in w and "-cp313" not in w - ] 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 diff --git a/test/test_musllinux_X_Y_only.py b/test/test_musllinux_X_Y_only.py index 9438821a1..f8396aa6a 100644 --- a/test/test_musllinux_X_Y_only.py +++ b/test/test_musllinux_X_Y_only.py @@ -24,7 +24,7 @@ @pytest.mark.parametrize( "musllinux_image", - ["musllinux_1_1", "musllinux_1_2"], + ["musllinux_1_2"], ) @pytest.mark.usefixtures("docker_cleanup") def test(musllinux_image, tmp_path): @@ -36,12 +36,13 @@ def test(musllinux_image, tmp_path): # build the wheels add_env = { - "CIBW_SKIP": "*-manylinux* *_armv7l", + "CIBW_SKIP": "*-manylinux*", "CIBW_MUSLLINUX_X86_64_IMAGE": musllinux_image, "CIBW_MUSLLINUX_I686_IMAGE": musllinux_image, "CIBW_MUSLLINUX_AARCH64_IMAGE": musllinux_image, "CIBW_MUSLLINUX_PPC64LE_IMAGE": musllinux_image, "CIBW_MUSLLINUX_S390X_IMAGE": musllinux_image, + "CIBW_MUSLLINUX_ARMV7L_IMAGE": musllinux_image, } actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env, single_python=True) @@ -52,5 +53,4 @@ def test(musllinux_image, tmp_path): musllinux_versions=[musllinux_image], single_python=True, ) - expected_wheels = [w for w in expected_wheels if "armv7l" not in w] assert set(actual_wheels) == set(expected_wheels) diff --git a/test/test_testing.py b/test/test_testing.py index 4dfda9141..e7763447d 100644 --- a/test/test_testing.py +++ b/test/test_testing.py @@ -168,10 +168,6 @@ def test_failing_test(tmp_path): add_env={ "CIBW_TEST_REQUIRES": "pytest", "CIBW_TEST_COMMAND": f"{utils.invoke_pytest()} {{project}}/test", - # manylinux1 has a version of bash that's been shown to have - # problems with this, so let's check that. - "CIBW_MANYLINUX_I686_IMAGE": "manylinux1", - "CIBW_MANYLINUX_X86_64_IMAGE": "manylinux1", # CPython 3.8 when running on macOS arm64 is unusual. The build # always runs in x86_64, so the arm64 tests are not run. See # #1169 for reasons why. That means the build succeeds, which diff --git a/unit_test/main_tests/main_options_test.py b/unit_test/main_tests/main_options_test.py index 2aaebda43..a869d615f 100644 --- a/unit_test/main_tests/main_options_test.py +++ b/unit_test/main_tests/main_options_test.py @@ -80,24 +80,15 @@ def test_empty_selector(monkeypatch): ("architecture", "image", "full_image"), [ ("x86_64", None, "quay.io/pypa/manylinux2014_x86_64:*"), - ("x86_64", "manylinux1", "quay.io/pypa/manylinux1_x86_64:*"), - ("x86_64", "manylinux2010", "quay.io/pypa/manylinux2010_x86_64:*"), ("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:*"), - ("i686", "manylinux2010", "quay.io/pypa/manylinux2010_i686:*"), ("i686", "manylinux2014", "quay.io/pypa/manylinux2014_i686:*"), - ("i686", "manylinux_2_24", "quay.io/pypa/manylinux_2_24_i686:*"), ("i686", "custom_image", "custom_image"), ("pypy_x86_64", None, "quay.io/pypa/manylinux2014_x86_64:*"), - ("pypy_x86_64", "manylinux1", "manylinux1"), # Does not exist - ("pypy_x86_64", "manylinux2010", "quay.io/pypa/manylinux2010_x86_64:*"), ("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"), diff --git a/unit_test/oci_container_test.py b/unit_test/oci_container_test.py index 14c635b31..5acc9cc48 100644 --- a/unit_test/oci_container_test.py +++ b/unit_test/oci_container_test.py @@ -28,14 +28,8 @@ # for these tests we use manylinux2014 images, because they're available on # multi architectures and include python3.8 -DEFAULT_IMAGE_TEMPLATE = "quay.io/pypa/manylinux2014_{machine}:2023-09-04-0828984" +DEFAULT_IMAGE = "quay.io/pypa/manylinux2014:2025.03.08-1" pm = platform.machine() -if pm in {"x86_64", "ppc64le", "s390x"}: - DEFAULT_IMAGE = DEFAULT_IMAGE_TEMPLATE.format(machine=pm) -elif pm in {"aarch64", "arm64"}: - DEFAULT_IMAGE = DEFAULT_IMAGE_TEMPLATE.format(machine="aarch64") -else: - DEFAULT_IMAGE = "" DEFAULT_OCI_PLATFORM = { "AMD64": OCIPlatform.AMD64, "x86_64": OCIPlatform.AMD64, @@ -415,9 +409,7 @@ def test_create_args_volume(tmp_path: Path, container_engine: OCIContainerEngine ) with OCIContainer( - engine=container_engine, - image=DEFAULT_IMAGE, - oci_platform=DEFAULT_OCI_PLATFORM, + engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM ) as container: assert container.call(["cat", "/test_mount/test_file.txt"], capture_output=True) == "1234" @@ -497,9 +489,7 @@ def test_parse_engine_config(config, name, create_args, capsys): @pytest.mark.skipif(pm != "x86_64", reason="Only runs on x86_64") def test_enforce_32_bit(container_engine): with OCIContainer( - engine=container_engine, - image=DEFAULT_IMAGE_TEMPLATE.format(machine="i686"), - oci_platform=OCIPlatform.i386, + engine=container_engine, image=DEFAULT_IMAGE, oci_platform=OCIPlatform.i386 ) as container: assert container.call(["uname", "-m"], capture_output=True).strip() == "i686" container_args = subprocess.run( diff --git a/unit_test/option_prepare_test.py b/unit_test/option_prepare_test.py index 995048b2c..27b25377c 100644 --- a/unit_test/option_prepare_test.py +++ b/unit_test/option_prepare_test.py @@ -104,12 +104,11 @@ def test_build_with_override_launches(monkeypatch, tmp_path): musllinux-x86_64-image = "musllinux_1_2" enable = ["pypy", "cpython-freethreading"] -# Before Python 3.10, use manylinux2014, musllinux_1_1 +# Before Python 3.10, use manylinux2014 [[tool.cibuildwheel.overrides]] select = "cp3?-*" manylinux-x86_64-image = "manylinux2014" manylinux-i686-image = "manylinux2014" -musllinux-x86_64-image = "musllinux_1_1" [[tool.cibuildwheel.overrides]] select = "cp38-manylinux_x86_64" @@ -124,7 +123,7 @@ def test_build_with_override_launches(monkeypatch, tmp_path): build_in_container = typing.cast(mock.Mock, linux.build_in_container) - assert build_in_container.call_count == 7 + assert build_in_container.call_count == 6 kwargs = build_in_container.call_args_list[0][1] assert "quay.io/pypa/manylinux2014_x86_64" in kwargs["container"]["image"] @@ -188,25 +187,13 @@ def test_build_with_override_launches(monkeypatch, tmp_path): assert identifiers == {f"{x}-manylinux_i686" for x in ALL_IDS} kwargs = build_in_container.call_args_list[4][1] - assert "quay.io/pypa/musllinux_1_1_x86_64" in kwargs["container"]["image"] - assert kwargs["container"]["cwd"] == PurePosixPath("/project") - assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64 - - identifiers = {x.identifier for x in kwargs["platform_configs"]} - assert identifiers == { - f"{x}-musllinux_x86_64" for x in ALL_IDS & {"cp38", "cp39"} if "pp" not in x - } - - kwargs = build_in_container.call_args_list[5][1] assert "quay.io/pypa/musllinux_1_2_x86_64" in kwargs["container"]["image"] assert kwargs["container"]["cwd"] == PurePosixPath("/project") assert kwargs["container"]["oci_platform"] == OCIPlatform.AMD64 identifiers = {x.identifier for x in kwargs["platform_configs"]} - assert identifiers == { - f"{x}-musllinux_x86_64" for x in ALL_IDS - {"cp38", "cp39"} if "pp" not in x - } + assert identifiers == {f"{x}-musllinux_x86_64" for x in ALL_IDS if "pp" not in x} - kwargs = build_in_container.call_args_list[6][1] + kwargs = build_in_container.call_args_list[5][1] assert "quay.io/pypa/musllinux_1_2_i686" in kwargs["container"]["image"] assert kwargs["container"]["cwd"] == PurePosixPath("/project") assert kwargs["container"]["oci_platform"] == OCIPlatform.i386 diff --git a/unit_test/options_test.py b/unit_test/options_test.py index cbbdba596..5333d59e3 100644 --- a/unit_test/options_test.py +++ b/unit_test/options_test.py @@ -26,7 +26,7 @@ test-command = "pyproject" test-sources = ["test", "other dir"] -manylinux-x86_64-image = "manylinux1" +manylinux-x86_64-image = "manylinux_2_28" environment-pass = ["EXAMPLE_ENV"] @@ -36,7 +36,7 @@ [[tool.cibuildwheel.overrides]] select = "cp313-*" test-command = "pyproject-override" -manylinux-x86_64-image = "manylinux2014" +manylinux-x86_64-image = "manylinux_2_34" """ @@ -76,13 +76,13 @@ def test_options_1(tmp_path, monkeypatch): assert local.manylinux_images is not None assert local.test_command == "pyproject" assert local.test_sources == ["test", "other dir"] - assert local.manylinux_images["x86_64"] == pinned_x86_64_container_image["manylinux1"] + assert local.manylinux_images["x86_64"] == pinned_x86_64_container_image["manylinux_2_28"] local = options.build_options("cp313-manylinux_x86_64") assert local.manylinux_images is not None assert local.test_command == "pyproject-override" assert local.test_sources == ["test", "other dir"] - assert local.manylinux_images["x86_64"] == pinned_x86_64_container_image["manylinux2014"] + assert local.manylinux_images["x86_64"] == pinned_x86_64_container_image["manylinux_2_34"] def test_passthrough(tmp_path, monkeypatch): @@ -532,19 +532,22 @@ def test_dependency_versions_toml( @pytest.mark.parametrize( - ("image", "deprecated"), + ("image", "deprecated", "raises"), [ - ("manylinux1", True), - ("manylinux2010", True), - ("manylinux2014", False), - ("manylinux_2_24", True), - ("manylinux_2_28", False), - ("manylinux_2_34", False), - ("musllinux_1_1", True), - ("musllinux_1_2", False), + ("manylinux1", True, True), + ("manylinux2010", True, True), + ("manylinux2014", False, False), + ("manylinux_2_24", True, True), + ("manylinux_2_28", False, False), + ("manylinux_2_34", False, False), + ("musllinux_1_1", True, True), + ("musllinux_1_2", False, False), ], ) -def test_deprecated_image(image: str, deprecated: bool, capsys: pytest.CaptureFixture[str]) -> None: +def test_deprecated_image( + image: str, deprecated: bool, raises: bool, capsys: pytest.CaptureFixture[str] +) -> None: + assert not raises or deprecated args = CommandLineArguments.defaults() env = { "CIBW_ARCHS": "x86_64", @@ -552,7 +555,12 @@ def test_deprecated_image(image: str, deprecated: bool, capsys: pytest.CaptureFi "CIBW_MUSLLINUX_X86_64_IMAGE": image if image.startswith("musllinux") else "", } options = Options(platform="linux", command_line_arguments=args, env=env) - bo = options.build_options(None) + try: + bo = options.build_options(None) + assert not raises + except errors.DeprecationError: + assert raises + return images = bo.manylinux_images if image.startswith("manylinux") else bo.musllinux_images assert images is not None resolved_image = images["x86_64"] diff --git a/unit_test/options_toml_test.py b/unit_test/options_toml_test.py index 749ff4b50..03e125013 100644 --- a/unit_test/options_toml_test.py +++ b/unit_test/options_toml_test.py @@ -24,7 +24,7 @@ test-groups = ["three", "four"] test-sources = ["five", "six and seven"] -manylinux-x86_64-image = "manylinux1" +manylinux-x86_64-image = "manylinux_2_28" [tool.cibuildwheel.macos] test-requires = "else" @@ -67,7 +67,7 @@ def test_simple_settings(tmp_path, platform, fname): assert options_reader.get("test-extras", option_format=ListFormat(",")) == "one,two" assert options_reader.get("test-groups", option_format=ListFormat(" ")) == "three four" - assert options_reader.get("manylinux-x86_64-image") == "manylinux1" + assert options_reader.get("manylinux-x86_64-image") == "manylinux_2_28" assert options_reader.get("manylinux-i686-image") == "manylinux2014" with pytest.raises(OptionsReaderError):