Как я могу указать rpath в dylib?

У меня есть библиотека: libfoo.dylib. Проблема проиллюстрирована в командах:

$ install_name_tool -id "@rpath/libfoo.dylib" libfoo.dylib
$ install_name_tool -add_rpath "@executable_path/" libfoo.dylib
$ gcc -o foo foo.c -lfoo
$ ./foo #<==== I want this to work
dyld: Library not loaded: @rpath/libfoo.dylib
  Referenced from: ~/./foo
  Reason: image not found
$ install_name_tool -add_rpath "@executable_path/" foo #<=== I dont want to have to specify here where to look for the library
$ ./foo
Hello World

Как мне достичь цели, чтобы не указывать при компиляции исполняемого файла, где находится библиотека?


person chacham15    schedule 19.06.2013    source источник
comment
Думаю, вам нужно скомпилировать и связать libfoo.dylib с -headerpad_max_install_names, чтобы обеспечить достаточно места для имен, которые вы пытаетесь добавить. Как только libfoo.dylib получит имя для установки, foo сможет ссылаться на него независимо от местоположения программы.   -  person jww    schedule 06.09.2016


Ответы (2)


Должен признаться, что я немного смущен тем, чего вы пытаетесь достичь. Весь смысл использования пути поиска runpath заключается в том, что изображения, загружающие библиотеку, определяют путь поиска, который будет использоваться при загрузке библиотеки. Вы просите, чтобы библиотека определила, где исполняемый файл должен ее найти. Этого можно добиться без использования пути поиска пути выполнения, просто установив имя установки dylib в соответствующее значение. Основываясь на вашем конкретном примере, похоже, вы хотите установить имя установки что-то вроде @loader_path/libfoo.dylib. Рассмотрим следующее, что соответствует тем же линиям вашего образца:

$ cat a.c 
int a(void)
{
    return 1;
}
$ cc -install_name "@loader_path/liba.dylib" -dynamiclib -o liba.dylib a.c 
$ cat main.c
#include <stdio.h>

extern int a(void);

int main(int argc, char **argv)
{
    fprintf(stderr, "A: %d\n", a());
    return 0;
}
$ cc -L. -la -o main main.c
$ ./main
A: 1
$ 

Библиотека сообщает исполняемым файлам, которые ссылаются на нее, как ее найти, задавая ее имя установки, и ничего особенного не нужно делать при связывании исполняемого файла, чтобы он нашел библиотеку во время выполнения.

person bdash    schedule 22.06.2013
comment
Да, ваш пример делает то, что я хочу (с установленной библиотекой, где она должна быть найдена, а не с исполняемым файлом). Единственная проблема (и причина, по которой я хотел использовать rpath) заключается в том, что я хочу указать 3 местоположения для поиска: /usr/lib, ../Framework/ и путь к исполняемому файлу, как вы показали. Насколько я читал, это невозможно, используя только имя_установки, верно? - person chacham15; 22.06.2013
comment
Правильно, если вы хотите указать несколько местоположений, вам нужно использовать пути поиска пути выполнения, и, таким образом, исполняемый файл — это тот, который укажет, где найти библиотеку. Обратите внимание, что /usr/lib будет искаться по умолчанию, если библиотека не может быть найдена в местоположении, на которое ссылается команда загрузки, поэтому может не быть необходимости явно указывать это место. - person bdash; 22.06.2013

Единственное, что вам нужно, это сказать компоновщику добавить rpath в ваш двоичный файл. На самом деле вы говорите gcc сообщить об этом компоновщику следующим образом:

$ gcc -o foo foo.c -lfoo -Wl,-rpath=/some/path

Теперь, если вы используете objdump, чтобы увидеть, что там:

$ objdump -x ./foo | less

Вы увидите под Dynamic Section что-то вроде RPATH /some/path.

Если необходимость вводить один и тот же -Wl,-rpath=... слишком громоздка, ld принимает вариант @file (я не знаю насчет dyld, но полагаю, что и он тоже):

$ echo "-rpath=/some/path" > ./ld-options
$ gcc ./foo.c -o foo -Wl,@ld-options
person rectummelancolique    schedule 20.06.2013
comment
Думаю, мне следовало объяснить немного подробнее, но дело в том, что у меня много компилируемых исполняемых файлов и только одна библиотека. Я хочу сохранить команду для создания исполняемого файла в пределах 1 строки, чтобы было легко видеть предупреждения. Добавление rpath=... к каждой исполняемой команде компиляции делает команду очень длинной и выходит за отметку в 1 строку. Это скорее вопрос удобства, чем необходимости. - person chacham15; 20.06.2013
comment
не сработало, поэтому я попробовал оригинальный способ: ld: unknown option: -rpath=@executable_path/ - person chacham15; 20.06.2013
comment
Эти инструкции, по-видимому, предназначены для GCC и GNU binutils, а не для цепочки инструментов OS X. Вот почему такие варианты, как -Wl,-rpath=/foo до gcc, выдают ошибку. - person bdash; 22.06.2013