#linux #c #разделяемые_библиотеки
Есть библиотека libsvsynth.so, идущая в комплекте с программой, которая её использует.
Т.к. библиотека не устанавливается в систему (программа задумывалась, как физически
переносимая), то к путь к ней в функции dlopen описывается как ./libsvsynth.so.
При использовании:
$ ./prog
Всё работает - библиотека подключается. Однако, если написать
$ ./parent_dir/prog
То библиотека программой обнаружена не будет (как я понял, библиотека будет искаться
в вызываемом каталоге)
Что же нужно сделать для того, чтобы программу можно было запускать без проблем из
любого места, а не только из каталога с бинарником+библиотекой?
Ответы
Ответ 1
наиболее простой вариант: скрипт-обёртка
можете рядом с программой приложить скрипт примерно такого содержания:
#!/bin/sh
cd "$(dirname "$0")" && ./prog
присвоить ему биты исполнимости:
$ chmod +x путь/к/этому/скрипту
и вызывать его из любого места файловой системы, указывая хоть относительный, хоть
абсолютный путь.
более сложный вариант:
не линковать, а динамически подгружать нужную библиотеку в процессе работы программы,
предварительно получив путь к выполняемому файлу и дополнив его путём к библиотеке.
Ответ 2
Развивая идею, предложенную в дополнении к ответу Александра Баракина, набросал пример
функции, которая загружает динамическую библиотеку по пути файла, относительного текущего
выполняемого файла вне зависимости от рабочего каталога или переменных окружения.
void* load_library(const char* r_path)
{
if (r_path[0] == '/')
return dlopen(r_path, RTLD_LAZY);
char a_path[PATH_MAX] = {0};
readlink("/proc/self/exe", a_path, sizeof a_path);
char* last_slash = strrchr(a_path, '/');
if (last_slash == NULL) {
// в иных Unix-системах надо по-другому определять текущий бинарник
errno = ENOSYS;
return NULL;
}
strcpy(last_slash + 1, r_path);
return dlopen(a_path, RTLD_LAZY);
}
Ответ 3
При работе с библиотеками можно использовать возможности компилятора и указать путь
где будет происходить поиск библиотеки
gcc -Wl,rpath,/usr/local/lib
если нет возможности слинковать программу с нужными путями можно использовать переменую
LD_LIBRARY_PATH=/usr/local/lib
указав в ней пути поиска библиотеки.
Ответ 4
Итак, проблема была решена следующим образом: к программе всё же пришлось добавить
shell-скрипт (start.sh) следующего содержания:
#!/bin/bash
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
done
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
cd $DIR
./prog $@
Затем делаем chmod +x ./start.sh и запускаем из любого каталога в системе