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一起使用。 获得所有的依赖关系。
另一个你可以用来解决这个问题的成语:
- 使您的find_package命令可选(删除'必需的')
- 如果find_package成功,则添加一些条件代码以仅构build您的目标。
- find_package将会失败,你的目标将不会被第一次build立,但是外部项目将被build立。
- 再次运行cmake / make,这次find_package会成功,你的目标将被build立。
您可以使用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)