Closed Ucag closed 1 week ago
After really searching for hours, I finally solve this issue. Maybe this can be a documentation PR? I'm not sure. For helping people meet the same issue. The solution is below:
TL;DR;
Add a build.rs
to root of the project aligned to the Cargo.toml
file.
use std::process::Command;
pub fn main(){
let python_inline_script = "from distutils import sysconfig;print(sysconfig.get_config_var('LIBDIR'))";
let output = Command::new("python")
.arg("-c")
.arg(python_inline_script)
.output()
.expect("Failed to execute command");
if !output.status.success() {
panic!("Python command failed");
}
let python_lib_path = String::from_utf8_lossy(&output.stdout);
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", python_lib_path);
}
Then remove the target
directory and run cargo build
.
For people who's interested in what's going on here:
The build script just simply add rpath
to the linker. From the output of command
otool -L target/debug/call_python_from_rust
we can see that the built binary using @rpath
to find used dynamic libraries. Here is the point, rpath
differs from LD_LIBRARY_PATH
. Value of rpath
will be hard coded into binary header. Thus, we need to provide linker the right rpath
.
Actually, rpath
should be searched in system library path. This problem won't happen if I use python lib shipped with macOS. It just happens with anaconda. I searched a lot find out that many people have the similar issue when use with anaconda.
There are some other ways to tell the system to search for the library, like use DYLD_FALLBACK_LIBRARY_PATH
, but it's not easy to use. For details, see issue 1800.
Actually, this still does not totally solve the issue. Because the library path is hard coded, when publish the compiled binary to others, it will be a problem. This is only a just fine way to make things work.
I can successfully build the executable but it failed when run it. Error below occurs:
The code is copied from the doc.
main.rs
Cargo.toml
I can build it without any error reported, but the error appears at runtime. For inspecting the built binary, use command below