Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link errors on macOS when a dependency which also uses pyo3 has a cdylib target #1080

Open
1 task done
konstin opened this issue Sep 1, 2022 · 10 comments
Open
1 task done
Labels
bug Something isn't working

Comments

@konstin
Copy link
Member

konstin commented Sep 1, 2022

Bug Description

I have two crates, cell and mitochondria, where cell depends on mitochondria. Each has pyo3 bindings on its own. If mitochondria has cdylib as crate-type, trying to maturin build on mac os will fail with pyo3 linker errors, with only the default crate-type rlib or on ubuntu and windows it works. I've made a minimal example with github actions at https://github.com/konstin/maturin-mac-os-dep-repro.

The error looks like it's missing the link-arg=-undefined/link-arg=dynamic_lookup, even though they are present and work for the top level crate.

[package]
name = "mitochondria"
version = "0.1.0"
edition = "2021"

[lib]
# REMOVE cdyblib FROM THE LINE BELOW TO MAKE THIS PASS
crate-type = ["cdylib", "rlib"]

[dependencies]
pyo3 = { version = "0.17.1", features = ["extension-module"] }
[package]
name = "cell"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
pyo3 = { version = "0.17.1", features = ["extension-module"] }
mitochondria = { path = "mitochondria" }

Your Python version (python -V)

3.8

Your pip version (pip -V)

22.2.2

What bindings you're using

pyo3

Does cargo build work?

n/a, this is a linker error

If on windows, have you checked that you aren't accidentally using unix path (those with the forward slash /)?

  • Yes

Steps to Reproduce

See minimal example at https://github.com/konstin/maturin-mac-os-dep-repro

Ubuntu, passing: https://github.com/konstin/maturin-mac-os-dep-repro/runs/8144523404?check_suite_focus=true
Mac os, failing: https://github.com/konstin/maturin-mac-os-dep-repro/runs/8144523536?check_suite_focus=true

@konstin konstin added the bug Something isn't working label Sep 1, 2022
@messense
Copy link
Member

messense commented Sep 2, 2022

The error looks like it's missing the link-arg=-undefined/link-arg=dynamic_lookup, even though they are present and work for the top level crate.

I think it's because we are using cargo rustc which only applies these flags to top level crate.

@messense
Copy link
Member

messense commented Sep 2, 2022

See also PyO3/setuptools-rust#235

@messense messense changed the title Link errors on mac os when a depency which also uses pyo3 has a cdylib target Link errors on macOS when a depency which also uses pyo3 has a cdylib target Sep 25, 2022
@messense messense changed the title Link errors on macOS when a depency which also uses pyo3 has a cdylib target Link errors on macOS when a dependency which also uses pyo3 has a cdylib target Sep 25, 2022
@mlucool
Copy link

mlucool commented Nov 19, 2022

Any workarounds for this?

@messense
Copy link
Member

@mlucool If you mean deshaw/nbstripout-fast#3 you can feature-gate the extension-module feature of pyo3.

[dependencies]
pyo3 = "0.17.3"

[features]
default = ["extension-module"]
extension-module = ["pyo3/extension-module"]

Then you can build bin bindings with maturin build --no-default-features to disable extension-module feature. When using cibuildwheel you can pass --no-default-features option via MATURIN_PEP517_ARGS="--no-default-features" env var.

@peytondmurray
Copy link

@messense I tried feature-gating the python bindings as you said by setting

# Cargo.toml

[features]
default = ["extension-module"]
extension-module = ["pyo3/extension-module"]

and

# pyproject.toml

[tool.maturin]
bindings = "bin"

to match what you suggested above.

When I tried to build the project using maturin build --no-default-features, I got a binary - which is what I want - but when I just did maturin build, I got a binary also. Interestingly, the only thing that allowed me to build python bindings was removing tool.maturin.bindings = "bin" from pyproject.toml - but when I did that, I could no longer build the python bindings. Here's a table of the resulting build artifact that I get when I change settings with the different build commands:

maturin build maturin build --no-default-features
tool.maturin.bindings = "bin" bin bin
No tool.maturin settings python bindings python bindings

In summary, I wasn't able to get --no-default-features to act as a feature gate to allow me to switch from building bin to building the python bindings. What did I miss here? 🤔

@messense
Copy link
Member

