Связывание общих библиотек в одном каталоге

Я использую CMake для создания двух общих библиотек (файлы .so). Они встраиваются в отдельные каталоги, но на этапе установки копируются в тот же каталог. Один из них связан с другим. И оба загружаются динамически из другого процесса.

Первая проблема заключается в том, что, по-видимому, CMake не устанавливает rpath для файлов .so в OS X (не тестировалось на других платформах). В CMakeLists.txt у меня есть

set(CMAKE_INSTALL_PREFIX ../dist)
set(MACOSX_RPATH YES)
set(INSTALL_NAME_DIR YES)

И файлы CMakeLists.txt для двух библиотек включаются с помощью

add_subdirectory(./a "${CMAKE_BINARY_DIR}/a")
add_subdirectory(./b "${CMAKE_BINARY_DIR}/b")

Но запуск otool -l в результирующих .so файлах не показывает записи LC_RPATH.

Кроме того, какой путь необходимо указать в RPath (из a), чтобы, когда компоновщик загружает a.so, он мог найти b.so, который находится в том же каталоге (dist/). Исполняемый файл, из которого загружается a, находится в другом месте.

Я пробовал @executable_path/, @executable_path/../, @origin/../, но ни один из них не работает.


person tmlen    schedule 11.02.2015    source источник


Ответы (1)


Первая проблема заключается в том, что, по-видимому, CMake не устанавливает rpath

По умолчанию cmake устанавливает rpath для цели в каталоге сборки (см. проект):

> cmake -H. -B_builds -DBUILD_SHARED_LIBS=ON
> cmake --build _builds
> ls _builds/foo _builds/liba.dylib 
  _builds/foo
  _builds/liba.dylib
> otool -L _builds/foo 
_builds/foo:
  @rpath/liba.dylib (compatibility version 0.0.0, current version 0.0.0)
  ...
> otool -l _builds/foo | grep LC_RPATH -A2
      cmd LC_RPATH
  cmdsize 64
     path /.../_builds (offset 12)

т.е. библиотека загрузится правильно, если вы запустите ее из каталога _builds:

> ./_builds/foo
a: 42

Но запуск otool -l для результирующих файлов .so не показывает запись LC_RPATH.

Кроме того, какой путь необходимо указать в RPath

Я пробовал @executable_path/, @executable_path/../, @origin/../, но ничего не работает.

Это зависит от того, где вы хотите установить свою библиотеку и исполняемый файл. Например, если каталоги назначения одинаковы, вы можете установить только @executable_path:

set(CMAKE_INSTALL_RPATH "@executable_path")
install(TARGETS foo a DESTINATION bin)

См. пример проекта:

> cmake -H. -B_builds -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=_install
> cmake --build _builds --target install
> otool -L _install/bin/foo 
_install/bin/foo:
  @rpath/liba.dylib (compatibility version 0.0.0, current version 0.0.0)
  ...
> otool -l _install/bin/foo | grep LC_RPATH -A2
      cmd LC_RPATH
  cmdsize 32
     path @executable_path (offset 12)

Вы можете проверить правильность загрузки библиотеки из _install:

> ./_install/bin/foo
a: 42

Информация

person Community    schedule 15.02.2015
comment
Он работает с этими настройками, но проблема, похоже, в том, что когда я использую файл цепочки инструментов (-DCMAKE_TOOLCHAIN_FILE=...) для установки альтернативного компилятора, он больше не добавляет RPath и больше не добавляет @rpath/ к именам установки. Решил это, используя опцию -DCMAKE_CXX_COMPILER. - person tmlen; 16.02.2015
comment
@tmlen Вероятно, что-то не так с вашим файлом цепочки инструментов. Обычно нет ничего плохого в настройке компилятора через набор инструментов. - person ; 16.02.2015
comment
@tmlen Я не знаю о причине, но кажется, что здесь виноват set(CMAKE_SYSTEM_NAME Darwin). Вероятно, настройка RPATH сделана в функции, которая устанавливает CMAKE_SYSTEM_NAME, поэтому, если вы принудительно установите эту переменную, некоторый код будет пропущен. - person ; 16.02.2015