From c2d6a50b353a9460cc51171c60129ac08b68fe44 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Mon, 2 Aug 2021 22:56:24 +0100 Subject: [PATCH] build: revert usage of cargo:rustc-cdylib-link-arg --- CHANGELOG.md | 2 + build.rs | 5 --- guide/src/building_and_distribution.md | 30 +++++++++++++++ pyo3-build-config/src/lib.rs | 51 ++++++++++++++++---------- 4 files changed, 64 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79a045644e8..87f50f595d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Add `indexmap` feature to add `ToPyObject`, `IntoPy` and `FromPyObject` implementations for `indexmap::IndexMap`. [#1728](https://github.com/PyO3/pyo3/pull/1728) +- Add `pyo3_build_config::add_extension_module_link_args()` to use in build scripts to set linker arguments (for macOS). [#1755](https://github.com/PyO3/pyo3/pull/1755) ### Changed - `PyErr::new` no longer acquires the Python GIL internally. [#1724](https://github.com/PyO3/pyo3/pull/1724) +- Reverted PyO3 0.14.0's use of `cargo:rustc-cdylib-link-arg` in its build script, as Cargo unintentionally allowed crates to pass linker args to downstream crates in this way. Projects supporting macOS may need to restore `.cargo/config.toml` files. [#1755](https://github.com/PyO3/pyo3/pull/1755) ### Fixed diff --git a/build.rs b/build.rs index 6bfd4ce256a..c4ac6bf9623 100644 --- a/build.rs +++ b/build.rs @@ -121,11 +121,6 @@ fn emit_cargo_configuration(interpreter_config: &InterpreterConfig) -> Result<() println!("cargo:rustc-link-search=native={}\\libs", base_prefix); } } - (true, "macos") => { - // with extension module on macos some extra linker arguments are needed - println!("cargo:rustc-cdylib-link-arg=-undefined"); - println!("cargo:rustc-cdylib-link-arg=dynamic_lookup"); - } (false, _) | (_, "android") => { // other systems, only link libs if not extension module // android always link. diff --git a/guide/src/building_and_distribution.md b/guide/src/building_and_distribution.md index 54a81f30400..96cfc69838b 100644 --- a/guide/src/building_and_distribution.md +++ b/guide/src/building_and_distribution.md @@ -82,6 +82,36 @@ You can then open a Python shell in the output directory and you'll be able to r See, as an example, Bazel rules to build PyO3 on Linux at https://github.com/TheButlah/rules_pyo3. +#### macOS + +On macOS, because the `extension-module` feature disables linking to `libpython` ([see the next section](#the-extension-module-feature)), some additional linker arguments need to be set. `maturin` and `setuptools-rust` both pass these arguments for PyO3 automatically, but projects using manual builds will need to set these directly in order to support macOS. + +The easiest way to set the correct linker arguments is to add a [`build.rs`](https://doc.rust-lang.org/cargo/reference/build-scripts.html) with the following content: + +```rust,ignore +fn main() { + pyo3_build_config::add_extension_module_link_args(); +} +``` + +Remember to also add `pyo3-build-config` to the `build-dependencies` section in `Cargo.toml`. + +An alternative to using `pyo3-build-config` is add the following to a cargo configuration file (e.g. `.cargo/config.toml`): + +```toml +[target.x86_64-apple-darwin] +rustflags = [ + "-C", "link-arg=-undefined", + "-C", "link-arg=dynamic_lookup", +] + +[target.aarch64-apple-darwin] +rustflags = [ + "-C", "link-arg=-undefined", + "-C", "link-arg=dynamic_lookup", +] +``` + ### The `extension-module` feature PyO3's `extension-module` feature is used to disable [linking](https://en.wikipedia.org/wiki/Linker_(computing)) to `libpython` on unix targets. diff --git a/pyo3-build-config/src/lib.rs b/pyo3-build-config/src/lib.rs index 338e5b42460..0bc947aabed 100644 --- a/pyo3-build-config/src/lib.rs +++ b/pyo3-build-config/src/lib.rs @@ -1,18 +1,7 @@ //! Configuration used by PyO3 for conditional support of varying Python versions. //! -//! The only public API currently exposed is [`use_pyo3_cfgs`], which is intended to be used in -//! build scripts to add a standard set of `#[cfg]` attributes for handling multiple Python -//! versions. -//! -//! The full list of attributes added are the following: -//! -//! | Flag | Description | -//! | ---- | ----------- | -//! | `#[cfg(Py_3_6)]`, `#[cfg(Py_3_7)]`, `#[cfg(Py_3_8)]`, `#[cfg(Py_3_9)]`, `#[cfg(Py_3_10)]` | These attributes mark code only for a given Python version and up. For example, `#[cfg(Py_3_6)]` marks code which can run on Python 3.6 **and newer**. | -//! | `#[cfg(Py_LIMITED_API)]` | This marks code which is run when compiling with PyO3's `abi3` feature enabled. | -//! | `#[cfg(PyPy)]` | This marks code which is run when compiling for PyPy. | -//! -//! For examples of how to use these attributes, [see PyO3's guide](https://pyo3.rs/latest/building_and_distribution/multiple_python_versions.html). +//! The public APIs exposed, [`use_pyo3_cfgs`] and [`add_extension_module_link_args`] are intended +//! to be called from build scripts to simplify building crates which depend on PyO3. #[doc(hidden)] pub mod errors; @@ -20,14 +9,12 @@ mod impl_; use once_cell::sync::OnceCell; -pub use impl_::{ - find_interpreter, get_config_from_interpreter, InterpreterConfig, PythonImplementation, - PythonVersion, -}; - // Used in PyO3's build.rs #[doc(hidden)] -pub use impl_::{cargo_env_var, env_var, make_interpreter_config}; +pub use impl_::{ + cargo_env_var, env_var, find_interpreter, get_config_from_interpreter, make_interpreter_config, + InterpreterConfig, PythonImplementation, PythonVersion, +}; /// Reads the configuration written by PyO3's build.rs /// @@ -46,6 +33,32 @@ pub fn get() -> &'static InterpreterConfig { #[doc(hidden)] pub const PATH: &str = concat!(env!("OUT_DIR"), "/pyo3-build-config.txt"); +/// Adds all the [`#[cfg]` flags](index.html) to the current compilation. +/// +/// This should be called from a build script. +/// +/// The full list of attributes added are the following: +/// +/// | Flag | Description | +/// | ---- | ----------- | +/// | `#[cfg(Py_3_6)]`, `#[cfg(Py_3_7)]`, `#[cfg(Py_3_8)]`, `#[cfg(Py_3_9)]`, `#[cfg(Py_3_10)]` | These attributes mark code only for a given Python version and up. For example, `#[cfg(Py_3_6)]` marks code which can run on Python 3.6 **and newer**. | +/// | `#[cfg(Py_LIMITED_API)]` | This marks code which is run when compiling with PyO3's `abi3` feature enabled. | +/// | `#[cfg(PyPy)]` | This marks code which is run when compiling for PyPy. | +/// +/// For examples of how to use these attributes, [see PyO3's guide](https://pyo3.rs/latest/building_and_distribution/multiple_python_versions.html). pub fn use_pyo3_cfgs() { get().emit_pyo3_cfgs(); } + +/// Adds linker arguments (for macOS) suitable for PyO3's `extension-module` feature. +/// +/// This should be called from a build script. +/// +/// This is currently a no-op on non-macOS platforms, however may emit additional linker arguments +/// in future if deemed necessarys. +pub fn add_extension_module_link_args() { + if cargo_env_var("CARGO_CFG_TARGET_OS").unwrap() == "macos" { + println!("cargo:rustc-cdylib-link-arg=-undefined"); + println!("cargo:rustc-cdylib-link-arg=dynamic_lookup"); + } +}