2016-11-15 121 views
3

我有一个共享库,我想动态链接到几个单独的二进制货运应用程序。我使用-- -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没有效果。

+2

是否将路径添加到'/ etc/ld.so.conf'并运行'ldconfig'不适合你? (或者失败了,设置'LD_LIBRARY_PATH'环境变量?) – BurntSushi5

+2

*是否有办法让Rust查找.so文件* - 这不是关于Rust创建二进制文件后的情况;这取决于操作系统和可执行的加载器。设置'rpath' *是Rust可以控制的东西(更准确地说,Rust指示链接器处理)。 – Shepmaster

+1

*有没有办法让Rust至少插入与它链接的库的绝对路径* - 这就是rpath应该是的。你可以尝试[打印可执行文件的路径](http://stackoverflow.com/a/6348364/155423)?您可能还想尝试“货物清洁”和“货物构建 - 动词”。然后查看链接可执行文件时是否传递了'rpath'选项。 – Shepmaster

回答

7

下面是一个完整的解决方案...

我创建了一个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,并且请记住该路径是相对于可执行文件而不是当前工作目录。

+0

感谢您提供的信息非常丰富!您简化并澄清了几个小时将互联网拖拽到一个精心编写的格式中。 只有一个问题:$ ORIGIN是相对于二进制文件的位置还是正在编译的源代码的位置? – Ameo

+1

@Ameo'$ ORIGIN'是相对于可执行文件。 – Shepmaster

2

添加到what Shepmaster said(显然我没有足够的信誉评论):我不知道什么时候加入这个功能,但作为至少锈1.20的,你可以通过设置达到同样的效果环境变量RUSTFLAGS

$ RUSTFLAGS="-C link-args=-Wl,-rpath,/the/lib/path" cargo build 

如果,例如,您正在使用生成脚本,只是调用cargo build这可能比cargo rustc选项更方便。

相关问题