将 Rust 应用程序与不在运行时链接器搜索路径中的动态库链接

2024-01-15

我有一个共享库,我想将其动态链接到几个单独的二进制 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

如果我将库添加到/lib/x86_64-linux-gnu目录下,应用程序运行没有问题。

有没有办法让 Rust 在与二进制文件相同的目录中或在要在运行时加载的二进制文件目录中的 lib 这样的目录中查找 .so 文件?如果这是不可能的,有没有办法至少让 Rust 插入它所链接的库的绝对路径?

我尝试过设置rpath = true没有效果。


这是一个最小的、可重复的示例 https://stackoverflow.com/help/minimal-reproducible-example表现出与您遇到的相同问题。我创建了一个导出简单加法函数的 C 库。我还创建了一个 Cargo 项目来使用此功能。

dynlink/
├── executable
│   ├── build.rs
│   ├── Cargo.lock
│   ├── Cargo.toml
│   └── 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/main.rs

extern {
    fn from_the_library(a: u8, b: u8) -> u8;
}

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=/home/shep/rust/dynlink/library");
}

Cargo.toml

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

[profile.dev]
rpath = true

经过进一步调查,我要求 Rust 编译器打印出它将使用的链接器参数:

cargo rustc -- --print link-args

这打印出了一堆东西,但重要的一行是:

"-Wl,-rpath,$ORIGIN/../../../../../../.rustup/toolchains/nightly-aarch64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib"

这是链接器的指令,用于将特定值添加到完成的二进制文件的 rpath 中。缺少对我们链接到的动态库的任何引用。回想起来,这可能是有道理的,因为编译器如何知道我们想要将它包含在 rpath 中?

解决方法是向链接器添加另一个指令。有一些有趣的选项(例如$ORIGIN),但为了简单起见,我们将仅使用绝对路径:

cargo rustc -- -C link-args="-Wl,-rpath,/home/shep/rust/dynlink/library/"

生成的二进制文件打印出正确的内容ldd并且无需设置即可运行LD_LIBRARY_PATH:

$ ldd ./target/debug/executable | grep awesome
    libawesome_math.so => /home/shep/rust/dynlink/library/libawesome_math.so (0x0000ffffb1e56000)
    
$ ./target/debug/executable
Adding: 3

转向使其相对,我们可以使用$ORIGIN:

cargo rustc -- -C link-args='-Wl,-rpath,$ORIGIN/../../../library/'

小心逃跑$ORIGIN适合您的 shell,并记住该路径是相对于可执行文件,不是当前工作目录。

