CMake – 链接到从ExternalProject_add()下载的库

我正在尝试使用ExternalProject_add()来下载/安装依赖关系。 它安装正常,但我不知道如何实际上链接库后,他们被下载。

我想调用刚刚下载的库的target_link_libraries(),但是库的path会因系统而异。

如果这是一个系统依赖项,我可以调用find_package() – 但是软件包没有安装在默认searchpath中。 我不认为你可以在模块模式下指定find_package的searchpath。

下面是我的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}) 

当你使用ExternalProject_Add时,你不能使用find_package,因为当CMake运行来configuration外部项目时没有什么可以find的。

所以,如果库的位置因平台而异,则需要基于您的平台的条件逻辑。 (我不知道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不太方便。 如果您可以使用预先构build的/预先安装的软件包,则应该使用find_package。 如果您必须从源代码构build其他包作为您的项目的一部分,虽然ExternalProject_Add是有用的,即使它无法为您抽象掉所有细节。

要在上面扩展DLRdave答案,您不需要为静态库设置手动前缀和后缀,因为CMAKE为每个平台提供了正确的variables。

有关更多信息,请参阅CMake有用variables 。

例如:

  • CMAKE_SHARED_LIBRARY_PREFIX
  • CMAKE_SHARED_LIBRARY_SUFFIX
  • CMAKE_STATIC_LIBRARY_PREFIX
  • CMAKE_STATIC_LIBRARY_SUFFIX

因为你正在下载外部项目,所以你已经知道了所有的东西,因为你只是下载了它,所以它不需要'find'。

我得到它与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 – 告诉它在那里search目录
  • target_link_libraries – 只需添加你的库,就像你命名它(不是一个variables)

add_dependencies使它在尝试包含所需的dirs之前等待。

这对我来说是诀窍。 与make -j4一起使用。 获得所有的依赖关系。

另一个你可以用来解决这个问题的成语:

  1. 使您的find_package命令可选(删除'必需的')
  2. 如果find_package成功,则添加一些条件代码以仅构build您的目标。
  3. find_package将会失败,你的目标将不会被第一次build立,但是外部项目将被build立。
  4. 再次运行cmake / make,这次find_package会成功,你的目标将被build立。

你可以在https://github.com/biometrics/likely看到这个习惯用法。;

您可以使用link_directories命令链接特定目录中的库。 在你的情况下,目录是你的外部项目正在build立。

 ExternalProject_Add(MyExternalLibrary ...) 

将输出目录添加到searchpath中:

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

确保指定链接目录添加可执行文件:

 add_executable(MyProgram main.c) 

指定您的项目应链接到的库:

 target_link_libraries(MyProgram ExternalLibraryName) 

不要忘记依靠外部项目:

 add_dependencies(MyProgram MyExternalLibrary)