【发布时间】:2021-12-19 04:28:42
【问题描述】:
我有以下简化的 CMake 代码,用于在库中使用 Abseil:(minimal repository to reproduce)
cmake_minimum_required(VERSION 3.20)
project(MyProject)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
set(ABSL_PROPAGATE_CXX_STD ON)
find_package(absl REQUIRED)
add_library(MyStaticLibTarget STATIC MyStaticLib.cpp)
target_link_libraries(MyStaticLibTarget absl::strings)
install(TARGETS MyStaticLibTarget EXPORT MyProjectTargets)
install(TARGETS strings EXPORT MyProjectTargets)
if(EXPORT_MYSTATICLIB)
export(TARGETS MyStaticLibTarget FILE lib/cmake/MyProject/MyProjectTargets.cmake)
endif()
# Setup for downstream clients of MyProject?
install(EXPORT MyProjectTargets DESTINATION lib/cmake/MyProject COMPONENT cmake-exports)
但是,如果我在运行 CMake 时尝试使用 export 代码路径,则会遇到如下所示的错误:
cmake -G Ninja -S . -B build -DABSL_ENABLE_INSTALL=ON -DEXPORT_MYSTATICLIB=ON
# CMake Error in CMakeLists.txt:
# export called with target "MyStaticLibTarget" which requires target
# "strings" that is not in any export set.
我不明白错误信息;在我看来strings 已经是MyProjectTargets 的一部分(我认为这是一个导出集?),所以应该没有任何错误。
也就是说,根据错误消息,我尝试为strings 添加一个export 行,并暂时修复了所有错误,我最终得到了
export(TARGETS
strings
strings_internal
type_traits
base
config
throw_delegate
dynamic_annotations
log_severity
base_internal
raw_logging_internal
atomic_hook
core_headers
spinlock_wait
endian
bits
int128
memory
errno_saver
meta
APPEND FILE lib/cmake/MyProject/MyProjectTargets.cmake)
这确实解决了所有错误!在实践中,对于较大的库,手动执行此操作将非常痛苦。这似乎也是一个“错误”的解决方案,因为我手动命名了 Abseil 的许多内部细节。
- 手动添加上述目标是“正确”的解决方案吗?
- 有没有更好的方法来实现与上述相同的结果?
我有以下限制:
- 我需要导出
MyStaticLibTarget,以便下游客户端使用。 - 我很确定依赖项(在
target_link_libraries中)需要公开,因为在实际情况下(这是一个最小的示例),Abseil 标头将包含在库的公共标头中。
【问题讨论】:
-
"在我看来
strings已经是MyProjectTargets的一部分" -strings链接到MyStaticLibTarget但它不是部分。“......因为我手动命名了 Abseil 的许多内部细节。” - 因为您通过add_subdirectory包含 Abseil,所以 Abseil 内部成为项目的内部。不要与使用find_package(absl)混淆:它执行您的脚本 Findabsl.cmake,它在内部通过FetchContent_Add/add_subdirectory包含Abseil。 -
如果你想真正从 Abseil 内部抽象出来,那么首先安装 Abseil。之后
find_package(absl)无需手写脚本即可找到 Abseil。导出项目时,您只需将find_dependency(absl)调用添加到导出脚本中即可。