2011-06-15 116 views
38

我想使用ExternalProject_add()来下载/安装依赖关系。它的安装很好,但我无法弄清楚如何在下载后实际链接这些库。CMake - 链接到从ExternalProject_add下载的库()

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

如果这是一个系统依赖项,我可以调用find_package() - 但这些包未安装在默认搜索路径中。我不认为你可以在模块模式下为find_package指定一个搜索路径。

这里是我的CMakeLists.txt的片段,不工作:当你使用ExternalProject_Add

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

回答

15

,您不能使用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很有用,尽管它无法为您抽象出所有细节。

+0

谢谢,这真的很有帮助。也正因如此,我不会造成混淆,protobuf没有可变的库位置,但R。 – 2011-06-15 12:39:42

+7

CMake提供的前缀和后缀变量平台:' “$ {}安装目录/ lib中/ $ {} CMAKE_SHARED_MODULE_PREFIX $ protobufLib1 {} CMAKE_SHARED_LIBRARY_SUFFIX”' – 2015-04-02 15:48:16

+4

虽然这工作,我认为这是可怕的。如果我必须编写平台条件代码,使用cmake有什么意义?此外,我期望ExternalProject提供一种简单的方法来导入构建的目标,为什么我想要构建一个外部项目,如果以后不能轻松导入它们?重点是什么?我错过了什么吗? – Jens 2016-06-14 03:36:23

2

您可以使用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) 
+0

我觉得实际的'link_directories'串,我看到在我的情况下,* LIB *像* MyExternalLibrary建造/ lib中*要长一些。 – mlt 2013-03-20 21:23:33

+0

我试过这种技术,它不适用于新版本。你得到错误(你的图书馆找不到)。 – matiu 2015-03-29 00:06:02

3

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

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

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

14

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

查看CMake Useful Variables了解更多信息。

例如:

  • CMAKE_SHARED_LIBRARY_PREFIX
  • CMAKE_SHARED_LIBRARY_SUFFIX
  • CMAKE_STATIC_LIBRARY_PREFIX
  • CMAKE_STATIC_LIBRARY_SUFFIX
11

因为你下载的外部项目,你已经知道一切都是因为你下载它,所以它不需要'fin丁”。

我得到它与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一起使用。获得所有的依赖关系。

+1

由于cmake 3.2可以使用UPDATE_DISCONNECTED来避免自动更新。您仍然可以根据需要更新添加自定义目标。 – Jens 2016-08-22 07:21:10

+0

它如何知道'ForexConnect'?示例 'add_library(ForexConnect SHARED IMPORTED)' – Lamda 2017-10-24 23:16:14

+0

真的很棒的解决方案,甚至超越了简单的区分和管理依赖关系和链接。 – 2017-10-27 09:56:27