PyO3 / pyo3

Rust bindings for the Python interpreter
https://pyo3.rs
Apache License 2.0
11.93k stars 731 forks source link

Incorrect extra library search path when cross-compiling #4350

Open Thalyum opened 1 month ago

Thalyum commented 1 month ago

Bug Description

I tried to use PyO3 crate, and cross-compile a simple tool for Aarch64. I was using buildroot to cross-compile for my target:

When I encountered an error during link. Here is the error I got with buildroot:

   [...]
   Compiling pyo3-build-config v0.22.0
   Compiling syn v2.0.68
   Compiling pyo3-ffi v0.22.0
   Compiling pyo3-macros-backend v0.22.0
   Compiling pyo3 v0.22.0
   Compiling pyo3-macros v0.22.0
   Compiling pyo3-test v0.1.0 (<buildroot_path>/output/build/pyo3-test-custom)
error: linking with `aarch64-buildroot-linux-gnu-gcc` failed: exit status: 1
  |
  = note: LC_ALL="C" PATH="<buildroot_path>/output/host/lib64/rustlib/x86_64-unknown-linux-gnu/bin:<buildroot_path>/output/host/bin:<buildroot_path>/output/host/sbin:/home/<user>/.local/bin:/home/<user>/.asdf/shims:/home/<user>/.asdf/bin:/home/<user>/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/home/<user>/.antigen/bundles/robbyrussell/oh-my-zsh/lib:/home/<user>/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/git:/home/<user>/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/heroku:/home/<user>/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/pip:/home/<user>/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/lein:/home/<user>/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/command-not-found:/home/<user>/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/colored-man-pages:/home/<user>/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/ripgrep:/home/<user>/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/fd:/home/<user>/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/asdf:/home/<user>/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/ssh-agent:/home/<user>/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/fzf:/home/<user>/.antigen/bundles/zsh-users/zsh-syntax-highlighting" VSLANG="1033" "aarch64-buildroot-linux-gnu-gcc" "/tmp/rustcgJuVcE/symbols.o" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps/pyo3_test-f32b0c004f8ccc00.pyo3_test.fcad09a3b6d05bc0-cgu.0.rcgu.o" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps/pyo3_test-f32b0c004f8ccc00.pyo3_test.fcad09a3b6d05bc0-cgu.1.rcgu.o" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps/pyo3_test-f32b0c004f8ccc00.pyo3_test.fcad09a3b6d05bc0-cgu.2.rcgu.o" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps/pyo3_test-f32b0c004f8ccc00.pyo3_test.fcad09a3b6d05bc0-cgu.3.rcgu.o" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps/pyo3_test-f32b0c004f8ccc00.pyo3_test.fcad09a3b6d05bc0-cgu.4.rcgu.o" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps/pyo3_test-f32b0c004f8ccc00.24cs22e3m87m5ggl.rcgu.o" "-Wl,--as-needed" "-L" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps" "-L" "<buildroot_path>/output/build/pyo3-test-custom/target/release/deps" "-L" "/usr/lib" "-L" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps/libpyo3-a23ec84b4db81f26.rlib" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps/libcfg_if-e1038b298c3f372c.rlib" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps/libmemoffset-74f73402b9197fb9.rlib" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps/libonce_cell-ee7cb4582e05252e.rlib" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps/libpyo3_ffi-5cdbd4edc921ae4f.rlib" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps/liblibc-522fea0478d84537.rlib" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps/libunindent-6ab427a550abaff1.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/libstd-9db51037f7732c7f.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/libpanic_unwind-43f7084971578043.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/libobject-55e3c3e99d7ea57c.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/libmemchr-fb53010b8d947b31.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/libaddr2line-6f437829797b59f9.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/libgimli-c465d68cd448aa2e.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/librustc_demangle-12979ddb857b6856.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/libstd_detect-ecc5f92a35a5dcae.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/libhashbrown-09b6240c5d3892f5.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-e35646347e036948.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/libminiz_oxide-893df93494354b60.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/libadler-297a87c8b999e355.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/libunwind-eb6321afc60f0508.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/libcfg_if-e65240dca34fcbd0.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/liblibc-4b653d72a90009a1.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/liballoc-58548d24e1f3d56c.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/librustc_std_workspace_core-84c459117cd1fdc9.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/libcore-d6e05faaecef4023.rlib" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib/libcompiler_builtins-c35031b3bb3289ef.rlib" "-Wl,-Bdynamic" "-lpython3.12" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "<buildroot_path>/output/host/lib64/rustlib/aarch64-unknown-linux-gnu/lib" "-o" "<buildroot_path>/output/build/pyo3-test-custom/target/aarch64-unknown-linux-gnu/release/deps/pyo3_test-f32b0c004f8ccc00" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-Wl,-O1" "-Wl,--strip-debug" "-nodefaultlibs"
  = note: aarch64-buildroot-linux-gnu-gcc: ERROR: unsafe header/library path used in cross-compilation: '-L' '/usr/lib'

