将Rust应用程序与不在运行时链接程序搜索路径中的动态库链接
我有一个共享库,我想动态链接到几个单独的二进制货运应用程序。我使用-- -L /path/to/dir
格式将其位置包含在链接器中,并且应用程序编译正确,并且我期望的二进制大小显着下降。然而,检查使用ldd
所生成的二进制的时候,我得到一个消息说,图书馆找不到:将Rust应用程序与不在运行时链接程序搜索路径中的动态库链接
[email protected]:~/bot4/backtester/target/release$ ldd backtester
linux-vdso.so.1 => (0x00007ffc642f7000)
libalgobot_util.so => not found
如果我的库添加到/lib/x86_64-linux-gnu
目录,应用程序运行没有问题。
有没有办法让锈找.so文件在同一目录中的二进制或像二进制的lib目录的目录,以在运行时加载?如果这是不可能的,是否有办法让Rust至少插入它所链接的库的绝对路径?
我试过设置rpath = true
没有效果。
下面是一个完整的解决方案...
我创建了一个C库导出一个简单的加法功能。我还创建了一个货物项目来使用这个功能。
/scratch
├── executable
│ ├── Cargo.lock
│ ├── Cargo.toml
│ ├── build.rs
│ ├── src
│ │ ├── main.rs
└── library
├── awesome_math.c
└── libawesome_math.so
awesome_math.c
#include <stdint.h>
uint8_t from_the_library(uint8_t a, uint8_t b) {
return a + b;
}
库被编译为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));
}
}
build.rs
fn main() {
println!("cargo:rustc-link-lib=dylib=awesome_math");
println!("cargo:rustc-link-search=native=/scratch/library");
}
Cargo.toml
[package]
name = "executable"
version = "0.1.0"
authors = ["An Devloper <[email protected]>"]
build = "build.rs"
[dependencies]
libc = "*"
[profile.dev]
rpath = true
做这一切exhib的它与你经历的同样的问题。 这叫做Minimal, Complete, and Verifiable Example,你应该在提问时提供一个。如果提供了这个答案,这个答案可能在12小时前创建。
进一步调查,我问锈编译器打印出来的连接ARGS它要使用:
cargo rustc -- -Z print-link-args
此打印出来了一堆东西,但两个重要的线是
"-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"
这些是指令链接器将特定值添加到完成的二进制文件的路径。缺少的是对我们链接到的动态库的任何引用。回想起来,这可能是有道理的,因为编译器如何知道我们想将它包含在rpath中?
一个解决办法是另一个指令添加到链接器。有有趣的选项(如$ORIGIN
),但为了简单起见,我们将只使用绝对路径:
cargo rustc -- -C link-args="-Wl,-rpath,/scratch/library/"
产生的二进制打印正确的事情ldd
和运行,而无需设置LD_LIBRARY_PATH
:
$ ldd target/debug/executable | grep awesome
libawesome_math.so => /scratch/library/libawesome_math.so (0x00007fe859085000)
$ ./target/debug/executable
Adding: 3
谈到使得它相对的,我们可以用$ORIGIN
:
cargo rustc -- -C link-args='-Wl,-rpath,$ORIGIN/../../../library/'
要小心为您的shell正确转义$ORIGIN
,并且请记住该路径是相对于可执行文件而不是当前工作目录。
感谢您提供的信息非常丰富!您简化并澄清了几个小时将互联网拖拽到一个精心编写的格式中。 只有一个问题:$ ORIGIN是相对于二进制文件的位置还是正在编译的源代码的位置? – Ameo
@Ameo'$ ORIGIN'是相对于可执行文件。 – Shepmaster
添加到what Shepmaster said(显然我没有足够的信誉评论):我不知道什么时候加入这个功能,但作为至少锈1.20的,你可以通过设置达到同样的效果环境变量RUSTFLAGS
:
$ RUSTFLAGS="-C link-args=-Wl,-rpath,/the/lib/path" cargo build
如果,例如,您正在使用生成脚本,只是调用cargo build
这可能比cargo rustc
选项更方便。
是否将路径添加到'/ etc/ld.so.conf'并运行'ldconfig'不适合你? (或者失败了,设置'LD_LIBRARY_PATH'环境变量?) – BurntSushi5
*是否有办法让Rust查找.so文件* - 这不是关于Rust创建二进制文件后的情况;这取决于操作系统和可执行的加载器。设置'rpath' *是Rust可以控制的东西(更准确地说,Rust指示链接器处理)。 – Shepmaster
*有没有办法让Rust至少插入与它链接的库的绝对路径* - 这就是rpath应该是的。你可以尝试[打印可执行文件的路径](http://stackoverflow.com/a/6348364/155423)?您可能还想尝试“货物清洁”和“货物构建 - 动词”。然后查看链接可执行文件时是否传递了'rpath'选项。 – Shepmaster