From b6f3ae489e398b42d283b4920d23c89a16600df5 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Wed, 12 Nov 2025 20:13:32 +0000 Subject: [PATCH 1/3] add API to set rpath for libpython from build scripts --- pyo3-build-config/src/lib.rs | 46 ++++++++++++++++++++++++++++++++++++ pyo3-ffi-check/Cargo.toml | 5 +--- pyo3-ffi-check/build.rs | 3 +++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/pyo3-build-config/src/lib.rs b/pyo3-build-config/src/lib.rs index 0544376e3b4..96695b4a69a 100644 --- a/pyo3-build-config/src/lib.rs +++ b/pyo3-build-config/src/lib.rs @@ -73,6 +73,52 @@ fn _add_extension_module_link_args(triple: &Triple, mut writer: impl std::io::Wr } } +/// Adds linker arguments to set rpath when embedding Python within a Rust binary. +/// +/// When running tests or binaries built with PyO3, the Python dynamic library needs +/// to be found at runtime. +/// +/// This can be done by setting environment variables like `DYLD_LIBRARY_PATH` on macOS, +/// `LD_LIBRARY_PATH` on Linux, or `PATH` on Windows. +/// +/// Altrnatively (as per this function) rpath can be set at link time to point to the +/// directory containing the Python dynamic library. This avoids the need to set environment +/// variables, so can be convenient, however may not be appropriate for binaries packaged +/// for distribution. +/// +#[doc = concat!("[See PyO3's guide](https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/building-and-distribution#dynamically-embedding-the-python-interpreter)")] +/// for more details. +#[cfg(feature = "resolve-config")] +pub fn add_libpython_rpath_link_args() { + let target = impl_::target_triple_from_env(); + _add_libpython_rpath_link_args( + get(), + &target, + impl_::is_linking_libpython_for_target(&target), + std::io::stdout(), + ) +} + +#[cfg(feature = "resolve-config")] +fn _add_libpython_rpath_link_args( + interpreter_config: &InterpreterConfig, + triple: &Triple, + link_libpython: bool, + mut writer: impl std::io::Write, +) { + if link_libpython { + // FIXME: handle framework linking after #5606 merges + if let Some(lib_dir) = interpreter_config.lib_dir.as_ref() { + writeln!(writer, "cargo:rustc-link-arg=-Wl,-rpath,{lib_dir}").unwrap(); + } + } + // if matches!(triple.operating_system, OperatingSystem::Darwin(_)) && link_libpython { + // if let Some(framework_prefix) = interpreter_config.python_framework_prefix.as_ref() { + // writeln!(writer, "cargo:rustc-link-arg=-Wl,-rpath,{framework_prefix}").unwrap(); + // } + // } +} + /// Adds linker arguments suitable for linking against the Python framework on macOS. /// /// This should be called from a build script. diff --git a/pyo3-ffi-check/Cargo.toml b/pyo3-ffi-check/Cargo.toml index cdf38c9f9bf..6c861139098 100644 --- a/pyo3-ffi-check/Cargo.toml +++ b/pyo3-ffi-check/Cargo.toml @@ -6,10 +6,7 @@ publish = false [dependencies] pyo3-ffi-check-macro = { path = "./macro" } - -[dependencies.pyo3-ffi] -path = "../pyo3-ffi" -features = ["extension-module"] # A lazy way of skipping linking in most cases (as we don't use any runtime symbols) +pyo3-ffi = { path = "../pyo3-ffi" } [build-dependencies] bindgen = "0.69.4" diff --git a/pyo3-ffi-check/build.rs b/pyo3-ffi-check/build.rs index e7cfbe40df3..d6c4fb765b6 100644 --- a/pyo3-ffi-check/build.rs +++ b/pyo3-ffi-check/build.rs @@ -20,7 +20,10 @@ impl bindgen::callbacks::ParseCallbacks for ParseCallbacks { } fn main() { + pyo3_build_config::add_libpython_rpath_link_args(); + let config = pyo3_build_config::get(); + let python_include_dir = config .run_python_script( "import sysconfig; print(sysconfig.get_config_var('INCLUDEPY'), end='');", From a63c7f33420dc2659182c355a0edf8ec291fa455 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Wed, 12 Nov 2025 21:47:50 +0000 Subject: [PATCH 2/3] framework concern possibly irrelevant --- pyo3-build-config/src/lib.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/pyo3-build-config/src/lib.rs b/pyo3-build-config/src/lib.rs index 96695b4a69a..5011470bfa9 100644 --- a/pyo3-build-config/src/lib.rs +++ b/pyo3-build-config/src/lib.rs @@ -93,7 +93,6 @@ pub fn add_libpython_rpath_link_args() { let target = impl_::target_triple_from_env(); _add_libpython_rpath_link_args( get(), - &target, impl_::is_linking_libpython_for_target(&target), std::io::stdout(), ) @@ -102,21 +101,14 @@ pub fn add_libpython_rpath_link_args() { #[cfg(feature = "resolve-config")] fn _add_libpython_rpath_link_args( interpreter_config: &InterpreterConfig, - triple: &Triple, - link_libpython: bool, + is_linking_libpython: bool, mut writer: impl std::io::Write, ) { - if link_libpython { - // FIXME: handle framework linking after #5606 merges + if is_linking_libpython { if let Some(lib_dir) = interpreter_config.lib_dir.as_ref() { writeln!(writer, "cargo:rustc-link-arg=-Wl,-rpath,{lib_dir}").unwrap(); } } - // if matches!(triple.operating_system, OperatingSystem::Darwin(_)) && link_libpython { - // if let Some(framework_prefix) = interpreter_config.python_framework_prefix.as_ref() { - // writeln!(writer, "cargo:rustc-link-arg=-Wl,-rpath,{framework_prefix}").unwrap(); - // } - // } } /// Adds linker arguments suitable for linking against the Python framework on macOS. From a25301ccdd82ad7e6cabd880e6ba5fef0e6808f4 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Tue, 18 Nov 2025 12:04:26 +0000 Subject: [PATCH 3/3] newsfragment --- newsfragments/5624.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 newsfragments/5624.added.md diff --git a/newsfragments/5624.added.md b/newsfragments/5624.added.md new file mode 100644 index 00000000000..670a23039d9 --- /dev/null +++ b/newsfragments/5624.added.md @@ -0,0 +1 @@ +Add `pyo3_build_config::add_libpython_rpath_link_args`.