Ame*_*meo 6 dynamic-linking ldd dynamic-library rust rust-cargo
我有一个共享库,我想动态链接到几个单独的二进制货物应用程序.我使用-- -L /path/to/dir
格式在链接器中包含它的位置,并且应用程序正确编译,我期望的二进制大小显着减少.但是,在使用时检查生成的二进制文件时ldd
,我收到一条消息,指出无法找到该库:
casey@Gilthar-II:~/bot4/backtester/target/release$ ldd backtester
linux-vdso.so.1 => (0x00007ffc642f7000)
libalgobot_util.so => not found
Run Code Online (Sandbox Code Playgroud)
如果我将库添加到/lib/x86_64-linux-gnu
目录,应用程序运行没有问题.
有没有办法让Rust在与二进制文件相同的目录中查找.so文件,或者在二进制文件目录中的lib目录中查找要在运行时加载的文件?如果那是不可能的,有没有办法至少让Rust插入它所链接的库的绝对路径?
我试过设置rpath = true
没有效果.
She*_*ter 15
这是一个完整的解决方案......
我创建了一个C库,导出一个简单的加法函数.我还创建了一个Cargo项目来使用这个功能.
/scratch
??? executable
? ??? Cargo.lock
? ??? Cargo.toml
? ??? build.rs
? ??? src
? ? ??? main.rs
??? library
??? awesome_math.c
??? libawesome_math.so
Run Code Online (Sandbox Code Playgroud)
awesome_math.c
#include <stdint.h>
uint8_t from_the_library(uint8_t a, uint8_t b) {
return a + b;
}
Run Code Online (Sandbox Code Playgroud)
该库被编译为gcc -g -shared awesome_math.c -o libawesome_math.so
.
src.rs
extern crate libc;
extern {
fn from_the_library(a: libc::uint8_t, b: libc::uint8_t) -> libc::uint8_t;
}
fn main() {
unsafe {
println!("Adding: {}", from_the_library(1, 2));
}
}
Run Code Online (Sandbox Code Playgroud)
build.rs
fn main() {
println!("cargo:rustc-link-lib=dylib=awesome_math");
println!("cargo:rustc-link-search=native=/scratch/library");
}
Run Code Online (Sandbox Code Playgroud)
Cargo.toml
[package]
name = "executable"
version = "0.1.0"
authors = ["An Devloper <an.devloper@example.com>"]
build = "build.rs"
[dependencies]
libc = "*"
[profile.dev]
rpath = true
Run Code Online (Sandbox Code Playgroud)
所有这些都表现出您遇到的相同问题.这称为最小,完整和可验证的示例,您在提问时应提供一个.如果提供了这个,那么这个答案可能是在12小时之前创建的.
进一步调查,我要求Rust编译器打印出它将要使用的链接器args:
cargo rustc -- -Z print-link-args
Run Code Online (Sandbox Code Playgroud)
这打印出了一堆东西,但两条重要的线条都是
"-Wl,-rpath,$ORIGIN/../../../../root/.multirust/toolchains/stable-2016-11-08-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib"
"-Wl,-rpath,/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib"
Run Code Online (Sandbox Code Playgroud)
这些是链接器的指令,用于将特定值添加到已完成二进制文件的rpath中.缺失是对我们链接到的动态库的任何引用.回想起来,这可能是有意义的,因为编译器如何知道我们想要将它包含在rpath中?
解决方法是向链接器添加另一个指令.有一些有趣的选项(比如$ORIGIN
),但为简单起见,我们只使用绝对路径:
cargo rustc -- -C link-args="-Wl,-rpath,/scratch/library/"
Run Code Online (Sandbox Code Playgroud)
并且生成的二进制文件打印正确的东西,ldd
并且运行时没有设置LD_LIBRARY_PATH
:
$ ldd target/debug/executable | grep awesome
libawesome_math.so => /scratch/library/libawesome_math.so (0x00007fe859085000)
$ ./target/debug/executable
Adding: 3
Run Code Online (Sandbox Code Playgroud)
转向使其相对,我们可以使用$ORIGIN
:
cargo rustc -- -C link-args='-Wl,-rpath,$ORIGIN/../../../library/'
Run Code Online (Sandbox Code Playgroud)
小心$ORIGIN
为shell正确转义,并记住路径是相对于可执行文件而不是当前工作目录.
添加Shepmaster 所说的(显然我没有足够的声誉来评论):我不确定何时添加此功能,但至少从Rust 1.20 开始,您可以通过设置环境变量来实现相同的效果RUSTFLAGS
:
$ RUSTFLAGS="-C link-args=-Wl,-rpath,/the/lib/path" cargo build
Run Code Online (Sandbox Code Playgroud)
这可能是不是更方便cargo rustc
,如果,例如,你正在使用的编译脚本,只是调用选项cargo build
。
归档时间: |
|
查看次数: |
4208 次 |
最近记录: |