CMake中导出含第三方静态库依赖的目标的惯用方法是什么
你当前手动罗列所有Abseil内部目标的方案不是合规的生产级解决方案。该方案强耦合Abseil的内部实现细节,一旦升级Abseil版本,其内部目标名、传递依赖关系发生变更,你的导出配置会直接失效,长期维护成本极高。
你之前的报错根因为:install(TARGETS strings EXPORT MyProjectTargets) 是将目标加入安装阶段的导出集,而你调用的export()命令是生成本地构建目录的导出文件,二者是完全独立的CMake逻辑,安装阶段的导出配置不会作用于本地export命令,因此CMake会提示strings不在任何导出集中。
另外你的现有代码存在不规范写法:你链接时用的是Abseil的公开命名空间目标absl::strings,但install时写的是内部裸目标名strings,正常开发中不应该直接操作Abseil的内部无命名空间目标,所有交互都应该使用带absl::前缀的公开目标。
结合你的约束条件,最推荐的是使用CMake标准的依赖查找机制,不需要把Abseil目标嵌入你自己的导出集:
- 移除所有手动将Abseil目标加入你导出集的代码,包括
install(TARGETS strings EXPORT MyProjectTargets)以及你手动添加的一堆Abseil内部目标的export逻辑 - 新增
MyProjectConfig.cmake.in模板文件,内容如下:
include(CMakeFindDependencyMacro) find_dependency(absl REQUIRED) include("${CMAKE_CURRENT_LIST_DIR}/MyProjectTargets.cmake")
- 在你的CMakeLists.txt中添加配置和安装该Config文件的逻辑:
include(CMakePackageConfigHelpers) configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/MyProjectConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/MyProjectConfig.cmake" INSTALL_DESTINATION lib/cmake/MyProject ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/MyProjectConfig.cmake" DESTINATION lib/cmake/MyProject )
该方案完全依赖Abseil官方提供的导出配置,不需要你关心任何Abseil内部细节。下游用户使用你的库时,只要能正常找到Abseil包,CMake会自动处理所有依赖链路,完美适配你的公开头文件包含Abseil头的PUBLIC依赖场景。
如果你有特殊需求必须把Abseil目标一起打包进你的导出文件,也可以通过遍历目标传递依赖的方式自动获取所有需要导出的Abseil目标,不需要手动枚举,但这类场景非常少见,一般优先推荐上述方案。
内容的提问来源于stack exchange,提问作者typesanitizer

