CMake CMP0076警告排查:INTERFACE库exi的target_sources配置问题
我明白你现在的困扰——明明已经把构建接口的源文件路径处理成绝对路径了,却还是触发了CMP0076的警告,甚至注释掉INSTALL_INTERFACE相关代码后警告依然存在。咱们一步步来拆解问题,先解决警告,再优化你的CMake配置。
一、直接解决CMP0076警告的方法
这个警告的核心原因是CMake 3.13+引入的CMP0076政策未显式设置。该政策规定:target_sources()中的相对路径会被自动转换为相对于当前CMakeLists.txt的绝对路径。如果不显式设置该政策,CMake会默认发出警告提示。
你只需要在CMAKE_MINIMUM_REQUIRED之后添加一行代码,强制启用该政策的新行为:
CMAKE_MINIMUM_REQUIRED(VERSION 3.10) # 显式设置CMP0076政策,消除警告 cmake_policy(SET CMP0076 NEW)
添加后,警告会立即消失,同时CMake会按照新规则自动处理路径(即使有相对路径也会转为绝对路径,符合现代CMake的最佳实践)。
二、优化你的CMake配置(可选,但更简洁规范)
你的现有配置是可行的,但可以用CMake的内置语法简化冗余代码,减少出错概率:
1. 简化路径列表的构建(替代循环)
CMake支持直接给列表中的每个元素添加前缀,无需手动循环:
# 构建BUILD_INTERFACE的源文件绝对路径列表 set(SOURCE_C_BUILD "${CMAKE_CURRENT_SOURCE_DIR}/src/${SOURCE_C}") # 构建INSTALL_INTERFACE的源文件路径列表(相对于安装前缀) set(SOURCE_C_INSTALL "${SRC_INSTALL_DIR}/${SOURCE_C}")
这行代码和你原来的foreach循环效果完全一致,但代码更简洁,维护性更强。
2. 合并生成器表达式中的路径
target_include_directories中的多个BUILD_INTERFACE/INSTALL_INTERFACE可以合并成一个,用分号分隔路径:
target_include_directories(exi INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include;${CMAKE_CURRENT_SOURCE_DIR}/src> $<INSTALL_INTERFACE:include;${SRC_INSTALL_DIR}> )
同样,target_sources的写法可以保持不变,但合并后的代码更清晰。
3. 简化后完整的CMakeLists.txt示例
CMAKE_MINIMUM_REQUIRED(VERSION 3.10) cmake_policy(SET CMP0076 NEW) set(SOURCE_C file1.c file2.c) set(HEADER_PUBLIC src/header1.h include/header2.h) set(SRC_INSTALL_DIR share/src) # 简化路径构建 set(SOURCE_C_BUILD "${CMAKE_CURRENT_SOURCE_DIR}/src/${SOURCE_C}") set(SOURCE_C_INSTALL "${SRC_INSTALL_DIR}/${SOURCE_C}") add_library(exi INTERFACE) target_sources(exi INTERFACE $<BUILD_INTERFACE:${SOURCE_C_BUILD}> $<INSTALL_INTERFACE:${SOURCE_C_INSTALL}> ) target_include_directories(exi INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include;${CMAKE_CURRENT_SOURCE_DIR}/src> $<INSTALL_INTERFACE:include;${SRC_INSTALL_DIR}> ) # 安装规则保持不变 install(FILES ${SOURCE_C_BUILD} DESTINATION ${SRC_INSTALL_DIR}) install(FILES ${HEADER_PUBLIC} DESTINATION include) install(TARGETS exi EXPORT exi_targets DESTINATION lib/exi) install(EXPORT exi_targets DESTINATION lib/exi FILE exiConfig.cmake) export(TARGETS exi FILE exiConfig.cmake)
三、为什么注释掉INSTALL_INTERFACE还是有警告?
即使你注释掉$<INSTALL_INTERFACE:${SOURCE_C_INSTALL}>,CMake依然会触发警告,是因为CMP0076的检查是针对整个target_sources命令的,而不是单个路径。只要你没有显式设置该政策,CMake就会提示你遵循新的路径处理规则,和路径本身是否绝对无关。
四、验证最终效果
修改后重新构建:
- 构建目录下的
exiConfig.cmake依然会包含正确的绝对构建路径 - 安装后的
exiConfig.cmake会包含正确的相对安装路径 - CMP0076的警告完全消失
备注:内容来源于stack exchange,提问作者Andrew Ahmos

