diff --git a/README.md b/README.md index 237796812..fa036e7cd 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,11 @@ Let's get started. ### Install from PyPI > **Supported platform: Linux x86-64 only.** The published `aiconfigurator` wheel -> bundles a native (Rust/PyO3) extension and is built for `linux_x86_64`. macOS, -> Windows, and other architectures (including Linux aarch64) are **not supported** -> and have no published release wheels — `pip3 install aiconfigurator` will not -> find a compatible wheel there. Please install from source for non-Linux platforms. +> bundles a native (Rust/PyO3) extension and is built as a `manylinux_2_28_x86_64` +> wheel (Linux x86-64, glibc >= 2.28). macOS, Windows, and other architectures +> (including Linux aarch64) are **not supported** and have no published release +> wheels — `pip3 install aiconfigurator` will not find a compatible wheel there. +> Please install from source for non-Linux platforms. ```bash pip3 install aiconfigurator diff --git a/docker/Dockerfile b/docker/Dockerfile index ab8198b65..75d706b8b 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -15,14 +15,34 @@ RUN mkdir /opt/aiconfigurator && \ ENV PATH="${VIRTUAL_ENV}/bin:${PATH}" ENV MPLCONFIGDIR=/tmp/matplotlib -FROM base AS build -# The `aiconfigurator` wheel owns the Rust extension, SDK/data payload, CLI, -# generator, webapp, and Spica packages. Maturin needs the Rust crate sources, -# a C linker (gcc), and ca-certificates so cargo can fetch crates from crates.io -# over TLS. Rust itself is bootstrapped by maturin's build backend. -RUN apt-get update && \ - apt-get install -y --no-install-recommends ca-certificates gcc libc6-dev && \ - rm -rf /var/lib/apt/lists/* +# The `aiconfigurator` wheel (Rust extension + SDK/data payload + CLI, generator, +# webapp, Spica) is built in the PyPA manylinux_2_28 image so the native PyO3 +# `.so` links glibc 2.28 and maturin's auditwheel stamps the portable +# `manylinux_2_28_` tag. We add `uv` and a rustup toolchain so cargo can +# fetch crates over TLS. +# +# TARGETARCH (amd64/arm64) selects the base per `--platform`; only the matching +# stage builds. aarch64: `docker build --platform linux/arm64 --target build .`. +FROM quay.io/pypa/manylinux_2_28_x86_64 AS manylinux-amd64 +FROM quay.io/pypa/manylinux_2_28_aarch64 AS manylinux-arm64 +ARG TARGETARCH +FROM manylinux-${TARGETARCH} AS build +WORKDIR /workspace +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ + +ENV RUSTUP_HOME=/opt/rust/rustup \ + CARGO_HOME=/opt/rust/cargo \ + PATH=/opt/rust/cargo/bin:${PATH} +# Download to disk (not `curl | sh`, which hides a failed download behind sh's +# exit status); pin the toolchain for reproducible release wheels. +RUN curl --proto '=https' --tlsv1.2 -sSf --retry 5 --retry-connrefused --retry-delay 2 \ + https://sh.rustup.rs -o /tmp/rustup-init.sh \ + && sh /tmp/rustup-init.sh -y --profile minimal --default-toolchain 1.96.0 \ + && rm /tmp/rustup-init.sh + +# Pin to the image's CPython 3.12 so uv/maturin never fetch a standalone one. +ENV UV_PYTHON=/opt/python/cp312-cp312/bin/python3 + COPY src/ /workspace/src/ COPY rust/ /workspace/rust/ COPY LICENSE pyproject.toml README.md /workspace/ @@ -37,8 +57,12 @@ RUN set -e; \ echo "Run 'git lfs install && git lfs pull' in the source tree before building." >&2; \ exit 1; \ fi -RUN uv build --wheel --out-dir /workspace/dist && \ - python tools/verify_release_wheels.py /workspace/dist +# `uv build` runs maturin's PEP517 backend, which defaults to `--compatibility +# off`; MATURIN_PEP517_ARGS overrides it to stamp the manylinux_2_28 tag (maturin +# appends it last, so it wins). `python` isn't on PATH here -> verify via UV_PYTHON. +RUN MATURIN_PEP517_ARGS="--compatibility manylinux_2_28" \ + uv build --wheel --out-dir /workspace/dist && \ + "${UV_PYTHON}" tools/verify_release_wheels.py /workspace/dist FROM base AS runtime COPY --from=build /workspace/dist /wheelhouse diff --git a/pyproject.toml b/pyproject.toml index 24dd583b7..d0d86487d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -97,7 +97,9 @@ GitHub = "https://github.com/ai-dynamo/aiconfigurator" Repository = "https://github.com/ai-dynamo/aiconfigurator.git" [build-system] -requires = ["maturin>=1.5,<2"] +# >=1.5.1 fixed `--compatibility` under the PEP517 backend, which the +# manylinux_2_28 wheel build relies on (see docker/Dockerfile). +requires = ["maturin>=1.5.1,<2"] build-backend = "maturin" [project.scripts]