diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b8bd5dc472..cd07da78da6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `PyObject_Check`, `PySuper_Check`, and `FreeFunc` [#1438](https://github.com/PyO3/pyo3/pull/1438) ### Fixed +- Fix `cargo test` with `extension-module` feature. (Requires `cargo +nightly -Zextra-link-arg test` for now.) #[1123](https://github.com/PyO3/pyo3/pull/1123) - Remove FFI definition `PyCFunction_ClearFreeList` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425) - `PYO3_CROSS_LIB_DIR` enviroment variable no long required when compiling for x86-64 Python from macOS arm64 and reverse. [#1428](https://github.com/PyO3/pyo3/pull/1428) - Fix FFI definition `_PyEval_RequestCodeExtraIndex` which took an argument of the wrong type. [#1429](https://github.com/PyO3/pyo3/pull/1429) diff --git a/build.rs b/build.rs index 2afb5802ae5..8e1185f00d4 100644 --- a/build.rs +++ b/build.rs @@ -605,6 +605,13 @@ fn run_python_script(interpreter: &Path, script: &str) -> Result { } } +fn get_library_link_name_unix(config: &InterpreterConfig) -> String { + match config.version.implementation { + PythonInterpreterKind::CPython => format!("python{}", config.ld_version), + PythonInterpreterKind::PyPy => format!("pypy{}-c", config.version.major), + } +} + fn get_rustc_link_lib(config: &InterpreterConfig) -> String { let link_name = if env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() == "windows" { if env::var("CARGO_CFG_TARGET_ENV").unwrap().as_str() == "gnu" { @@ -628,10 +635,7 @@ fn get_rustc_link_lib(config: &InterpreterConfig) -> String { } } } else { - match config.version.implementation { - PythonInterpreterKind::CPython => format!("python{}", config.ld_version), - PythonInterpreterKind::PyPy => format!("pypy{}-c", config.version.major), - } + get_library_link_name_unix(config) }; format!( @@ -764,17 +768,23 @@ fn configure(interpreter_config: &InterpreterConfig) -> Result<()> { check_target_architecture(interpreter_config)?; let target_os = env::var_os("CARGO_CFG_TARGET_OS").unwrap(); + if let Some(libdir) = &interpreter_config.libdir { + println!("cargo:rustc-link-search=native={}", libdir); + } else if target_os == "windows" { + println!( + "cargo:rustc-link-search=native={}\\libs", + interpreter_config.base_prefix + ); + } + let is_extension_module = env::var_os("CARGO_FEATURE_EXTENSION_MODULE").is_some(); - if !is_extension_module || target_os == "windows" || target_os == "android" { + if is_extension_module && !(target_os == "windows" || target_os == "android") { + // Extension module on unix - only link non-lib targets + let lib_name = get_library_link_name_unix(&interpreter_config); + println!("cargo:rustc-link-arg-bins=-l{}", lib_name); + } else { + // Not extension module, or is windows or android - always link to libpython. println!("{}", get_rustc_link_lib(&interpreter_config)); - if let Some(libdir) = &interpreter_config.libdir { - println!("cargo:rustc-link-search=native={}", libdir); - } else if target_os == "windows" { - println!( - "cargo:rustc-link-search=native={}\\libs", - interpreter_config.base_prefix - ); - } } if interpreter_config.shared { diff --git a/guide/src/faq.md b/guide/src/faq.md index 1bda457fceb..7c82ba6a6ab 100644 --- a/guide/src/faq.md +++ b/guide/src/faq.md @@ -15,17 +15,18 @@ PyO3 provides a struct [`GILOnceCell`] which works equivalently to `OnceCell` bu [`GILOnceCell`]: https://docs.rs/pyo3/latest/pyo3/once_cell/struct.GILOnceCell.html -## I can't run `cargo test`: I'm having linker issues like "Symbol not found" or "Undefined reference to _PyExc_SystemError"! +## I can't run `cargo test` or `cargo run`: I'm having linker issues like "Symbol not found" or "Undefined reference to _PyExc_SystemError"! -Currently, [#341](https://github.com/PyO3/pyo3/issues/341) causes `cargo test` to fail with linking errors when the `extension-module` feature is activated. For now you can work around this by making the `extension-module` feature optional and running the tests with `cargo test --no-default-features`: +On unix operating systems the `extension-module` feature is required to disable linking against libpython to meet criteria of how Python extension modules should be built. -```toml -[dependencies.pyo3] -version = "*" +PyO3 is able to re-enable linking for binaries and tests in the project, but it requires a nightly cargo feature. To use this feature, you must opt into it, e.g.: -[features] -extension-module = ["pyo3/extension-module"] -default = ["extension-module"] +``` +# For cargo test +cargo +nightly -Zextra-link-arg test + +# For cargo run +cargo +nightly -Zextra-link-arg run ``` ## I can't run `cargo test`: my crate cannot be found for tests in `tests/` directory!