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

Bre*_*mas 46 cmake external-project

我正在尝试使用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})
Run Code Online (Sandbox Code Playgroud)

mat*_*tiu 23

因为您正在下载外部项目,所以您已经知道所有内容,因为您刚刚下载了它,所以它不需要"查找".

我使用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)
Run Code Online (Sandbox Code Playgroud)

从那里,每个依赖它的程序都需要一个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)
Run Code Online (Sandbox Code Playgroud)
  • include_directories - 告诉它在那里搜索目录
  • target_link_libraries - 只需添加您的库,就像命名它(不是变量)

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

这对我有用.适用于make -j4.得到所有的依赖关系.

  • 它怎么知道`ForexConnect`?这里的例子`add_library(ForexConnect SHARED IMPORTED)` (2认同)
  • 看起来像一个优雅的解决方案。它适用于 `make`,但不适用于 `ninja`。对于后者,您必须使用生成文件的路径设置外部项目的“BUILD_BYPRODUCTS”属性。如果没有,Ninja 会尖叫它没有找到你的图书馆。 (2认同)
  • 这看起来只适用于 Linux(您对 lib***.so 的使用)。你如何让它交叉编译? (2认同)

DLR*_*ave 19

当您使用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}")
Run Code Online (Sandbox Code Playgroud)

当然,这比使用find_package要方便.如果您可以使用预先构建/预安装的软件包,那么您应该使用find_package.但是,如果必须从源代码构建另一个包作为项目的一部分,则ExternalProject_Add很有用,即使它无法为您抽象出所有细节.

  • cmake为您的平台提供前缀和后缀变量:`"$ {install_dir}/lib/$ {CMAKE_SHARED_MODULE_PREFIX} protobufLib1 $ {CMAKE_SHARED_LIBRARY_SUFFIX}"` (7认同)
  • 虽然这有效,但我认为这很糟糕.如果我必须编写平台条件代码,那么使用cmake有什么意义呢?此外,我希望ExternalProject提供一种简单的方法来导入构建的目标,如果我以后不能轻易导入它,为什么我要构建一个外部项目呢?重点是什么?我错过了什么吗? (6认同)
  • 你没有遗漏任何@Jens,但场景不是 ExternalProject 与 CMake 的正常使用。事实上,我会建议反对它。典型的场景是**all** ExternalProject,或者没有ExternalProject,不是一些外部的这种混合情况,一些不是。当所有组件都由 ExternalProject 在所谓的“超级构建”场景中构建/安装时,以后构建的组件可以使用 find_package 来查找较早构建/安装的组件。这是使用 ExternalProject 的推荐方式。 (3认同)

ale*_*led 18

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

有关更多信息,请参阅CMake有用变量.

例如:

  • CMAKE_SHARED_LIBRARY_PREFIX
  • CMAKE_SHARED_LIBRARY_SUFFIX
  • CMAKE_STATIC_LIBRARY_PREFIX
  • CMAKE_STATIC_LIBRARY_SUFFIX


jok*_*oke 5

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

ExternalProject_Add(MyExternalLibrary ...)
Run Code Online (Sandbox Code Playgroud)

将输出目录添加到搜索路径:

link_directories(${CMAKE_BINARY_DIR}/lib/MyExternalLibrary-prefix/lib)
Run Code Online (Sandbox Code Playgroud)

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

add_executable(MyProgram main.c)
Run Code Online (Sandbox Code Playgroud)

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

target_link_libraries(MyProgram ExternalLibraryName)
Run Code Online (Sandbox Code Playgroud)

不要忘记依赖外部项目:

add_dependencies(MyProgram MyExternalLibrary)
Run Code Online (Sandbox Code Playgroud)


jkl*_*ntz 5

您可以使用另一个惯用语来解决此问题:

  1. 将 find_package 命令设置为可选(删除“REQUIRED”)
  2. 添加一些条件代码,以便仅在 find_package 成功时构建目标。
  3. find_package 将失败,并且您的目标将不会在第一次构建,但将构建外部项目。
  4. 再次运行 cmake/make,这次 find_package 将成功并且您的目标将被构建。

您可以在https://github.com/biometrics/likely中看到这个习惯用法的实际应用。