Distribution & Standalone Wheels¶
This page explains how maya-py is packaged so it installs on machines with a
very old C++ compiler — or none at all. It's aimed at maintainers and the
curious. (Users: see the install instructions —
it's on PyPI, so pip install maya-py is all you need.)
The constraint¶
maya is C++26 by default, and the library features it leans on
(std::expected, std::format, views::enumerate, deducing-this) need a
recent standard library: GCC 14 or Clang 19. (Clang 18 nominally has
the language features, but its bundled libstdc++ <expected> support is
incomplete and fails to compile maya — Clang 19 is the real floor.) That's
newer than what old user machines have, so "compile on the user's old machine"
isn't the plan.
The answer is to not compile on the user's machine at all. maya-py ships
prebuilt binary wheels: a modern machine compiles everything once, into a
.whl that contains the finished .so. The user's machine just unzips it.
What makes the wheel standalone¶
A precompiled .so can still fail to load on an old machine if it needs
runtime libraries the old system doesn't have. Two things prevent that:
1. Static C++ runtime¶
A C++23 binary built with a modern GCC pulls in newer libstdc++ symbols
(GLIBCXX_3.4.3x). An old system libstdc++ won't have them. So the
extension is built with:
(see MAYA_PY_STATIC_CXX in CMakeLists.txt). The .so then carries its own
C++ runtime and links only libc / libm:
No libstdc++, no libgcc_s. The host's C++ toolchain is irrelevant.
2. Old-glibc build (manylinux)¶
libc itself can't be statically linked safely (it breaks dlopen/NSS), so
the binary still needs a glibc at least as new as the one it was built
against. Building on a 2024 distro would demand GLIBC_2.38 (2023) — too new
for old machines.
The fix is manylinux: build inside a container with an old glibc. maya-py
uses manylinux_2_28 (AlmaLinux 8, glibc 2.28 / 2019), so the wheel runs
on any distro with glibc 2.28 or newer. auditwheel (run automatically by
cibuildwheel) stamps the resulting manylinux_2_28 platform tag.
The build pipeline¶
pyproject.toml's [tool.cibuildwheel] section drives it; the GitHub Actions
workflow .github/workflows/wheels.yml runs it on every vX.Y.Z tag.
maya-py tracks the latest maya — CMakeLists.txt fetches master rather
than a frozen commit, so each tagged wheel bundles whatever maya is current at
build time. The guard against an upstream render change sneaking in is the
golden snapshot (tests/golden.txt, checked by scripts/check_golden.py in
CI); regenerate it with --update and commit the visual diff when maya changes
output on purpose.
The one wrinkle is the compiler: the manylinux_2_28 image (AlmaLinux 8)
ships gcc-toolset-14, which is exactly what maya-py needs (C++23). So
scripts/cibw_before_all.sh simply enables that toolset inside the container
and symlinks its gcc/g++ into /usr/local/bin before the build:
- default (
MAYA_PY_GCC_BUILD=0, what CI uses) → enablegcc-toolset-14. MAYA_PY_GCC_BUILD=1→ build a newer GCC from source (slow, ~30-60 min) — an escape hatch, not normally needed.
Releasing¶
The wheels workflow then:
- enables
gcc-toolset-14and builds the wheel insidemanylinux_2_28for each CPython (3.9–3.14), - runs
auditwheelto tag + bundle, - builds the Windows (x64) and macOS (Apple Silicon / arm64) wheels and the sdist,
- attaches all artifacts to the GitHub Release (the
releasejob hascontents: write, so this is automatic), - publishes to PyPI via Trusted Publishing (OIDC, no stored token) —
gated on the Linux + Windows + macOS builds, with
skip-existingso re-tagging a version is safe.
All three platforms (Linux, Windows, macOS arm64) build in the same matrix and
gate the publish. macOS builds with Homebrew GCC — pip / cibuildwheel
auto-picks it via the pre-project() block in CMakeLists.txt, since
AppleClang lags upstream LLVM on the C++23/26 bits maya uses.
Users just pip install maya-py; pip picks the matching wheel automatically.
The source-build fallback¶
If pip can't find a matching wheel (a Python/platform CI didn't cover), it
builds the sdist. On an old compiler that would fail deep inside maya's
templates, so CMakeLists.txt does a preflight check: if GCC < 14 (or
Clang < 19), it aborts immediately with an actionable message pointing the
user back to the prebuilt wheel.
Platform status¶
| Platform | Wheel | Notes |
|---|---|---|
| Linux x86-64 | ✅ via CI | manylinux_2_28, glibc ≥ 2.28, CPython 3.9–3.14 |
| Windows x64 | ✅ via CI | VS 2022 (MSVC), UCRT-linked, CPython 3.9–3.14 |
| macOS arm64 | ✅ via CI | Apple Silicon, Homebrew GCC, CPython 3.9–3.14 |
| Linux aarch64 | ⚙️ configured | same image; slower CI (emulated/native) |
| musl (Alpine) | ❌ skipped | maya's toolchain story on musl is untested |
Summary¶
- Users:
pip install maya-py— precompiled on Linux, Windows, and macOS (Apple Silicon), no compiler, works on old machines. - The
.sois self-contained (static C++ runtime, old-glibc target). - Source builds need GCC 14+ / Clang 19+, and say so clearly if your compiler is too old.