install_name_tool для обновления исполняемого файла для поиска dylib в Mac OS X

У меня есть динамическая библиотека libtest.dylib, установленная в /PATH/lib, и исполняемый двоичный файл myapp, который использует dylib, установленный в /PATH/bin.

Я могу запустить myapp, чтобы найти dylib следующим образом (Можно ли использовать DYLD_LIBRARY_PATH в Mac OS X? И каков алгоритм поиска в динамической библиотеке?):

DYLD_LIBRARY_PATH="/PATH/lib" myapp 

Думаю, я могу использовать install_name_tool для обновления библиотеки и исполняемого файла, чтобы библиотеку можно было найти с помощью rpath. Я использовал подсказки в этом сообщении - Как я могу указать rpath в дилибе?.

В lib я выполнил эту команду, чтобы добавить rpath.

install_name_tool -id "@rpath/libtest.dylib" libtest.dylib
install_name_tool -add_rpath "@executable_path/../lib/" libtest.dylib

В корзине я выполнил install_name_tool -add_rpath "@executable_path/../lib/" myapp.

Однако, когда я выполнил myapp в каталоге bin, у меня появляются сообщения об ошибках.

dyld: Library not loaded: libtest.dylib
  Referenced from: /PATH/bin/./myapp
  Reason: image not found
Trace/BPT trap: 5

otool -l myapp показывает, что rpath правильно обновлен в myapp.

Load command 16
          cmd LC_RPATH
      cmdsize 40
         path @executable_path/../lib/ (offset 12)

То же самое и с libtest.dylib.

Load command 13
          cmd LC_RPATH
      cmdsize 40
         path @executable_path/../lib/ (offset 12)

Что может быть не так?

ДОБАВЛЕН

Конечно, я могу использовать cc -install_name во время компиляции и компоновки, но я хотел знать, как сделать то же самое, что и при изменении сгенерированного dylib и исполняемого двоичного файла.

Из библиотеки:

cc -install_name "@loader_path/../lib/libtest.dylib" -dynamiclib -o libtest.dylib test.c

Или имя_установки может использовать @rpath:

cc -install_name "@rpath/libtest.dylib" -dynamiclib -o libtest.dylib test.c

Из корзины:

cc -I../lib -c main.c
cc -o main main.o ../lib/libtest.dylib -Wl,-rpath -Wl,@loader_path/../lib

Или всего одна строчка:

cc -I../lib -L../lib -o main main.c -ltest -Wl,-rpath -Wl,@loader_path/../lib

person prosseek    schedule 30.11.2015    source источник


Ответы (1)


В otool -l я проанализировал, что нужно добавить или изменить из исходной библиотеки и двоичного файла.

Дилиб

Изменение в id:

Load command 2 <-- OLD
          cmd LC_ID_DYLIB
      cmdsize 40
         name libtest.dylib (offset 24)
   time stamp 1 Wed Dec 31 18:00:01 1969

Load command 2 <-- NEW
          cmd LC_ID_DYLIB
      cmdsize 64
         name @loader_path/../lib/libtest.dylib (offset 24)

Это команда для выполнения изменения:

install_name_tool -id "@loader_path/../lib/libtest.dylib" libtest.dylib 

Или используйте rpath:

install_name_tool -id "@rpath/libtest.dylib" libtest.dylib

Исполняемый файл

Есть два изменения: rpath и load_dylib

Load command 12 <-- OLD
          cmd LC_LOAD_DYLIB
      cmdsize 40
         name libtest.dylib (offset 24)

Load command 12 <-- NEW
          cmd LC_LOAD_DYLIB
      cmdsize 64
         name @loader_path/../lib/libtest.dylib (offset 24)

Это команда для выполнения изменения

install_name_tool -change libtest.dylib @loader_path/../lib/libtest.dylib myapp 

Также мне нужно было добавить rpath

Load command 14
          cmd LC_RPATH
      cmdsize 32
         path @loader_path/../lib (offset 12)

Это команда для выполнения добавления:

 install_name_tool -add_rpath "@loader_path/../lib" myapp

Идея

Бинарный файл пытается найти библиотеку, он знает, где она находится, начиная с install_name_tool -add_rpath "@loader_path/../lib" myapp. Он загружает библиотеку, и идентификатор библиотеки равен @rpath/libtest.dylib, где @rpath установлен в @loader_path/../lib в исполняемом двоичном файле, чтобы обеспечить соответствие.

Ссылка

Cmake

При использовании CMake мы можем автоматизировать процесс с помощью следующего дополнения в файле CMakeLists.txt.

Library

Должен быть добавлен идентификатор.

# https://cmake.org/pipermail/cmake/2006-October/011530.html
SET_TARGET_PROPERTIES (test
  PROPERTIES BUILD_WITH_INSTALL_RPATH 1
             INSTALL_NAME_DIR "@rpath"
  )
Executable

Необходимо указать rpath:

SET(CMAKE_INSTALL_RPATH "@loader_path/../lib/libtest.dylib")
person prosseek    schedule 30.11.2015
comment
Кажется, что атрибуты в dylib не имеют большого значения во время выполнения. Они используются только во время сборки для копирования атрибутов из dylib в исполняемый файл. В случае, когда у вас уже есть исполняемый файл, связанный с dylib, но вам нужно изменить пути, тогда достаточно отредактировать только исполняемый файл, чтобы установить LC_LOAD_DYLIB и, необязательно, LC_RPATH. Второй нужен только в том случае, если в первом есть @rpath. - person v.shashenko; 06.07.2017