如何导出使用 FetchContent 获取的目标
How to exporting targets fetched with FetchContent
我正在尝试使用 FetchContent
CMake 帮助程序自动构建所需的依赖项,以防它们不是 installed/available 到 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()
然后用于link项目目标:
# ...
target_link_libraries(${PROJECT_NAME} PUBLIC ${Boost_LIBRARIES}
pthread
${tinyxml2_LIBRARIES})
然后导出 linked 目标:
# ...
export(EXPORT ${PROJECT_NAME}Targets
FILE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake
NAMESPACE ${PROJECT_NAME}::)
问题是,从源中获取时,导出步骤失败:
CMake Error in src/myproject/CMakeLists.txt:
export called with target "myproject" which requires target "tinyxml2" that
is not in any export set.
有没有办法自动导出 tinyxml2
作为必需的依赖项?
Is there a way to also auto-export tinyxml2
as a required dependency?
自 CMake 3.23 起 (pre-release)。
当您使用 FetchContent 时,就好像您自己编写了“third-party”代码。 CMake 不知道它是外部的。这称为“供应商”代码。
因为您没有经历 find_package
,您将需要 install()
“您的”目标,就像您将导出的任何其他依赖项一样。它也将导出到您的命名空间,以避免与 other 可能浮动的 tinyxml2
副本发生冲突。
我也觉得这很乏味,这就是为什么我回避 FetchContent
任何可能安装或导出的东西,而是使用适当的 source-based 包管理工具,如 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)
这也比通过变量输入更少。
我正在尝试使用 FetchContent
CMake 帮助程序自动构建所需的依赖项,以防它们不是 installed/available 到 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()
然后用于link项目目标:
# ...
target_link_libraries(${PROJECT_NAME} PUBLIC ${Boost_LIBRARIES}
pthread
${tinyxml2_LIBRARIES})
然后导出 linked 目标:
# ...
export(EXPORT ${PROJECT_NAME}Targets
FILE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake
NAMESPACE ${PROJECT_NAME}::)
问题是,从源中获取时,导出步骤失败:
CMake Error in src/myproject/CMakeLists.txt:
export called with target "myproject" which requires target "tinyxml2" that
is not in any export set.
有没有办法自动导出 tinyxml2
作为必需的依赖项?
Is there a way to also auto-export
tinyxml2
as a required dependency?
自 CMake 3.23 起 (pre-release)。
当您使用 FetchContent 时,就好像您自己编写了“third-party”代码。 CMake 不知道它是外部的。这称为“供应商”代码。
因为您没有经历 find_package
,您将需要 install()
“您的”目标,就像您将导出的任何其他依赖项一样。它也将导出到您的命名空间,以避免与 other 可能浮动的 tinyxml2
副本发生冲突。
我也觉得这很乏味,这就是为什么我回避 FetchContent
任何可能安装或导出的东西,而是使用适当的 source-based 包管理工具,如 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)
这也比通过变量输入更少。