Skip to content

Commit

Permalink
Fix cargo test with extension-module feature.
Browse files Browse the repository at this point in the history
  • Loading branch information
aviramha committed Feb 1, 2022
1 parent bb0ae49 commit 8aef9a0
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 16 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ jobs:
run: |
python -m pip install -U pip nox
cargo xtask test-py
cargo run
cargo test
env:
CARGO_TARGET_DIR: ${{ github.workspace }}/target

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- Fix `cargo test` with `extension-module` feature. (Requires `cargo +nightly` for now.) #[2135](https://github.com/PyO3/pyo3/pull/2135)
- Fix undefined symbol for `PyObject_HasAttr` on PyPy. [#2025](https://github.com/PyO3/pyo3/pull/2025)
- Fix memory leak in `PyErr::into_value`. [#2026](https://github.com/PyO3/pyo3/pull/2026)
- Fix clippy warning `needless-option-as-deref` in code generated by `#[pyfunction]` and `#[pymethods]`. [#2040](https://github.com/PyO3/pyo3/pull/2040)
Expand Down
16 changes: 8 additions & 8 deletions guide/src/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ PyO3 provides a struct [`GILOnceCell`] which works equivalently to `OnceCell` bu

[`GILOnceCell`]: {{#PYO3_DOCS_URL}}/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, [#340](https://github.com/PyO3/pyo3/issues/340) 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]
{{#PYO3_CRATE_VERSION}}
PyO3 is able to re-enable linking for binaries and tests in the project, but this requires a `cargo` version capable of understanding extra linker arguments. This is only supported on nightly cargoes from February of 2022 or newer.

[features]
extension-module = ["pyo3/extension-module"]
default = ["extension-module"]
```
# For cargo test
cargo +nightly test
# For cargo run
cargo +nightly run
```

## I can't run `cargo test`: my crate cannot be found for tests in `tests/` directory!
Expand Down
45 changes: 37 additions & 8 deletions pyo3-build-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,36 @@ pub fn use_pyo3_cfgs() {
get().emit_pyo3_cfgs();
}

/// Adds linker arguments (for macOS) suitable for PyO3's `extension-module` feature.
/// Adds linker arguments 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.
#[cfg(feature = "resolve-config")]
pub fn add_extension_module_link_args() {
let interpreter_config = get();

_add_extension_module_link_args(
interpreter_config,
&impl_::cargo_env_var("CARGO_CFG_TARGET_OS").unwrap(),
std::io::stdout(),
)
}

fn _add_extension_module_link_args(target_os: &str, mut writer: impl std::io::Write) {
fn _add_extension_module_link_args(
interpreter_config: &InterpreterConfig,
target_os: &str,
mut writer: impl std::io::Write,
) {
if target_os == "macos" {
writeln!(writer, "cargo:rustc-cdylib-link-arg=-undefined").unwrap();
writeln!(writer, "cargo:rustc-cdylib-link-arg=dynamic_lookup").unwrap();
}
if target_os != "windows" && target_os != "android" {
let lib_name = interpreter_config.lib_name.as_ref().unwrap();
writeln!(writer, "cargo:rustc-link-arg-bins=-l{}", lib_name).unwrap();
writeln!(writer, "cargo:rustc-link-arg-tests=-l{}", lib_name).unwrap();
writeln!(writer, "cargo:rustc-link-arg-benches=-l{}", lib_name).unwrap();
writeln!(writer, "cargo:rustc-link-arg-examples=-l{}", lib_name).unwrap();
}
}

/// Loads the configuration determined from the build environment.
Expand Down Expand Up @@ -179,15 +191,32 @@ mod tests {
fn extension_module_link_args() {
let mut buf = Vec::new();

let interpreter_cfg = InterpreterConfig {
version: PythonVersion { major: 3, minor: 7 },
implementation: PythonImplementation::CPython,
shared: true,
abi3: false,
lib_name: Some("test".to_owned()),
lib_dir: None,
executable: None,
pointer_width: None,
build_flags: BuildFlags::default(),
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
};
// Does nothing on non-mac
_add_extension_module_link_args("windows", &mut buf);
_add_extension_module_link_args(&interpreter_cfg, "windows", &mut buf);
assert_eq!(buf, Vec::new());

_add_extension_module_link_args("macos", &mut buf);
_add_extension_module_link_args(&interpreter_cfg, "macos", &mut buf);
assert_eq!(
std::str::from_utf8(&buf).unwrap(),
"cargo:rustc-cdylib-link-arg=-undefined\n\
cargo:rustc-cdylib-link-arg=dynamic_lookup\n"
cargo:rustc-cdylib-link-arg=dynamic_lookup\n\
cargo:rustc-link-arg-bins=-ltest\n\
cargo:rustc-link-arg-tests=-ltest\n\
cargo:rustc-link-arg-benches=-ltest\n\
cargo:rustc-link-arg-examples=-ltest\n"
);
}
}

0 comments on commit 8aef9a0

Please sign in to comment.