From 5d072cb2a68506445844112e95b732c4287f39a0 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Wed, 27 May 2026 14:28:58 +0300 Subject: [PATCH] cffi: derive Python include dir from PYO3_CROSS_LIB_DIR when cross-compiling (#14904) When cross-compiling, ``cryptography-cffi/build.rs`` queries the host interpreter via ``setuptools.command.build_ext.build_ext.include_dirs`` and feeds the result into ``cc-rs`` as ``-I /usr/include/python3.X``. On hosts that happen to ship Python development headers for the same 3.X line as the target (e.g. an Arch Linux build host with Python 3.14 installed), the host headers leak into the cross build and the target compiler aborts with:: /usr/include/python3.14/pyport.h:429:2: error: #error "LONG_BIT definition appears wrong for platform (bad gcc/glibc config?)." ``PYO3_CROSS_LIB_DIR`` is the documented PyO3 cross-compile signal and points at the target's libpython directory. When it is set, derive the matching Python include dir from it (``/include/``) and skip the host setuptools probe entirely. Native builds keep the existing setuptools-based behaviour, so this is a no-op outside of PyO3-style cross builds. This is consistent with the existing ``PYO3_PYTHON`` handling in the same file: cryptography-cffi already respects PyO3's cross-compile environment for picking the interpreter, and this extends that to the matching header directory. Signed-off-by: Alexandru Ardelean [OpenWrt: dropped the CHANGELOG.rst hunk — the 48.0.0 source tarball does not yet carry the post-48.0.0 "unreleased" section the upstream hunk targets. Drop this patch on next bump once the upstream change is in a tagged release.] Signed-off-by: Alexandru Ardelean --- src/rust/cryptography-cffi/build.rs | 44 ++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 10 deletions(-) --- a/src/rust/cryptography-cffi/build.rs +++ b/src/rust/cryptography-cffi/build.rs @@ -56,16 +56,40 @@ fn main() { ) .unwrap(); println!("cargo:rustc-cfg=python_implementation=\"{python_impl}\""); - let python_includes = run_python_script( - &python, - "import os; \ - import setuptools.dist; \ - import setuptools.command.build_ext; \ - b = setuptools.command.build_ext.build_ext(setuptools.dist.Distribution()); \ - b.finalize_options(); \ - print(os.pathsep.join(b.include_dirs), end='')", - ) - .unwrap(); + println!("cargo:rerun-if-env-changed=PYO3_CROSS_LIB_DIR"); + // When cross-compiling, PyO3 expects the build system to point + // PYO3_CROSS_LIB_DIR at the target's libpython directory. Derive the + // matching include dir from it instead of querying the host + // interpreter's setuptools, which returns host headers (e.g. + // /usr/include/python3.x) and breaks the cross build whenever the host + // happens to have same-version Python development headers installed. + let python_includes = if let Ok(lib_dir) = env::var("PYO3_CROSS_LIB_DIR") { + let lib = Path::new(&lib_dir); + let py_ver = lib + .file_name() + .and_then(|s| s.to_str()) + .unwrap_or("python3"); + let prefix = lib + .parent() + .and_then(|p| p.parent()) + .expect("PYO3_CROSS_LIB_DIR has unexpected layout"); + prefix + .join("include") + .join(py_ver) + .to_string_lossy() + .into_owned() + } else { + run_python_script( + &python, + "import os; \ + import setuptools.dist; \ + import setuptools.command.build_ext; \ + b = setuptools.command.build_ext.build_ext(setuptools.dist.Distribution()); \ + b.finalize_options(); \ + print(os.pathsep.join(b.include_dirs), end='')", + ) + .unwrap() + }; let openssl_c = Path::new(&out_dir).join("_openssl.c"); let mut build = cc::Build::new();