如何导出使用 FetchContent 获取的目标

joa*_*dre 9 dependencies build cmake

我正在尝试使用FetchContentCMake 帮助程序自动构建所需的依赖项,以防它们未通过安装/可用find_package,但在如何处理导出构建目标方面遇到了困难。

我自己的项目例如需要TinyXML2作为依赖项:

## TinyXML2
find_package(tinyxml2 QUIET)
if (${tinyxml2_FOUND})
    message(STATUS "tinyxml2 FOUND!(${tinyxml2_LIBRARIES})")
    echo_all_cmake_variable_values()
else()
    message(STATUS "tinyxml2 NOT FOUND, fetching from source!")
    FetchContent_Declare(tinyxml2
      GIT_REPOSITORY     https://github.com/leethomason/TinyXML2
      GIT_TAG            9.0.0
    )
    FetchContent_MakeAvailable(tinyxml2)
    set(tinyxml2_LIBRARIES tinyxml2)
endif()
Run Code Online (Sandbox Code Playgroud)

然后用于链接项目目标:

# ...
target_link_libraries(${PROJECT_NAME} PUBLIC ${Boost_LIBRARIES}
                                             pthread
                                             ${tinyxml2_LIBRARIES})
Run Code Online (Sandbox Code Playgroud)

然后导出链接的目标:

# ...
export(EXPORT ${PROJECT_NAME}Targets
       FILE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake
       NAMESPACE ${PROJECT_NAME}::)
Run Code Online (Sandbox Code Playgroud)

问题是,从源获取时,导出步骤失败:

CMake Error in src/myproject/CMakeLists.txt:
    export called with target "myproject" which requires target "tinyxml2" that
    is not in any export set.
Run Code Online (Sandbox Code Playgroud)

有没有办法也自动导出tinyxml2为必需的依赖项?

Ale*_*ing 6

有没有办法也自动导出tinyxml2为必需的依赖项?

自 CMake 3.23(预发布版)起不适用。

当您使用 FetchContent 时,就好像您自己编写了“第三方”代码一样。CMake 不知道它是外部的。这称为“供应”代码。

因为您没有经历find_package,所以您将需要install()像您将导出的任何其他依赖项一样“您的”目标。它也会导出到您的命名空间中,以避免与可能浮动的其他副本发生冲突。tinyxml2

我也觉得这很乏味,这就是为什么我回避FetchContent任何可能安装或导出的东西,而是使用适当的基于源的包管理工具,比如vcpkg。这些工具可以让你用来find_package定位你的依赖项,无论如何,这是 (imo) 你应该在 100% 的时间里做的事情。


另外,您的代码是错误的(请参阅我的顶级评论)。这是一个更正确的版本(我find_package(tinyxml2 REQUIRED)个人只是说)。

## TinyXML2
find_package(tinyxml2 QUIET)
if (NOT tinyxml2_FOUND)
  message(STATUS "tinyxml2 NOT FOUND, fetching from source!")
  FetchContent_Declare(tinyxml2
    GIT_REPOSITORY     https://github.com/leethomason/TinyXML2
    GIT_TAG            9.0.0
  )
  FetchContent_MakeAvailable(tinyxml2)
  install(
    TARGETS tinyxml2 
    EXPORT ${PROJECT_NAME}Targets
    # More arguments as necessary...
  )
endif ()

# ... usage ...
target_link_libraries(${PROJECT_NAME} PUBLIC ${Boost_LIBRARIES}
                                             pthread
                                             tinyxml2::tinyxml2)
Run Code Online (Sandbox Code Playgroud)

这也比通过变量输入更少。