Как избежать «не удается открыть общий объектный файл» при использовании CMake?

Ситуация

  • Мой проект использует CMake и без проблем компилируется в Ubuntu 16.04.

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

  • Все библиотеки общих объектов доступны в одной нестандартной папке (и они мне там нужны).

  • Почему-то одни можно найти, а другие нет.

Что мне нужно

  1. Причина, по которой некоторые общие объекты могут быть найдены, а другие нет. Проект довольно большой со многими файлами CMake. Я пытался найти различия между загружаемыми и не загружаемыми библиотеками, но безуспешно. Любая помощь, которая укажет мне нужное место, приветствуется.
  2. Решение внутри CMake, позволяющее найти все общие объекты.

лдд

Вывод ldd показывает, что можно найти большинство общих объектов. Вот некоторые примеры:

libboost_filesystem.so.1.55.0 => /path/to/libs/boost/lib/libboost_filesystem.so.1.55.0 (0x00007f2ed1fa0000)
libboost_filesystem.so.1.55.0 => /path/to/libs/boost/lib/libboost_filesystem.so.1.55.0 (0x00007f96af1f5000)
libboost_program_options.so.1.55.0 => /path/to/libs/boost/lib/libboost_program_options.so.1.55.0 (0x00007f96aef85000)
libboost_system.so.1.55.0 => /path/to/libs/boost/lib/libboost_system.so.1.55.0 (0x00007f96aed80000)

Некоторых других почему-то не найти. Например:

libboost_iostreams.so.1.55.0 => not found
libboost_chrono.so.1.55.0 => not found

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

Обходные пути уже опробованы

Ниже приведены обходные пути, которые уже успешно работают. Но меня действительно интересуют два пункта в разделе Что мне нужно.


person mz1000    schedule 29.12.2016    source источник
comment
This is what I tried already... - Помогло или нет? Если проблема связана с RPATH, которую можно исправить с помощью LD_LIBRARY_PATH, тогда CMake также поддерживает RPATH, см. обработка CMake RPATH.   -  person Tsyvarev    schedule 30.12.2016
comment
Итак... существует ли libboost_chrono.so.1.55.0 в вашей системе и где?   -  person cen    schedule 30.12.2016
comment
@cen Да, libboost_chrono.so.1.55.0 и все остальные библиотеки Boost находятся в /path/to/libs/boost/lib/. Как упоминалось в вопросе, их также можно загрузить при добавлении пути к переменной среды LD_LIBRARY_PATH.   -  person mz1000    schedule 30.12.2016
comment
@Tsyvarev Да, с LD_LIBRARY_PATH это работает.   -  person mz1000    schedule 30.12.2016
comment
@Tsyvarev Я проверил все переменные CMake RPATH в своем проекте. В файлах CMake ничего не установлено. Согласно статье, по умолчанию все каталоги ссылок будут добавлены в RPATH сборки. Я также сделал это явным, установив SET(CMAKE_SKIP_BUILD_RPATH FALSE). Результат все тот же, какие-то либы находят, какие-то нет. Я также пытался проверить с помощью objdump. Ничего связанного с RPATH нет. Однако он показал RUNPATH со всеми правильными путями.   -  person mz1000    schedule 30.12.2016
comment
Ну, согласно комментарию здесь: stackoverflow.com/questions/8880802/ вы должны установить RPATH самостоятельно. Вы уже пробовали это?   -  person cen    schedule 31.12.2016
comment
@cen Я попробовал, ничего не изменилось. По-видимому, CMAKE_INSTALL_RPATH должен влиять на установку RPATH. Я не устанавливаю приложение, я пытаюсь запустить его из пути сборки.   -  person mz1000    schedule 01.01.2017
comment
Было бы интересно узнать, как вы говорите CMake связать библиотеки, которые не могут быть найдены. Можете ли вы опубликовать соответствующий код?   -  person oLen    schedule 06.01.2017
comment
Я также сталкиваюсь с этой проблемой. Это БЫЛО работать на Linux, затем я немного поработал на Mac, и библиотека, которая дает сбой, использует скрипт режима пользовательского модуля, который раньше был режимом конфигурации.   -  person johnb003    schedule 24.07.2018


Ответы (1)


tldr; Убедитесь, что импортированная библиотека импортирована как SHARED или UNKNOWN, а не как STATIC, и имеет свойство IMPORTED_SONAME.

Вы должны проверить, как импортируется библиотека, которую вы связываете.

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

Например для zlib, вот версия для статических библиотек:

add_library(ZLIB::zlibstatic STATIC IMPORTED)
set_target_properties(ZLIB::zlibstatic PROPERTIES
  IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIG "C"
  IMPORTED_LOCATION_NOCONFIG "${_IMPORT_PREFIX}/lib/libz.a"
)

Однако для динамических библиотек это:

add_library(ZLIB::zlib SHARED IMPORTED)
set_target_properties(ZLIB::zlib PROPERTIES
  IMPORTED_LOCATION_NOCONFIG "${_IMPORT_PREFIX}/lib/libz.so.1.2.11"
  IMPORTED_SONAME_NOCONFIG "libz.so.1"
)

В сценарии режима модуля find_package вы можете подумать, что импортируете статическую библиотеку, когда на самом деле найденная библиотека является .so, поэтому она может использовать неправильные целевые свойства. В режиме конфигурации это маловероятно, потому что это гораздо более явно при определении цели. Однако в режиме модуля (cmake/findXXX.cmake) вы часто определяете эти свойства как результат переменной FIND_PACKAGE_HANDLE_STANDARD_ARGS _LIBRARIES, и трудно сказать, что вы собираетесь получить. Вы можете использовать libFoo.a в поиске, чтобы быть более явным, или поиграть с CMAKE_FIND_LIBRARY_SUFFIXES.

person johnb003    schedule 24.07.2018