【问题标题】:CMake: how to use INTERFACE_INCLUDE_DIRECTORIES with ExternalProject?CMake:如何将 INTERFACE_INCLUDE_DIRECTORIES 与 ExternalProject 一起使用?
【发布时间】:2018-01-12 22:44:34
【问题描述】:

我正在尝试使用 ExternalProject_Add 将外部项目作为库添加到我的项目中:

ExternalProject_Add(
        xgboost
        GIT_REPOSITORY https://github.com/dmlc/xgboost.git
        GIT_TAG v0.60
        PREFIX ${CMAKE_CURRENT_BINARY_DIR}
        INSTALL_COMMAND ""
)

另外,我正在定义库目标并将外部项目添加为依赖项:

set(XGBOOST_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/src")
set(XGBOOST_BINARY_PATH "${XGBOOST_PREFIX_PATH}/xgboost-build")
set(XGBOOST_BINARY_INCLUDE "${XGBOOST_PREFIX_PATH}/xgboost/include;${XGBOOST_PREFIX_PATH}/xgboost/dmlc-core/include;${XGBOOST_PREFIX_PATH}/xgboost/rabit/include")
add_library(libxgboost IMPORTED STATIC GLOBAL)
add_dependencies(libxgboost xgboost)

set_target_properties(libxgboost PROPERTIES
        "IMPORTED_LOCATION" "${XGBOOST_BINARY_PATH}/liblibxgboost.dylib"
        "IMPORTED_LINK_INTERFACE_LIBRARIES" "${CMAKE_THREAD_LIBS_INIT}"
        "INTERFACE_INCLUDE_DIRECTORIES" "${XGBOOST_BINARY_INCLUDE}"
        )

在另一个 CMakeLists.txt 中:

add_library(somelib STATIC SomeLib.cpp)
target_include_directories(somelib PUBLIC libxgboost)
target_link_libraries(somelib libxgboost)

问题是 cmake INTERFACE_INCLUDE_DIRECTORIES 不允许导出不存在的包含目录。

是否有任何其他方法可以使所有依赖于 libxgboost 的目标自动包含头文件?

更新:

错误信息:

CMake Error in somelib/CMakeLists.txt:
  Imported target "libxgboost" includes non-existent path

    "build/xgboost/src/xgboost/include"

  in its INTERFACE_INCLUDE_DIRECTORIES.  Possible reasons include:

  * The path was deleted, renamed, or moved to another location.

  * An install or uninstall procedure did not complete successfully.

  * The installation package was faulty and references files it does not
  provide.

【问题讨论】:

  • Presize 错误信息,请。
  • IMPORTED_LINK_INTERFACE_LIBRARIES 顺便说一句已被弃用。使用INTERFACE_LINK_LIBRARIES。您是否考虑过在 ExternalProject CMakeLists.txt 上使用execute_process() 调用cmake(两次),那么您将在配置时拥有可用的依赖项?或者,您可以在 CMakeLists.txt 配置期间伪造仅依赖目录的创建。
  • 这是我的 B 计划,但仍然想知道是否有好的做法
  • 我遇到了同样的问题。运气好吗?
  • @mchiasson 我已添加完整的 CMakeLists.txt,希望对您有所帮助

标签: cmake


【解决方案1】:

我将发布最终的 CMakeLists.txt 以将 xgboost 包含到您的项目中,它可能对某人有用,上述问题的解决方案是在 cmake 配置阶段创建目录(注意:我使用的是 OSX要构建它,所以你需要在 GNU/Linux 上使用 liblibxgboost.so 而不是 liblibxgboost.dylib):

include(ExternalProject)

ExternalProject_Add(
        xgboost
        GIT_REPOSITORY https://github.com/dmlc/xgboost.git
        GIT_TAG v0.60
        PREFIX ${CMAKE_CURRENT_BINARY_DIR}
        INSTALL_COMMAND ""
)

set(XGBOOST_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/src")
set(XGBOOST_BINARY_PATH "${XGBOOST_PREFIX_PATH}/xgboost-build")

set(XGBOOST_LIB_INCLUDE "${XGBOOST_PREFIX_PATH}/xgboost/include")
set(DMLC_LIB_INCLUDE "${XGBOOST_PREFIX_PATH}/xgboost/dmlc-core/include")
set(RABIT_LIB_INCLUDE "${XGBOOST_PREFIX_PATH}/xgboost/rabit/include")
set(XGBOOST_BINARY_INCLUDE "${XGBOOST_LIB_INCLUDE};${DMLC_LIB_INCLUDE};${RABIT_LIB_INCLUDE}")

# Hack to make it work, otherwise INTERFACE_INCLUDE_DIRECTORIES will not be propagated
file(MAKE_DIRECTORY ${XGBOOST_LIB_INCLUDE})
file(MAKE_DIRECTORY ${DMLC_LIB_INCLUDE})
file(MAKE_DIRECTORY ${RABIT_LIB_INCLUDE})

add_library(libxgboost IMPORTED STATIC GLOBAL)
add_dependencies(libxgboost xgboost)

set_target_properties(libxgboost PROPERTIES
        "IMPORTED_LOCATION" "${XGBOOST_BINARY_PATH}/liblibxgboost.dylib"
        "INTERFACE_INCLUDE_DIRECTORIES" "${XGBOOST_BINARY_INCLUDE}"
)

【讨论】:

  • 希望CMake能更好地支持这一点;这似乎有点像黑客。有没有办法以某种方式处理依赖关系?例如,您可以在不存在的情况下设置库的 IMPORTED_LOCATION。让 INTERFACE_INCLUDE_DIRECTORIES 不同似乎不一致。
  • @JeffTrull 我希望它以更好的方式支持它。但这是我发现的唯一方式,但这并不意味着它是唯一存在的方式。我是 cmake 的新手,所以我可能会在这里遗漏一些东西。
  • FWIW,file(MAKE_DIRECTORY ...) 也是人们在 CMake 错误跟踪器上提出的:gitlab.kitware.com/cmake/cmake/issues/15052
【解决方案2】:

请注意,可以结合FetchContentExternalProject_Add 来实现以下目的:

  • FetchContent 将在配置时提供源代码,从而绕过INTERFACE_INCLUDE_DIRECTORIES 不存在的问题。
  • ExternalProject_Add 将使用FetchContent 下载的源代码在构建时间进行构建

这是一个示例建筑libpqxx

include(FetchContent)
include(ExternalProject)

find_package(PostgreSQL)

# Using FetchContent means we will download libpqxx at configure-time

FetchContent_Declare(libpqxx_ext
    GIT_REPOSITORY
        https://github.com/jtv/libpqxx
    GIT_TAG
        tags/7.4.1
    )

FetchContent_GetProperties(libpqxx_ext)

if(NOT libpqxx_ext_POPULATED)
  FetchContent_Populate(libpqxx_ext)
endif()

set(LIB_PQXX_SRC_DIR ${CMAKE_BINARY_DIR}/_deps/libpqxx_ext-src)

# Build libpqxx

ExternalProject_Add(libpqxx_ext
    SOURCE_DIR
        ${libpqxx_ext_SOURCE_DIR}
    PREFIX
        ext
    BINARY_DIR
        build
    CMAKE_ARGS
        -DSKIP_BUILD_TEST=on
    INSTALL_COMMAND
        ""
    BUILD_ALWAYS
        OFF
    )

set(LIB_PQXX_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/build/src)

# Make the libpxqq artifacts available to our project

add_library(libpqxx STATIC IMPORTED GLOBAL)

set_target_properties(libpqxx
    PROPERTIES

    INTERFACE_INCLUDE_DIRECTORIES
        ${LIB_PQXX_SRC_DIR}/include
    IMPORTED_LOCATION
        ${LIB_PQXX_BUILD_DIR}/libpqxx.a
    INTERFACE_LINK_LIBRARIES
        ${PostgreSQL_LIBRARIES})

add_dependencies(libpqxx libpqxx_ext)

【讨论】:

    猜你喜欢
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-06
    相关资源
    最近更新 更多