Итак, проект, над которым я работаю, использует несистемный каталог для хранения некоторых DLL, используемых кодом. Я не хочу помещать их в системные каталоги, поэтому исполняемые файлы имеют rpath, установленный для поиска DLL. Однако, поскольку добавляется все больше и больше библиотек, теперь есть DLL, которые зависят от других DLL в этом каталоге.
Эти библиотеки не могут найти библиотеки DLL, от которых они зависят, поскольку они не находятся в каталоге, который ищет компоновщик, например, в системном каталоге.
Есть ли способ заставить DLL искать этот конкретный несистемный каталог? Например, rpath? И как это сделать с библиотекой? Система сборки, используемая для проекта, — CMake, если это поможет в ответе.
Этот ответ не работает, так как в библиотеке нет тега rPath:https://unix.stackexchange.com/a/272286/4193
Я рассматривал возможность использования LD_LIBRARY_PATH
, и это работает, но это раздражает при наборе текста и не очень здорово, когда другие люди используют приложение. Если есть способ добавить тег rPath
в библиотеку, это был бы лучший вариант.
Приветствуются ссылки на предыдущие соответствующие вопросы и ответы.
решение1
Существует ли rpath для динамически подключаемых библиотек?
Да, есть. Вы можете использовать -Wl,-rpath
с общими объектами ELF так же, как и с исполняемыми файлами ELF. Клонируйте небольшой пример, который я выложил
здесь:
git clone https://gist.github.com/ardrabczyk/6aeb8545c9b754d6b15be390af4bdff0
Запустите make
для компиляции. Проверьте, какие библиотеки необходимы main
исполняемому файлу ELF:
$ readelf -d ./main
Dynamic section at offset 0xe30 contains 22 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libtwo.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [.]
(...)
И проверьте, какие библиотеки нужны libtwo.so
:
$ readelf -d ./libtwo.so
Dynamic section at offset 0xe38 contains 22 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libone.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [libs]
(...)
Как вы можете видеть, оба main
и libtwo.so
нуждаются в некоторых общих объектах и оба имеют установленный rpath. Вам не нужно устанавливать LD_LIBRARY_PATH для запуска ./main:
$ ./main
I'm in bar()
main всегда будет искать свою зависимость libtwo.so в .
текущем каталоге, а libtwo.so в свою очередь всегда будет искать свою зависимость libone.so в libs
каталоге. Если libs
отсутствует, ./main не запустится:
$ mv libs libs.bak
$ ./main
./main: error while loading shared libraries: libone.so: cannot open shared object file: No such file or directory
Восстановить:
$ mv libs.bak libs
$ ./main
I'm in bar()
решение2
Поскольку вы не хотите рассматривать его как часть системы, используйте его таким, какой он есть: пользовательским приложением!
Если вы добавите ~/.local/lib/
в свой LD_LIBRARY_PATH
, вы можете разместить все там. Просто создайте частичную структуру FHS под ~/.local/
какмусорное ведро,и т. д.,либиделиться. Таким образом, вам не нужно вызывать программу с предшествующей переменной environmemt. Все остальные системы просто должны будут добавить этот каталог к своей переменной окружения library path. Очень аккуратно и unixish.
Если вы отвергнете и это решение, то останется только одна возможность. Либо вы используете фиксированный путь, который ожидается в каждой системе, либо переменную окружения, которая содержит путь и также ожидается.