From 87377876e2e2cc98cbd1e970942b9e9abaf3c161 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Thu, 18 Jun 2026 14:10:12 -0600 Subject: [PATCH] Set PYO3_PYTHON to run scripts for stable ABI builds --- src/compile.rs | 2 +- test-crates/pyo3-cffi-build-script/Cargo.lock | 132 ++++++++++++++++++ test-crates/pyo3-cffi-build-script/Cargo.toml | 11 ++ test-crates/pyo3-cffi-build-script/build.rs | 21 +++ test-crates/pyo3-cffi-build-script/src/lib.rs | 7 + tests/common/other.rs | 34 +++++ tests/run/integration.rs | 5 + 7 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 test-crates/pyo3-cffi-build-script/Cargo.lock create mode 100644 test-crates/pyo3-cffi-build-script/Cargo.toml create mode 100644 test-crates/pyo3-cffi-build-script/build.rs create mode 100644 test-crates/pyo3-cffi-build-script/src/lib.rs diff --git a/src/compile.rs b/src/compile.rs index 499a656b3..28711c9ac 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -895,7 +895,7 @@ fn configure_pyo3_env( // Setup `PYO3_CONFIG_FILE` if we are cross compiling for pyo3 bindings if let Some(interpreter) = python_interpreter { // Target python interpreter isn't runnable when cross compiling - if interpreter.runnable && !force_target_abi { + if interpreter.runnable { if bridge_model.is_pyo3() { debug!( "Setting PYO3_PYTHON to {}", diff --git a/test-crates/pyo3-cffi-build-script/Cargo.lock b/test-crates/pyo3-cffi-build-script/Cargo.lock new file mode 100644 index 000000000..1c6ff40cb --- /dev/null +++ b/test-crates/pyo3-cffi-build-script/Cargo.lock @@ -0,0 +1,132 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pyo3" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd274650b21d4bfc26a0a47587962c1edb425f69287324355cd040c3ea66071c" +dependencies = [ + "libc", + "once_cell", + "portable-atomic", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", +] + +[[package]] +name = "pyo3-build-config" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e2a7d2f0d013342f295c048ad19237add5154a55b1c5a254c0ec93d4109078" +dependencies = [ + "target-lexicon", +] + +[[package]] +name = "pyo3-cffi-build-script" +version = "0.1.0" +dependencies = [ + "pyo3", +] + +[[package]] +name = "pyo3-ffi" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca85c467da1bbc8d866eea5deff9cf29ea5f7785054a17da36e65bda9c05845b" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac53762fd065daa3194dd09337a38bd793a188100fd1a9304c4ab312d901771" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca3a1557399783172dc5bf39cfca835157732532cba56b71d2292161e53b362" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" diff --git a/test-crates/pyo3-cffi-build-script/Cargo.toml b/test-crates/pyo3-cffi-build-script/Cargo.toml new file mode 100644 index 000000000..e4a976515 --- /dev/null +++ b/test-crates/pyo3-cffi-build-script/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "pyo3-cffi-build-script" +version = "0.1.0" +edition = "2021" + +[dependencies] +pyo3 = { version = "0.29.0", features = ["abi3"] } + +[lib] +name = "pyo3_cffi_build_script" +crate-type = ["cdylib"] diff --git a/test-crates/pyo3-cffi-build-script/build.rs b/test-crates/pyo3-cffi-build-script/build.rs new file mode 100644 index 000000000..9e68011cd --- /dev/null +++ b/test-crates/pyo3-cffi-build-script/build.rs @@ -0,0 +1,21 @@ +//! Models the `cryptography` project: a PyO3 extension whose build script shells +//! out to the build interpreter to run cffi. maturin must hand us that +//! interpreter via `PYO3_PYTHON`, even for abi3 builds. + +use std::env; +use std::process::Command; + +fn main() { + println!("cargo:rerun-if-env-changed=PYO3_PYTHON"); + let python = env::var("PYO3_PYTHON") + .expect("PYO3_PYTHON is not set; maturin must hand abi3 builds an interpreter"); + let status = Command::new(&python) + .args([ + "-c", + "import cffi; ffi = cffi.FFI(); ffi.cdef('int answer(void);'); \ + ffi.set_source('_pyo3_cffi_demo', 'int answer(void) { return 42; }')", + ]) + .status() + .expect("failed to run PYO3_PYTHON"); + assert!(status.success(), "cffi codegen via PYO3_PYTHON failed"); +} diff --git a/test-crates/pyo3-cffi-build-script/src/lib.rs b/test-crates/pyo3-cffi-build-script/src/lib.rs new file mode 100644 index 000000000..dcf71cb03 --- /dev/null +++ b/test-crates/pyo3-cffi-build-script/src/lib.rs @@ -0,0 +1,7 @@ +use pyo3::prelude::*; + +#[pymodule] +fn pyo3_cffi_build_script(m: &Bound<'_, PyModule>) -> PyResult<()> { + m.add("answer", 42)?; + Ok(()) +} diff --git a/tests/common/other.rs b/tests/common/other.rs index 0c686713e..6a653d7c8 100644 --- a/tests/common/other.rs +++ b/tests/common/other.rs @@ -489,6 +489,40 @@ pub fn abi3_without_version() -> Result<()> { Ok(()) } +pub fn pyo3_cffi_build_script() -> Result<()> { + let base = crate::common::test_python_path().map(PathBuf::from); + let venv_dir = crate::common::create_named_virtualenv("pyo3-cffi-build-script", base)?; + let venv_python = maturin::Target::from_target_triple(None)?.get_venv_python(&venv_dir); + crate::common::install_pip_packages(&venv_python, &["cffi"])?; + let python = venv_python + .to_str() + .context("venv python path is not utf-8")?; + + // The first argument is ignored by clap + let cli = vec![ + "build", + "--manifest-path", + "test-crates/pyo3-cffi-build-script/Cargo.toml", + "--quiet", + "--interpreter", + python, + "--target-dir", + "test-targets/wheels/pyo3_cffi_build_script", + ]; + + let options = BuildOptions::try_parse_from(cli)?; + let build_context = options + .into_build_context() + .strip(Some(cfg!(feature = "faster-tests"))) + .editable(false) + .build()?; + // Actually build the wheel so the crate's build.rs runs. + let wheels = BuildOrchestrator::new(&build_context).build_wheels(); + assert!(wheels.is_ok()); + + Ok(()) +} + pub fn abi3t_without_version() -> Result<()> { let python = crate::common::test_python_path().unwrap_or_else(|| "python3".to_string()); // The first argument is ignored by clap diff --git a/tests/run/integration.rs b/tests/run/integration.rs index 141453647..74f0e1302 100644 --- a/tests/run/integration.rs +++ b/tests/run/integration.rs @@ -168,6 +168,11 @@ fn abi3_without_version() { handle_result(other::abi3_without_version()) } +#[test] +fn pyo3_cffi_build_script() { + handle_result(other::pyo3_cffi_build_script()) +} + #[test] fn abi3t_without_version() { // abi3t requires CPython >= 3.15 (PEP 803). On older runners the build