Подтвердить что ты не робот

CMake - ссылка на библиотеку, загруженную из ExternalProject_add()

Я пытаюсь использовать ExternalProject_add() для загрузки/установки зависимостей. Он устанавливает отлично, но я не могу понять, как на самом деле связывать библиотеки после их загрузки.

Я хочу вызвать target_link_libraries() в только что загруженной библиотеке, но путь к библиотеке зависит от системы.

Если это была системная зависимость, я мог бы просто вызвать find_package() - но пакеты не были установлены по пути поиска по умолчанию. Я не думаю, что вы можете указать путь поиска для find_package в режиме модуля.

Вот фрагмент моего CMakeLists.txt, который не работает:

ExternalProject_Add(
protobuf
URL http://protobuf.googlecode.com/files/protobuf-2.4.1.tar.gz
CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR>
PREFIX ${MYPROJ_SOURCE_DIR}/dependencies
)
find_package(protobuf REQUIRED)
set(LIBS ${LIBS} ${PROTOBUF_LIBRARIES})
target_link_libraries (mybinary ${LIBS})
4b9b3361

Ответ 1

Когда вы используете ExternalProject_Add, вы не можете использовать find_package, так как ничего не найти, когда CMake запускает настройку внешнего проекта.

Итак, если места для библиотек зависят от платформы, вам понадобится условная логика, основанная на вашей платформе. (Я не знаю библиотеки или структуры протобуфа здесь, так что это всего лишь пример, но он должен заставить вас идти в правильном направлении...) Что-то вроде этого:

if(WIN32)
  set(PROTOBUF_LIB_DIR "${MYPROJ_SOURCE_DIR}/dependencies/win"
  set(prefix "")
  set(suffix ".lib")
elseif(APPLE)
  set(PROTOBUF_LIB_DIR "${MYPROJ_SOURCE_DIR}/dependencies/mac"
  set(prefix "lib")
  set(suffix ".a")
else()
  set(PROTOBUF_LIB_DIR "${MYPROJ_SOURCE_DIR}/dependencies/linux"
  set(prefix "lib")
  set(suffix ".a")
endif()

set(PROTOBUF_LIBRARIES
  "${PROTOBUF_LIB_DIR}/${prefix}protobufLib1${suffix}"
  "${PROTOBUF_LIB_DIR}/${prefix}protobufLib2${suffix}")

Конечно, это менее удобно, чем использование find_package. Если вы можете использовать предварительно установленный/предварительно установленный пакет, вы должны использовать find_package. Если вы должны собрать другой пакет из исходного кода как часть вашего проекта, однако, ExternalProject_Add полезен, хотя он не может абстрагировать все детали для вас.

Ответ 2

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

Для получения дополнительной информации см. Полезные переменные CMake.

Например:

  • CMAKE_SHARED_LIBRARY_PREFIX
  • CMAKE_SHARED_LIBRARY_SUFFIX
  • CMAKE_STATIC_LIBRARY_PREFIX
  • CMAKE_STATIC_LIBRARY_SUFFIX

Ответ 3

Поскольку вы загружаете внешний проект, вы уже знаете, где все, потому что вы его просто загрузили, поэтому ему не нужно "находить".

Я работал с add_library. Это мой фактический код, который работает:

ExternalProject_Add(ForexConnectDownload
    PREFIX 3rd_party
    #--Download step--------------
    URL http://fxcodebase.com/bin/forexconnect/1.3.1/ForexConnectAPI-1.3.1-Linux-x86_64.tar.gz
    URL_HASH SHA1=7fdb90a2d45085feb8b76167cae419ad4c211d6b
    #--Configure step-------------
    CONFIGURE_COMMAND ""
    #--Build step-----------------
    BUILD_COMMAND ""
    #--Install step---------------
    UPDATE_COMMAND "" # Skip annoying updates for every build
    INSTALL_COMMAND ""
)

SET(FXCM_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/3rd_party/src/ForexConnectDownload/include)
SET(FXCM_LIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/3rd_party/src/ForexConnectDownload/lib)

add_library(ForexConnect SHARED IMPORTED)
set_target_properties(ForexConnect PROPERTIES IMPORTED_LOCATION ${FXCM_LIB_DIR}/libForexConnect.so)

Оттуда каждая программа, которая зависит от нее, нуждается в add_dependencies и, конечно, target_link_libraries. Например:

include_directories(${FXCM_INCLUDE_DIR})
add_executable(syncDatabase syncDatabase.cpp trader/database.cpp trader/fxcm.cpp)
target_link_libraries(syncDatabase ForexConnect)
add_dependencies(syncDatabase ForexConnectDownload)
  • include_directories - указывает на поиск каталогов там
  • target_link_libraries - просто добавьте свою библиотеку, как вы ее назвали (не переменная)

add_dependencies заставляет его ждать, прежде чем пытаться включить необходимые dirs.

Это трюк для меня. Работает с make -j4. Получите все зависимости правильно.

Ответ 4

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

  • Сделайте свои команды find_package необязательными (удалите 'REQUIRED')
  • Добавьте код условия, чтобы создавать свои цели только в том случае, если find_package успешно завершен.
  • find_package не удастся, и ваши цели не будут созданы в первый раз, но будут созданы внешние проекты.
  • Запустите cmake/make снова, на этот раз find_package будет успешным, и ваши цели будут построены.

Вы можете увидеть эту идиому в действии в https://github.com/biometrics/likely.

Ответ 5

Вы можете использовать команду link_directories для связывания библиотек в определенном каталоге. В вашем случае каталог был создан ваш внешний проект.

ExternalProject_Add(MyExternalLibrary ...)

Добавьте выходной каталог в путь поиска:

link_directories(${CMAKE_BINARY_DIR}/lib/MyExternalLibrary-prefix/lib)

Обязательно добавьте исполняемый файл после, указав каталог ссылок:

add_executable(MyProgram main.c)

Укажите библиотеки, к которым должен быть связан ваш проект:

target_link_libraries(MyProgram ExternalLibraryName)

Не забудьте зависеть от внешнего проекта:

add_dependencies(MyProgram MyExternalLibrary)