@peytondmurray Have you tried override bindings type in cli? maturin build -b pyo3.

@peytondmurray
Copy link

peytondmurray commented Nov 28, 2022

@messense Thanks for the help - overriding the bindings type in CLI does work, but I'm still getting macOS build issues using cibuildwheel even after feature-gating the extension-module as you suggested above. From the log I've confirmed that the build command used on the runner is correct:

    Running `maturin pep517 build-wheel -i /private/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/cibw-run-klnop_4a/cp39-macosx_arm64/build/venv/bin/python --compatibility off --no-default-features`

but the build still fails at the linking stage for binary output 🤔. I can keep poking around with this, maybe there's something else I'm doing wrong here.

I'm also not sure if this helps, but cibuildwheel recently added the option to pass CLI args to the build backend with the CIBW_BUILD_SETTINGS variable: pypa/cibuildwheel#1244 which could be useful here too.

@messense
Copy link
Member

messense commented Nov 29, 2022

Not sure why, but with some debugging it show that even when extension-module feature disabled CARGO_FEATURE_EXTENSION_MODULE env var still presents:

https://github.com/PyO3/pyo3/blob/a71905052e9320767a1275a85b07e2dc895a17e0/pyo3-build-config/src/impl_.rs#L710

which in turn causes pyo3 to not emit libpython link args.

cc @davidhewitt

Reproduce steps:

git clone https://github.com/peytondmurray/nbstripout-fast.git
cd nbstripout-fast
git checkout add-bin
maturin build --no-default-features

PYO3_PRINT_CONFIG looks fine to me

$ PYO3_PRINT_CONFIG=1 maturin build --no-default-features
📦 Including license file "/Users/messense/Projects/nbstripout-fast/LICENSE.txt"
🐍 Found CPython 3.11 at /Users/messense/.pyenv/versions/3.11.0/bin/python3
📡 Using build options bindings from pyproject.toml
   Compiling pyo3-ffi v0.16.6
error: failed to run custom build command for `pyo3-ffi v0.16.6`

Caused by:
  process didn't exit successfully: `/Users/messense/Projects/nbstripout-fast/target/debug/build/pyo3-ffi-2eeeb1eb9310c032/build-script-build` (exit status: 101)
  --- stdout
  cargo:rerun-if-env-changed=PYO3_CROSS
  cargo:rerun-if-env-changed=PYO3_CROSS_LIB_DIR
  cargo:rerun-if-env-changed=PYO3_CROSS_PYTHON_VERSION
  cargo:rerun-if-env-changed=PYO3_CROSS_PYTHON_IMPLEMENTATION
  cargo:rerun-if-env-changed=PYO3_PRINT_CONFIG

  -- PYO3_PRINT_CONFIG=1 is set, printing configuration and halting compile --
  implementation=CPython
  version=3.11
  shared=true
  abi3=false
  lib_name=python3.11
  lib_dir=/Users/messense/.pyenv/versions/3.11.0/lib
  executable=/Users/messense/.pyenv/versions/3.11.0/bin/python3
  pointer_width=64
  build_flags=
  suppress_build_script_link_lines=false

  note: unset the PYO3_PRINT_CONFIG environment variable and retry to compile with the above config
💥 maturin failed
  Caused by: Failed to build a native library through cargo
  Caused by: Cargo build finished with "exit status: 101": `"cargo" "rustc" "--no-default-features" "--manifest-path" "/Users/messense/Projects/nbstripout-fast/Cargo.toml" "--message-format" "json" "--bin" "nbstripout-fast"`

peytondmurray added a commit to peytondmurray/nbstripout-fast that referenced this issue Dec 5, 2022
@messense
Copy link
Member

messense commented Dec 14, 2022

xref rust-lang/cargo#9235

there is an implicit dependency from a binary to the library

@konstin
Copy link
Member Author

konstin commented Apr 4, 2023

For future reference, i've confirmed that changing

      - name: Build wheels - x86_64
        uses: PyO3/maturin-action@v1
        with:
          target: x86_64

to

      - name: Build wheels - x86_64
        uses: PyO3/maturin-action@v1
        with:
          target: x86_64
        env:
          RUSTFLAGS: "-C link-arg=-undefined -C link-arg=dynamic_lookup"

is a workaround

I'm not sure where to document that properly, it's definitely a rare problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants