CI: stop recompiling pyo3 on every run (pin PYO3_CONFIG_FILE in tests sessions)#14968
Closed
alex wants to merge 3 commits into
Closed
CI: stop recompiling pyo3 on every run (pin PYO3_CONFIG_FILE in tests sessions)#14968alex wants to merge 3 commits into
alex wants to merge 3 commits into
Conversation
64a9214 to
b94f4cf
Compare
PEP 517 builds run in a randomly-named temporary environment, and PyO3's build script fingerprints the interpreter path it is given by maturin. That path changes on every CI run, which makes cargo recompile pyo3-build-config, pyo3-ffi, pyo3, pyo3-macros-backend, and pyo3-macros (and on Windows openssl-sys/openssl too) despite a warm rust-cache. Instead of disabling build isolation, resolve the PyO3 build config once per session -- against the session venv's interpreter, whose path is stable from run to run -- using pyo3's own discovery (PYO3_PRINT_CONFIG), and pin it via PYO3_CONFIG_FILE. PYO3_CONFIG_FILE takes priority over the PYO3_PYTHON that maturin points at the ephemeral build environment, so cached pyo3 artifacts stay fresh while the build itself remains fully isolated. The config file's name is content-addressed and its mtime pinned so that a regenerated-but-identical config doesn't trip cargo's rerun-if-changed, while a genuinely different config changes the PYO3_CONFIG_FILE value and correctly triggers a rebuild. The cache key is bumped so caches are re-saved with the new fingerprints (rust-cache does not re-save on a primary key hit). https://claude.ai/code/session_014StKTjk7GBcVdiWKimEsQb
b94f4cf to
67f3427
Compare
maturin also reads PYO3_CONFIG_FILE and treats it as the authoritative description of the target interpreter: it requires ext_suffix on Windows, and without abiflags it tags free-threaded wheels as regular CPython (cp314 instead of cp314t), which the installer then rejects. PyO3 itself ignores unknown config keys with a warning, so appending both is safe. https://claude.ai/code/session_014StKTjk7GBcVdiWKimEsQb
When PYO3_CONFIG_FILE is set, maturin doesn't export PYO3_PYTHON to cargo, so cryptography-cffi's build script fell back to 'python3' to run _cffi_src/build_openssl.py. On Windows that resolved to an interpreter without cffi (venvs there don't ship python3.exe), breaking all Windows jobs. Point PYO3_PYTHON at the session venv's interpreter -- a stable path, so no cache churn -- and install the build requirements into the session venv so that interpreter can run the cffi bridge script. The build itself still runs in an isolated environment. https://claude.ai/code/session_014StKTjk7GBcVdiWKimEsQb
Member
Author
|
Closing in favor of the upstream fix: maturin will export a Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
In the
tests*nox sessions, resolve the PyO3 build config once — against the session venv's interpreter, whose path is stable from run to run — and pin it viaPYO3_CONFIG_FILEfor the build of cryptography itself. Build isolation stays fully enabled. Bumps the shared rust cache key so caches get re-saved with the new fingerprints.(Earlier revision of this PR used
--no-build-isolation; reworked per review feedback.)Why
CI logs show every run recompiles
pyo3-build-config,pyo3-ffi,pyo3,pyo3-macros-backend, andpyo3-macros(and on Windows,openssl-sys/openssltoo) despite a rust-cache hit — e.g. this main run.Mechanism: PEP 517 builds run in a randomly-named temporary environment (
~/.cache/uv/builds-v0/.tmpXXXX), and maturin points PyO3 at that environment's interpreter viaPYO3_PYTHON. PyO3's build scripts emitcargo:rerun-if-env-changedfor the env vars they actually consult, and the resolved config embeds the interpreter path — so a different temp path every run dirties the whole chain.PYO3_CONFIG_FILEtakes priority overPYO3_PYTHON: when it's set, PyO3 never consults (and therefore never fingerprints) the volatile variables. We generate the config using pyo3's own discovery (PYO3_PRINT_CONFIG=1against the session interpreter), so it's correct across CPython/PyPy/free-threaded/Windows without hand-rolling sysconfig logic.Three details to make this work:
PYO3_CONFIG_FILEvalue and correctly triggers a rebuild;cargo:rerun-if-changed, which compares mtimes;ext_suffixandabiflagsare appended: maturin also readsPYO3_CONFIG_FILEas the authoritative target description — it requiresext_suffixon Windows and usesabiflagsfor the wheel tag (without it, free-threaded wheels get taggedcp314instead ofcp314tand the installer rejects them). PyO3 ignores unknown config keys with a warning, so appending both is safe.Verified locally
With a warm
target/, removing.noxentirely and re-runningnox -e tests-nocoverage --install-only:Compiling pyo3-build-config / pyo3-ffi / pyo3-macros-backend / pyo3 / pyo3-macros+ workspace crates, every timeFinished release [optimized] target(s) in 0.04s— zero recompilesAlso verified that churning
PYO3_PYTHON/VIRTUAL_ENVacross fake temp envs withPYO3_CONFIG_FILEset recompiles nothing in the pyo3 chain.Expected CI impact
Same as measured for the previous revision of this PR (warm run vs baseline): windows build step 1m48s → ~1m04s, the critical-path
windows (3.9, tests-nocoverage)job 6.4m → ~4.1m; linux saves the CPU of the pyo3 chain. The first run on each revision is cold (key bump); the following push demonstrates warm behavior.Behavior notes
session.run_install, so it executes duringnox --install-only(CI's "create env" step) and is skipped under--no-install(CI's "tests" step, where the build already exists).PYO3_PRINT_CONFIGcargo invocation is the documented mechanism for producing config files and costs a few seconds (cached dev-profile artifacts).nox -e flakepasses locally.https://claude.ai/code/session_014StKTjk7GBcVdiWKimEsQb
Generated by Claude Code