Динамическое связывание иногда нелегко. Сообщение об ошибке Library not loaded: @rpath/libstd-d00eaa6834e55536.dylib
довольно ясно. У вас проблема с DYLD_LIBRARY_PATH
(macOS).
TL; DR
Ваш DYLD_LIBRARY_PATH
не содержит пути к библиотекам Rust. Положите следующее в ваш ~/.bash_profile
:
source "$HOME/.cargo/env"
export RUST_SRC_PATH="$(rustc --print sysroot)/lib/rustlib/src/rust/src"
export DYLD_LIBRARY_PATH="$(rustc --print sysroot)/lib:$DYLD_LIBRARY_PATH"
Объяснение
Я следовал структуре вашего проекта, за исключением одного - я удалил _
(my_bin
-> mybin
, ...).
cargo run --bin mybin
против target/debug/mybin
Прежде всего, проверьте, что otool -L target/debug/mybin
говорит:
target/debug/mybin:
/Users/robertvojta/Work/bar/target/debug/deps/libmylib.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libstd-d4fbe66ddea5f3ce.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
Обратите внимание на @rpath
. Если вы не знаете, что это такое, я бы порекомендовал прочитать сообщения Майка Эша:
Также запустите man dlopen
и прочитайте раздел SEARCHING
. Копировать и вставлять здесь довольно долго, поэтому просто первое предложение:
dlopen () ищет совместимый файл Mach-O в каталогах, заданных набором переменных среды и текущим рабочим каталогом процесса.
Вы узнаете о DYLD_LIBRARY_PATH
и других переменных среды.
Какой вывод команды echo $DYLD_LIBRARY_PATH
в вашей оболочке? Я предполагаю, что он пуст / не содержит пути к библиотекам Rust.
Добавьте следующие строки в ваш mybin:main.rs
...
println!(
"DYLD_LIBRARY_PATH={}",
std::env::var("DYLD_LIBRARY_PATH").unwrap_or("N/A".to_string())
);
... и запустить cargo run --bin mybin
. Вы должны увидеть что-то вроде этого:
DYLD_LIBRARY_PATH=~/.rustup/toolchains/stable-x86_64-apple-darwin/lib
cargo run
добавляет эту переменную среды для вас.
Откуда вы можете получить правильное значение? Запустите rustc --print sysroot
и добавьте /lib
к выводу.
Если вы хотите запустить mybin
напрямую (без cargo
), вы можете сделать это следующим образом:
DYLD_LIBRARY_PATH="$(rustc --print sysroot)/lib:$DYLD_LIBRARY_PATH" target/debug/mybin
Python скрипт
Добавить похожие строки в ваш run.py
скрипт:
import os
print('DYLD_LIBRARY_PATH: {}'.format(os.environ.get('DYLD_LIBRARY_PATH', 'N/A')))
Если печатается N/A
, DYLD_LIBRARY_PATH
не установлено. Вы можете исправить это аналогичным образом:
DYLD_LIBRARY_PATH="$(rustc --print sysroot)/lib:$DYLD_LIBRARY_PATH" python run.py
macOS и защита целостности системы
Имейте в виду, что вы не можете использовать системный Python для этого ...
$ echo $DYLD_LIBRARY_PATH
~/.rustup/toolchains/stable-x86_64-apple-darwin/lib:
$ /usr/bin/python run.py
DYLD_LIBRARY_PATH: N/A
Traceback (most recent call last):
File "./run.py", line 21, in <module>
lib = cdll.LoadLibrary(lib_path)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 443, in LoadLibrary
return self._dlltype(name)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 365, in __init__
self._handle = _dlopen(self._name, mode)
OSError: dlopen(./target/debug/libmylib.dylib, 6): Library not loaded: @rpath/libstd-d4fbe66ddea5f3ce.dylib
Referenced from: /Users/robertvojta/Work/bar/target/debug/libmylib.dylib
Reason: image not found
... но вы можете использовать один, установленный через brew
, например ...
$ echo $DYLD_LIBRARY_PATH
/Users/robertvojta/.rustup/toolchains/stable-x86_64-apple-darwin/lib:
$ /usr/local/bin/python run.py
DYLD_LIBRARY_PATH: /Users/robertvojta/.rustup/toolchains/stable-x86_64-apple-darwin/lib:
Причина в SIP. SIP был введен в El Capitan и может быть на вашем пути. Вы можете испытать такие вещи, как:
$ env | grep DYLD
$ echo $DYLD_LIBRARY_PATH
/Users/robertvojta/.rustup/toolchains/stable-x86_64-apple-darwin/lib:
Вот страница описания SIP . SIP защищает папки типа /usr
, /bin
, /sbin
, но не защищает /usr/local
, например.
Что это значит? SIP делает много вещей, но одна из них разрушает значение DYLD_LIBRARY_PATH
. Шебанг линии, как ...
#!/usr/bin/env python
#!/usr/bin/python
... не будет работать для вас. Вы должны использовать интерпретатор Python, который не установлен в системных (и защищенных) папках. Установите один с помощью brew
, установите Anaconda, ...
SIP можно отключить, но НЕ сделать это.
Другой способ исправить это - заменить @rpath
в вашем mylib
на полный путь через install_name_tool
(man install_name_tool
). Дополнительная информация в Почему для библиотек Mach-O в Mac Os X необходимы install_name_tool и otool? .
Пример:
$ otool -L target/debug/mybin
target/debug/mybin:
/Users/robertvojta/Work/bar/target/debug/deps/libmylib.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libstd-d4fbe66ddea5f3ce.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
$ install_name_tool -change @rpath/libstd-d4fbe66ddea5f3ce.dylib /Users/robertvojta/.rustup/toolchains/stable-x86_64-apple-darwin/lib/libstd-d4fbe66ddea5f3ce.dylib target/debug/libmylib.dylib
$ otool -L target/debug/libmylib.dylib
target/debug/libmylib.dylib:
/Users/robertvojta/Work/bar/target/debug/deps/libmylib.dylib (compatibility version 0.0.0, current version 0.0.0)
/Users/robertvojta/.rustup/toolchains/stable-x86_64-apple-darwin/lib/libstd-d4fbe66ddea5f3ce.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
$ /usr/bin/python run.py
DYLD_LIBRARY_PATH: N/A
Hallo
Как видите, @rpath
сейчас нет, DYLD_LIBRARY_PATH
не установлен, но работает (Hallo
выводится через hallo
функцию из libmylib.dylib
) с системным интерпретатором Python.
Помните об одном: динамические библиотеки macOS ведут себя иначе, чем, например, в Linux.
Если вы не хотите с ним связываться, вы можете изменить mylib
crate-type
на ["rlib", "cdylib"]
, но это не то, что вы, вероятно, хотите.