CMake - ссылка на библиотеку, загруженную из ExternalProject_add () - PullRequest
44 голосов
/ 15 июня 2011

Я пытаюсь использовать 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})

Ответы [ 5 ]

20 голосов
/ 29 марта 2015

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

У меня все работает с 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 заставляет его подождать, прежде чем включать необходимые каталоги.

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

19 голосов
/ 15 июня 2011

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

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

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 будет полезен, даже если он не сможет абстрагировать все детали для вас.

18 голосов
/ 12 июля 2013

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

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

Например:

  • CMAKE_SHARED_LIBRARY_PREFIX
  • CMAKE_SHARED_LIBRARY_SUFFIX
  • CMAKE_STATIC_LIBRARY_PREFIX
  • CMAKE_STATIC_LIBRARY_SUFFIX
4 голосов
/ 03 марта 2013

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

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

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

4 голосов
/ 20 марта 2012

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

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)
...