Вот полное решение ...
Я создал библиотеку C экспортирующей простую функцию сложения. Я также создал проект Cargo для использования этой функции.
/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
Делая все это проявляли его та же проблема, что и вы. Это называется Minimal, Complete, and Verifiable Example, и вы должны указать его, задав вопрос. Если бы это было предусмотрено, этот ответ мог быть создан за 12 часов до этого.
Исследуя дальше, я спросил Rust компилятор, чтобы распечатать компоновщика арг он собирался использовать:
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/'
Будьте осторожны, чтобы избежать $ORIGIN
правильно для вашей оболочки и помните, что путь относительно исполняемый файл, а не текущий рабочий каталог.
Добавляет ли путь к '/ etc/ld.so.conf' и работает' ldconfig' не для вас? (Или не удалось установить переменную среды LD_LIBRARY_PATH?) – BurntSushi5
* Есть ли способ заставить Rust искать .so файлы * - это не что-то о Rust после создания двоичного файла; это зависит от ОС и исполняемых загрузчиков. Установка 'rpath' * - это то, что может контролировать Rust (более точно, что Rust указывает на компоновщик). – Shepmaster
* есть способ, по крайней мере, получить Rust, чтобы вставить абсолютный путь библиотеки, с которой он был связан *, - это то, что должно быть rpath. Можете ли вы попробовать [распечатать rpath исполняемого файла] (http://stackoverflow.com/a/6348364/155423)? Вы также можете попробовать «очистить груз» и «сборку грузов». Затем проверьте, передается ли опция «rpath» при соединении с исполняемым файлом. – Shepmaster