error: could not compile `pyo3-test` (bin "pyo3-test") due to 1 previous error
make: *** [package/pkg-generic.mk:283: <buildroot_path>/output/build/pyo3-test-custom/.stamp_built] Error 101

The error comes from a bad linker option: -L /usr/lib. Buildroot uses a wrapper around the toolchain (including the linker) that checks if the build tries to use "unsafe" paths, especially in the includes path and library search path. As stated in buildroot documentation:

 * An unsafe path is one that points to a directory with libraries or
 * headers for the build machine, which are not suitable for the target.

We do not expect cross-compiled library in /usr/lib, only host libraries or headers. I tried to reproduce with 'manual' cross-compilation. I reused the cross-compiled python interpreter built by Buildroot, as well as its cross-toolchain:

setup the linker:

[target.aarch64-unknown-linux-gnu]
linker = "<buildroot_path>/output/host/bin/aarch64-buildroot-linux-gnu-ld"
rustflags = [
    "-L", "<buildroot_path>/output/host/lib/gcc/aarch64-buildroot-linux-gnu/13.3.0",
    "-C", "link-arg=--verbose",
]

The custom rustflags is to add the search path for libgcc, as well as some verbosity.

Then compile:

RUSTC_LOG=rustc_codegen_ssa::back::link=info PYO3_CROSS=y \
    PYO3_PTYHON=<buildroot_path>/output/host/bin/python3.12 \
    PYO3_CROSS_LIB_DIR=<buildroot_path>/output/target/usr/lib/ \
    cargo build --target=aarch64-unknown-linux-gnu

No issue with manual cross-compilation. Since the linker recognizes the architecture of the libraries in /usr/lib and ignores them as they are for the host:

<buildroot_path>/output/host/bin/aarch64-buildroot-linux-gnu-ld: warning: library search path "/usr/lib" is unsafe for cross-compilation
<buildroot_path>/output/host/bin/aarch64-buildroot-linux-gnu-ld: skipping incompatible /usr/lib/libpython3.12.so when searching for -lpython3.12
<buildroot_path>/output/host/bin/aarch64-buildroot-linux-gnu-ld: skipping incompatible /usr/lib/libgcc_s.so.1 when searching for libgcc_s.so.1
<buildroot_path>/output/host/bin/aarch64-buildroot-linux-gnu-ld: skipping incompatible /usr/lib/libgcc_s.so.1 when searching for libgcc_s.so.1
<buildroot_path>/output/host/bin/aarch64-buildroot-linux-gnu-ld: skipping incompatible /usr/lib/libm.so when searching for -lm
<buildroot_path>/output/host/bin/aarch64-buildroot-linux-gnu-ld: skipping incompatible /usr/lib/libm.a when searching for -lm
<buildroot_path>/output/host/bin/aarch64-buildroot-linux-gnu-ld: skipping incompatible /usr/lib/libc.so when searching for -lc
<buildroot_path>/output/host/bin/aarch64-buildroot-linux-gnu-ld: skipping incompatible /usr/lib/libc.a when searching for -lc

But we still see the same kind of warning.

By using the PYO3_PRINT_CONFIG variable, I took a peek at the configuration generated by pyo3-build-config:

error: failed to run custom build command for `pyo3-ffi v0.22.0`

Caused by:
  process didn't exit successfully: `/home/user/projects/pyo3-test/target/debug/build/pyo3-ffi-2b44fcc05a9f602e/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_NO_PYTHON
  cargo:rerun-if-env-changed=_PYTHON_SYSCONFIGDATA_NAME
  cargo:rerun-if-env-changed=PYO3_ENVIRONMENT_SIGNATURE
  cargo:rerun-if-env-changed=PYO3_PYTHON
  cargo:rerun-if-env-changed=VIRTUAL_ENV
  cargo:rerun-if-env-changed=CONDA_PREFIX
  cargo:rerun-if-env-changed=PATH
  cargo:rerun-if-env-changed=PYO3_USE_ABI3_FORWARD_COMPATIBILITY
  cargo:rerun-if-env-changed=PYO3_PRINT_CONFIG

  -- PYO3_PRINT_CONFIG=1 is set, printing configuration and halting compile --
  implementation=CPython
  version=3.12
  shared=true
  abi3=false
  lib_name=python3.12
  lib_dir=/usr/lib
  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

