链接到 CMAKE 中的 ExternalProject_add 依赖项

Posted

技术标签:

【中文标题】链接到 CMAKE 中的 ExternalProject_add 依赖项【英文标题】:Linking against an ExternalProject_add dependency in CMAKE 【发布时间】:2016-10-29 00:15:43 【问题描述】:

我在运行 Ninja 时遇到了下面的这个 ninja build 错误。我的 CMAKE 构建命令是cmake -G"Ninja" -DCMAKE_BUILD_TYPE=Release

ninja: error: 'ext_deps/api/src/ext_api/build/src/lib/libapi.a', needed by 'Project', missing and no known rule to make it

假设我的项目由一个 API(通过 CMAKE 从 GitHub 下载)和实现(项目)组成。

The layout would look like:
Project/
-- build/
-- cmake/modules
----- ExternalDep.cmake
----- FindAPI.cmake
-- CMakeLists.txt
-- src/
---- CMakeLists.txt
-- include/

假设在***CMakeLists.txt 中,我执行设置构建设置、CXX 标志等的常规业务,然后我调用include(ExternalDep),它检查“API”库是否在用户的系统(如果不是,则通过 CMAKE 下载)。 在src/CMakeLists.txt 中,我尝试使用

链接到 API 库
target_link_libraries($PROJECT_NAME PRIVATE $API_LIBRARY)

我遇到的第一个问题是,在“API”库甚至可以下载和构建之前,我收到了上面发布的 ninja build 错误。在我尝试添加项目可执行文件并链接到“API”库之前,我很肯定 ExternalDep.cmake 已包含在内。

这是ExternalDep.cmake的简化版:

  set(EXT_DEPS_PREFIX "ext_deps")

  ExternalProject_Add(ext_lib
    GIT_REPOSITORY "https://github.com/fake/api.git"
    GIT_TAG "master"
    PREFIX "$CMAKE_BINARY_DIR/$EXT_DEPS_PREFIX/api"
    TMP_DIR "$CMAKE_BINARY_DIR/$EXT_DEPS_PREFIX/api-tmp"
    STAMP_DIR "$CMAKE_BINARY_DIR/$EXT_DEPS_PREFIX/api-stamp"
    CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release
    SOURCE_DIR "$CMAKE_BINARY_DIR/$EXT_DEPS_PREFIX/api/ext_api"
    BINARY_DIR "$CMAKE_BINARY_DIR/$EXT_DEPS_PREFIX/api/ext_api-build"
    BUILD_ALWAYS true
    TEST_COMMAND "")

  add_dependencies(ext_projects ext_api)

  set(API_LIBRARY "$CMAKE_BINARY_DIR/$EXT_DEPS_PREFIX/api/ext_api-build/src/lib/libapi.a")

【问题讨论】:

ExternalProject_Add构建阶段构建项目。但FindXXX.cmake 预计 XXX 项目已在 配置阶段 安装。如果要在配置阶段构建项目,请使用execute_process() @Tsyvarev 因此,经过多次摆弄,我发现我需要做的就是使用Unix Makefiles 作为我生成的构建文件,而不是Ninja。不知道为什么会这样,但它奏效了。 【参考方案1】:

我遇到了与Ninja 相同的问题,而它与Unix Makefiles 一起工作正常,我设法通过在我的ExternalProject_Add 块中添加BUILD_BYPRODUCTS 行使其与Ninja 一起工作。示例:

    ExternalProject_Add(SDL2_PROJECT
        PREFIX 3rdparty
        URL https://www.libsdl.org/release/SDL2-2.0.5.tar.gz
        URL_MD5 d4055424d556b4a908aa76fad63abd3c
        CONFIGURE_COMMAND <SOURCE_DIR>/configure $SDL2_configure_args --prefix=<INSTALL_DIR> --disable-shared
        INSTALL_COMMAND make install -j9
        BUILD_BYPRODUCTS <INSTALL_DIR>/lib/libSDL2.a
    )
    ExternalProject_Get_Property(SDL2_PROJECT INSTALL_DIR)
    set(SDL2_INSTALL_DIR $INSTALL_DIR)
    add_library(SDL2_LIBRARY STATIC IMPORTED GLOBAL)
    set_property(TARGET SDL2_LIBRARY PROPERTY IMPORTED_LOCATION $SDL2_INSTALL_DIR/lib/libSDL2.a)
    add_dependencies(SDL2_LIBRARY SDL2_PROJECT)

【讨论】:

只有忍者需要BUILD_BYPRODUCTS,我在某处读到过。尽管如此,由于构建顺序错误,我在 UNIX Makefile 中遇到了这个错误。我需要我的 cmake 目标的依赖项,该依赖项与外部项目在该外部项目上生成的 .a 链接,因此后者将首先构建... @CarloWood 您是否尝试过创建一个依赖于外部项目的导入库,就像我在上面的代码示例中所做的那样?如果您完全按照我的方式进行操作,您只需针对导入的目标添加您的二进制文件,就可以了...【参考方案2】:

我能够通过生成 Unix Makefiles 而不是 Ninja 来解决这个问题。我仍然不确定这是否是单一问题,但这绝对是问题之一。

【讨论】:

那是因为你需要使用BUILD_BYPRODUCTS。看看我的回答。

以上是关于链接到 CMAKE 中的 ExternalProject_add 依赖项的主要内容,如果未能解决你的问题,请参考以下文章

库中的 CMake 链接目录

cmake - 全局链接器标志设置(适用于目录中的所有目标)

你如何告诉 CMake 静态链接到使用 find_package 找到的包中的库?

opencv静态链接库cmake链接顺序问题

如何强制 CMake 链接到系统库而不是同名目标

注册。使用 CMake 将外部库链接到项目