Построение простого (hello-world-esque) примера использования опции ld-rpath с $ORIGIN
Примечание: полный рабочий пример сейчас ниже. Оригинальный вопрос следует:
у меня проблемы с использованием ld с $ORIGIN
.
Поскольку я не смог найти полного примера, я решил попробовать написать его сам, чтобы я и другие могли использовать его позже. Как только он заработает, я его приведу в порядок.
я спросил об этом раньше, но я думаю, что мой пост был немного запутанным.
пример проекта создает одну общую библиотеку и один исполняемый файл, который ссылается на указанную библиотеку.
Он очень маленький (3 файла, 22 строки, включая buildscript).
Вы можете скачать проект из здесь
структура файла (перед здание):
-
project/
-
src/
foo.cpp
main.cpp
make.sh
-
project/src/foo.cpp
int foo()
{ return 3; }
project/src/main.cpp
int foo();
#include <iostream>
int main()
{
std::cout << foo() << std::endl;
return 0;
}
project/make.sh
# Make directories:
mkdir -p -v obj
mkdir -p -v lib
mkdir -p -v run
# Build the library:
g++ -c -o obj/foo.o src/foo.cpp -fPIC
g++ -shared -o lib/foo.sh obj/foo.o
# Build the executable:
g++ -c -o obj/main.o src/main.cpp
g++ -o run/main.run obj/main.o -Wl,-rpath,'$ORIGIN/../../lib' -Llib -l:foo.sh
С
2 ответов
(я бы предпочел
[foo.sh]
чем[lib/foo.sh]
но я исправлю это позже).
есть большая часть вашей проблеме:/
в названии останавливает динамический компоновщик от выполнения магии rpath.
(ваш rpath тоже ошибается. Подумайте об этом: из оболочки, если бы Вы были в настоящее время в каталоге, где находится ваш исполняемый файл, как бы вы попали в каталог, где находится ваша библиотека? Здесь вам нужно cd ../lib
. Таким образом, ваш rpath должен быть $ORIGIN/../lib
.)
если вы построили свой объект как libfoo.so
и связан с -Llib -lfoo
, компоновщик будет работать над тем, что вы намеревались, и делать правильные вещи. Но если вы собираетесь использовать необычные соглашения об именах, вам придется помочь:
-
измените строку ссылки для библиотеки, чтобы явно установить SONAME для вашей библиотеки просто
foo.sh
:g++ -shared -Wl,-soname,foo.sh -o lib/foo.sh obj/foo.o
-
исправить путь rpath:
g++ -o run/main.run obj/main.o -Wl,-rpath,'$ORIGIN/../lib' -Llib -l:foo.sh
это полезно для запуска ldd main/main.run
чтобы увидеть, что происходит. В исходном случае неудачи вы увидите что-то вроде:
lib/foo.sh (0xNNNNNNNN)
(отсутствие какого-либо => /some/resolved/path
показывая, что это не сделано никакого разрешения пути). В фиксированном случае, вы увидите что-то вроде:
foo.sh => /your/path/to/run/../lib/foo.sh (0xNNNNNNNN)
это пример связывания относительного пути (с ld) с помощью $ORIGIN
на rpath
.
rpath - это путь (или набор путей), встроенный в двоичные файлы (общие библиотеки (.Итак) и исполняемые).
Эти пути являются основными путями поиска для общих библиотек, с которыми двоичный файл должен быть связан во время выполнения.
$ ORIGIN потенциальная каталога на путь rpath пути.
Он разрешается в каталог содержащий исполняемый файл. (например: $ORIGIN/lib
)
пример проекта создает одну общую библиотеку и один исполняемый файл, который ссылается на указанную библиотеку с помощью rpath
и $ORIGIN
.
Вы можете скачать проект из здесь.
структура файла (перед здание):
-
project/
-
src/
foo.cpp
main.cpp
make.sh
-
project/src/foo.cpp
int foo()
{ return 3; }
project/src/main.cpp
int foo();
#include <iostream>
int main()
{
std::cout << foo() << std::endl;
return 0;
}
project/make.sh
# Make directories:
mkdir -p -v obj
mkdir -p -v lib/dir
mkdir -p -v run
# Build the library:
g++ -c -o obj/foo.o src/foo.cpp -fPIC
g++ -shared -o lib/dir/foo.so -Wl,-soname,foo.so obj/foo.o
# Build the executable:
g++ -c -o obj/main.o src/main.cpp
g++ -o run/main.run obj/main.o -Wl,-rpath,'$ORIGIN/../lib/dir' -Llib/dir -l:foo.so
с project
директория, беги!--12--> (если он не будет работать, обеспечить make.sh
обладает разрешением).
если все прошло нормально, main.run
теперь необходимо загрузить lib/dir/foo.so
при выполнении, независимо от абсолютного пути к project
(вы можете переместить его в любом месте), и независимо от текущего рабочего каталога (вы можете запустить его из любого места).
Примечания:
-
-fPIC
указывает компилятору создавать перемещаемые объектные файлы (объектные файлы сборка в общих библиотеках должна быть перемещаемой). -
-Wl,-soname,<NAME>
добавляет<NAME>
в создаваемую библиотеку. Это должно соответствовать имени для-l
или-l:
параметры при подключении к этой библиотеке. -
-Wl,-rpath,'<PATH>'
добавляет<PATH>
в созданную библиотеку в качестве пути поиска библиотеки времени выполнения (или rpath - см. выше). -
-L
добавить путь к построить-времени список путей поиска библиотеки. (Примечание:rpath
не имеет значения в время сборки,-L
не имеет значения во время выполнения). -
-l:
добавляет имя файла (без пути) библиотеки для ссылки. (Похожие на-l
, за исключением-l:
требуется полное имя файла.
структура файла (после Я использую -l:
который требует полного имени файла библиотеки (среди других причин, легче писать с переменными, когда все функции имеют одинаковый формат имени).
Это более распространенное использование -l
, whereby -l<NAME>
обозначает Либ.так.
ограничения
насколько мне известно (поправьте меня, если я ошибаюсь), нет способа добавить библиотеку внутри подкаталога в пути поиска (за исключением добавления этого каталога в качестве подкаталога). Это справедливо для обоих build-time (-L
) и (-rpath
) пути поиска.
поэтому, если у вас есть две библиотеки с одинаковым именем, но в разных местах, вы не сможете связать их оба. (Надеюсь, я ошибаюсь или что это исправлено).