I created a dummy configuration file with the content above, and I just changed the "lib_dir":

implementation=CPython
version=3.12
shared=true
abi3=false
lib_name=python3.12
lib_dir=/foo/bar
pointer_width=64
build_flags=
suppress_build_script_link_lines=false

And used it to cross-compile:

RUSTC_LOG=rustc_codegen_ssa::back::link=info PYO3_CROSS=y \
    PYO3_PTYHON=<buildroot_path>/output/host/bin/python3.12 \
    PYO3_CROSS_LIB_DIR=<buildroot_path>/output/target/usr/lib/ \
    PYO3_CONFIG_FILE=$PWD/test.conf \
    cargo build --target=aarch64-unknown-linux-gnu

And the compilation log shows that the 'faulty' -L /usr/lib option has been replaced by -L /foo/bar:

INFO rustc_codegen_ssa::back::link LC_ALL="C" PATH="/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:/home/user/.local/bin:/home/user/.asdf/shims:/home/user/.asdf/bin:/home/user/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/home/user/.antigen/bundles/robbyrussell/oh-my-zsh/lib:/home/user/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/git:/home/user/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/heroku:/home/user/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/pip:/home/user/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/lein:/home/user/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/command-not-found:/home/user/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/colored-man-pages:/home/user/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/ripgrep:/home/user/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/fd:/home/user/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/asdf:/home/user/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/ssh-agent:/home/user/.antigen/bundles/robbyrussell/oh-my-zsh/plugins/fzf:/home/user/.antigen/bundles/zsh-users/zsh-syntax-highlighting" VSLANG="1033" "/home/user/projects/buildroot/output/host/bin/aarch64-buildroot-linux-gnu-ld" "/tmp/rustclQBU39/symbols.o" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/pyo3_test-5b1692f08f5eee5a.255y9jhu2k5p0jzs.rcgu.o" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/pyo3_test-5b1692f08f5eee5a.2tj0blelfealrdr0.rcgu.o" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/pyo3_test-5b1692f08f5eee5a.4qjukpkxe769efla.rcgu.o" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/pyo3_test-5b1692f08f5eee5a.56t07phfolb0x8z1.rcgu.o" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/pyo3_test-5b1692f08f5eee5a.59chm4am7t2e8o58.rcgu.o" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/pyo3_test-5b1692f08f5eee5a.a5iolrda1a6rbfv.rcgu.o" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/pyo3_test-5b1692f08f5eee5a.bpt1c06x9ej4di4.rcgu.o" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/pyo3_test-5b1692f08f5eee5a.mbopwb5g448jtoi.rcgu.o" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/pyo3_test-5b1692f08f5eee5a.wmqarkbk7966wt3.rcgu.o" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/pyo3_test-5b1692f08f5eee5a.y45k5vkce3jkarj.rcgu.o" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/pyo3_test-5b1692f08f5eee5a.7inrf17h7ly91vp.rcgu.o" "--as-needed" "-L" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps" "-L" "/home/user/projects/pyo3-test/target/debug/deps" "-L" "/home/user/projects/buildroot/output/host/lib/gcc/aarch64-buildroot-linux-gnu/13.3.0" "-L" "/foo/bar" "-L" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib" "-Bstatic" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/libpyo3-335e1ce7b70e6926.rlib" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/libcfg_if-04428f2181350e3e.rlib" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/libmemoffset-9006560f372e224f.rlib" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/libonce_cell-b2bbc0ba8536a9fc.rlib" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/libpyo3_ffi-c39cd969bd5c9b82.rlib" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/liblibc-7aaba065f884b491.rlib" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/libunindent-e30c13f993bd5e23.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libstd-9db51037f7732c7f.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libpanic_unwind-43f7084971578043.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libobject-55e3c3e99d7ea57c.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libmemchr-fb53010b8d947b31.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libaddr2line-6f437829797b59f9.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libgimli-c465d68cd448aa2e.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/librustc_demangle-12979ddb857b6856.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libstd_detect-ecc5f92a35a5dcae.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libhashbrown-09b6240c5d3892f5.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-e35646347e036948.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libminiz_oxide-893df93494354b60.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libadler-297a87c8b999e355.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libunwind-eb6321afc60f0508.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libcfg_if-e65240dca34fcbd0.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/liblibc-4b653d72a90009a1.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/liballoc-58548d24e1f3d56c.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/librustc_std_workspace_core-84c459117cd1fdc9.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libcore-d6e05faaecef4023.rlib" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libcompiler_builtins-c35031b3bb3289ef.rlib" "-Bdynamic" "-lpython3.12" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "--eh-frame-hdr" "-z" "noexecstack" "-L" "/home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib" "-o" "/home/user/projects/pyo3-test/target/aarch64-unknown-linux-gnu/debug/deps/pyo3_test-5b1692f08f5eee5a" "--gc-sections" "-pie" "-z" "relro" "-z" "now" "--verbose"

