Skip to content

Commit b0cf4cc

Browse files
committed
Fix cargo test with extension-module feature.
1 parent 67b1a61 commit b0cf4cc

File tree

3 files changed

+33
-21
lines changed

3 files changed

+33
-21
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
2929
- `PyObject_Check`, `PySuper_Check`, and `FreeFunc` [#1438](https://github.com/PyO3/pyo3/pull/1438)
3030

3131
### Fixed
32+
- Fix `cargo test` with `extension-module` feature. (Requires `cargo +nightly -Zextra-link-arg test` for now.) #[1123](https://github.com/PyO3/pyo3/pull/1123)
3233
- Remove FFI definition `PyCFunction_ClearFreeList` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425)
3334
- `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)
3435
- Fix FFI definition `_PyEval_RequestCodeExtraIndex` which took an argument of the wrong type. [#1429](https://github.com/PyO3/pyo3/pull/1429)

build.rs

+23-13
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,13 @@ fn run_python_script(interpreter: &Path, script: &str) -> Result<String> {
605605
}
606606
}
607607

608+
fn get_library_link_name_unix(config: &InterpreterConfig) -> String {
609+
match config.version.implementation {
610+
PythonInterpreterKind::CPython => format!("python{}", config.ld_version),
611+
PythonInterpreterKind::PyPy => format!("pypy{}-c", config.version.major),
612+
}
613+
}
614+
608615
fn get_rustc_link_lib(config: &InterpreterConfig) -> String {
609616
let link_name = if env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() == "windows" {
610617
if env::var("CARGO_CFG_TARGET_ENV").unwrap().as_str() == "gnu" {
@@ -628,10 +635,7 @@ fn get_rustc_link_lib(config: &InterpreterConfig) -> String {
628635
}
629636
}
630637
} else {
631-
match config.version.implementation {
632-
PythonInterpreterKind::CPython => format!("python{}", config.ld_version),
633-
PythonInterpreterKind::PyPy => format!("pypy{}-c", config.version.major),
634-
}
638+
get_library_link_name_unix(config)
635639
};
636640

637641
format!(
@@ -764,17 +768,23 @@ fn configure(interpreter_config: &InterpreterConfig) -> Result<()> {
764768
check_target_architecture(interpreter_config)?;
765769
let target_os = env::var_os("CARGO_CFG_TARGET_OS").unwrap();
766770

771+
if let Some(libdir) = &interpreter_config.libdir {
772+
println!("cargo:rustc-link-search=native={}", libdir);
773+
} else if target_os == "windows" {
774+
println!(
775+
"cargo:rustc-link-search=native={}\\libs",
776+
interpreter_config.base_prefix
777+
);
778+
}
779+
767780
let is_extension_module = env::var_os("CARGO_FEATURE_EXTENSION_MODULE").is_some();
768-
if !is_extension_module || target_os == "windows" || target_os == "android" {
781+
if is_extension_module && !(target_os == "windows" || target_os == "android") {
782+
// Extension module on unix - only link non-lib targets
783+
let lib_name = get_library_link_name_unix(&interpreter_config);
784+
println!("cargo:rustc-link-arg-bins=-l{}", lib_name);
785+
} else {
786+
// Not extension module, or is windows or android - always link to libpython.
769787
println!("{}", get_rustc_link_lib(&interpreter_config));
770-
if let Some(libdir) = &interpreter_config.libdir {
771-
println!("cargo:rustc-link-search=native={}", libdir);
772-
} else if target_os == "windows" {
773-
println!(
774-
"cargo:rustc-link-search=native={}\\libs",
775-
interpreter_config.base_prefix
776-
);
777-
}
778788
}
779789

780790
if interpreter_config.shared {

guide/src/faq.md

+9-8
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,18 @@ PyO3 provides a struct [`GILOnceCell`] which works equivalently to `OnceCell` bu
1515

1616
[`GILOnceCell`]: https://docs.rs/pyo3/latest/pyo3/once_cell/struct.GILOnceCell.html
1717

18-
## I can't run `cargo test`: I'm having linker issues like "Symbol not found" or "Undefined reference to _PyExc_SystemError"!
18+
## I can't run `cargo test` or `cargo run`: I'm having linker issues like "Symbol not found" or "Undefined reference to _PyExc_SystemError"!
1919

20-
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`:
20+
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.
2121

22-
```toml
23-
[dependencies.pyo3]
24-
version = "*"
22+
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.:
2523

26-
[features]
27-
extension-module = ["pyo3/extension-module"]
28-
default = ["extension-module"]
24+
```
25+
# For cargo test
26+
cargo +nightly -Zextra-link-arg test
27+
28+
# For cargo run
29+
cargo +nightly -Zextra-link-arg run
2930
```
3031

3132
## I can't run `cargo test`: my crate cannot be found for tests in `tests/` directory!

0 commit comments

Comments
 (0)