也可以看看:

  • 如何在构建脚本中指定链接器标志/参数? https://stackoverflow.com/q/50642574/155423
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 Rust 应用程序与不在运行时链接器搜索路径中的动态库链接 的相关文章

  • 使用参数时内联汇编混乱

    我正在 x86 64 Linux 上试验 Rust 的内联汇编功能 我写了一个简单的程序 调用exit值为 23 的系统调用 feature asm fn main unsafe asm mov 60 rax mov 23 rdi sysc
  • 防止运行测试时优化掉未使用的静态函数

    我正在编写一个将利用 LLVM 的库 通过inkwell https github com TheDan64 inkwell 来 JIT 编译一些函数 这些函数需要能够回调我的代码中的一些 Rust 函数 我让它工作 但我的单元测试不起作用
  • Rust 柴油 orm 查询

    我是生锈和柴油奥姆的新手 我正在尝试在我的查询中执行以下操作 count select order limit 但我收到错误 我正在使用 postgres 数据库 我已在评论中的查询上方添加了确切的错误 这是我的代码 模式 rs table
  • 使用 RPATH 但不使用 RUNPATH?

    这一页 https web archive org web 20120418232524 http labs qt nokia com 2011 10 28 rpath and runpath 说关于图书馆检索的顺序ld so Unless
  • 使用 Read::read_to_string 从 TcpStream 读取会挂起,直到远程端关闭连接

    我正在尝试实施Haskell IRC 机器人教程 https wiki haskell org Roll your own IRC bot在 Rust 中 我在阅读连接后服务器发送给我的内容时遇到一些困难 似乎发生的情况是 我连接并从服务器
  • 特征内的常量表达式?

    我有一个特点 看起来像这样 pub trait Buf
  • 无法将“&Thing”与“Thing”进行比较

    我知道该错误意味着什么 但我无法修复它 我在用着mockers为了测试我的工作 当我尝试验证提供给模拟特征函数的结构参数时 我陷入了困境 简化的代码 cfg test extern crate mockers cfg test extern
  • 允许 Rust 格式中未使用的命名参数!() 系列

    Given format red reset text red RED blue BLUE reset RESET 编译器退出并出现错误 error named argument never used gt example rs 1 47
  • 相同代码的货物构建:虚假的编译时错误?

    我有板条箱A取决于B and B取决于rust nmea https github com Dushistov rust nmea crate 如果我建造箱子A我遇到了很多错误 所有错误都错过了 use std error Error 在构
  • 我可以在运行时选择一个特征对象而不使用 Box 吗?

    我想分支并决定在运行时在函数中使用的 Trait 实现 请参阅poly read在下面的代码示例中 Trait 对象是在 if 表达式的分支臂内部构造的 并且只需要在 if 表达式的生命周期内存在poly read但我需要Box它是因为无法
  • 如何惯用地复制切片?

    在 Go 中 复制切片是标准操作 如下所示 It will figure out the details to match slice sizes dst copy dst n src m 在 Rust 中 我找不到类似的替换方法 我想出的
  • Rust 双与号,&&

    我看到一些代码如下所示 fn test lt a gt a mut a str 我知道 a 是一生 而 是引用 但是我很难理解双重引用 根据我的理解 引用是一个指针 那么 是指向另一个指针还是其他指针的指针 根据我的理解 引用是一个指针 是
  • 我可以在 Rust 中有效地按值返回对象吗?

    我想用函数初始化一个大对象 目前我有 fn initialize mydata mut Vec
  • 如何区分缺少的反序列化字段和空字段?

    我想用Serde https serde rs 将一些 JSON 解析为 HTTP PATCH 请求的一部分 由于 PATCH 请求不传递整个对象 仅传递要更新的相关数据 因此我需要能够区分未传递的值和显式设置为的值null 以及存在的值
  • 类型提示中 _ 的正确术语是什么?

    在 Rust 的类型提示中 可以在注释中使用部分类型 如下所示 let myvec Vec lt gt vec 1 2 3 部分类型注释中下划线的正确术语是什么 我对 Rust 术语以及更多学术类型理论术语感兴趣 我找到了一个一份官方文件
  • 是否可以从 io::stdin() 读取字符而不逐行缓存输入?

    这个问题指的是稳定的Rust版本1 2 0 您可以通过使用单个字节数组并继续读取直到Result成为一个Err 然而 这有一个问题 因为如果您不以 ASCII 字符阅读 就会出现这种情况 如果您要遇到这个问题 最好只分配一个String 并
  • 为什么在迭代过程中需要“&”来解构元组列表?

    当迭代元组列表时 需要使其发挥作用 因此这会起作用 for a b c in hello 1 0 5 world 2 0 2 iter println a b c 但这不会 for a b c in hello 1 0 5 world 2
  • 如何创建静态字符串数组?

    Note这个问题包含 Rust 1 0 之前的语法 代码无效 但概念仍然相关 如何在 Rust 中创建全局静态字符串数组 对于整数 编译如下 static ONE u8 1 static TWO u8 2 static ONETWO sta
  • 循环时,.iter() 与引用 (&) 有何不同?

    在玩 Rust 时 我发现你可以循环Vecs and HashMaps 可能还有其他 通过引用 而不是使用 iter let xs vec 1 2 3 4 5 for x in xs println x x The iter 函数似乎具有相
  • 在 Rust 中,我用什么来与多个线程和一个 writer 共享一个对象?

    当对象有时可能由一个所有者写入时 在多个线程之间共享公共对象的正确方法是什么 我尝试创建一个ConfigurationTrait 对象具有多种获取和设置配置键的方法 我想将其传递给可以读取配置项的其他线程 如果每个人都能写和读 那就加分了

随机推荐