And there is no more warning for the linker.

This configuration file is generated from the InterpreterConfig struct, and based on the code comments, "lib_dir" should be the directory where the Python library is located. In the current case, "/usr/lib" is not a correct path.

/// Configuration needed by PyO3 to build for the correct Python implementation.
///
/// Usually this is queried directly from the Python interpreter, or overridden using the
/// `PYO3_CONFIG_FILE` environment variable.
///
/// When the `PYO3_NO_PYTHON` variable is set, or during cross compile situations, then alternative
/// strategies are used to populate this type.
#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
pub struct InterpreterConfig {
    [...]
    /// The directory containing the Python library to link against.
    ///
    /// The effectively controls the `cargo:rustc-link-search=native=<path>` value
    /// to add an additional library search path for the linker.
    ///
    /// Serialized to `lib_dir`.
    pub lib_dir: Option<String>,
    [...]
}

Extra question: since I used PYO3_CROSS_LIB_DIR env variable to cross-compile, should not "lib_dir" be filled with the content of this environment variable ?

Steps to Reproduce

If you want to reproduce, here is how to use buildroot to get the cross-compiled python interpreter + cross-toolchain, as well as the simple application code.

simple app code

Here is the code for the tool, a very simple "hello" print:

=> Cargo.toml

[package]
name = "pyo3-test"
version = "0.1.0"
edition = "2021"

[dependencies.pyo3]
version = "0.22.0"
features = ["auto-initialize"]

=> main.rs

use pyo3::prelude::*;

fn main() -> PyResult<()> {
    Python::with_gil(|py| {
        let code = "print(\"Hello !\")";
        py.eval_bound(code, None, None)?;
        Ok(())
    })
}

python interpreter cross-compilation with buildroot

git clone https://gitlab.com/buildroot.org/buildroot.git
cd buildroot

Enable python3 for a basic configuration

echo "BR2_PACKAGE_PYTHON3=y" >> configs/qemu_aarch64_virt_defconfig
make qemu_aarch64_virt_defconfig

Then compile. To be faster, and since only the cross-compilation of python3 is of interest here, we can compile directly the python3 package:

make python3

The build output will be available in output/target directory. We will find:

Buildroot also builds the host version of the same interpreter:

Backtrace

No response

Your operating system and version

Linux 6.6.34-1-MANJARO

Your Python version (python --version)

Python 3.12

Your Rust version (rustc --version)

rustc 1.79.0 (129f3b996 2024-06-10)

Your PyO3 version

0.22.0

How did you install python? Did you use a virtualenv?

Host + cross-compiled interpreter using Buildroot, no virtualenv.

Additional Info

No response

Thalyum commented 1 month ago

I created a draft PR where I suggest a change. As I do not know all the internals, I may have missed something.

I identified 3 ways to fix my issue:

  1. In the pyo3-ffi build script, to ignore the content of the InterpreterConfig
  2. in the function that parses the sysconfigdata, to add a special case when cross-compiling, and ignore LIBDIR
  3. in the function that creates the InterpreterConfig from the parsed sysconfigdata script

I thought solution 3. was better, as solution 1. seems dirty. As for solution 2., I think the function that parses the script does its job perfectly. I believe it is up to the bit that uses the parsed output to handle the special case.

Let me know what you think. In the draft PR, I added a commit (to be removed later obviously) that points to the three parts in the code where I considered making a change.