CMake中替代if(EXISTS)的文件检查方案,解决跨系统不一致问题
解决CMake宏跨系统/IDE文件检查不一致的问题
针对你遇到的if(EXISTS)配合${CMAKE_BINARY_DIR}时的行为不一致问题,可以通过以下几种更可靠的方式处理,无需硬编码路径:
1. 用cmake_path()规范化路径
CMake 3.20及以上版本提供的cmake_path()命令可以统一处理跨系统的路径分隔符、规范化路径格式,确保EXISTS判断的准确性:
macro(set_up) # 规范化主路径,确保是当前系统标准格式的绝对路径 cmake_path(SET buildinfo_path "${CMAKE_BINARY_DIR}/buildinfo.cmake" NORMALIZE) if (EXISTS "${buildinfo_path}") include("${buildinfo_path}") else() # 同样规范化 fallback 路径 cmake_path(SET fallback_path "${CMAKE_CURRENT_SOURCE_DIR}/tmp/build/buildinfo.cmake" NORMALIZE) if (EXISTS "${fallback_path}") include("${fallback_path}") else() message(FATAL_ERROR "Dependencies not linked.") endif() endif() endmacro()
NORMALIZE选项会自动处理路径中的冗余部分(如./、../),并转换为当前系统的标准路径分隔符,避免因格式差异导致EXISTS判断失误。
2. 使用file(CHECK_EXISTS)命令
file(CHECK_EXISTS)是专门用于检查文件/目录存在性的命令,它会将检查结果存入指定变量,比直接用if(EXISTS)的上下文依赖更低:
macro(set_up) # 检查主路径是否存在,结果存入 buildinfo_exists 变量 file(CHECK_EXISTS "${CMAKE_BINARY_DIR}/buildinfo.cmake" buildinfo_exists) if (buildinfo_exists) include("${CMAKE_BINARY_DIR}/buildinfo.cmake") else() # 检查 fallback 路径 file(CHECK_EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tmp/build/buildinfo.cmake" fallback_exists) if (fallback_exists) include("${CMAKE_CURRENT_SOURCE_DIR}/tmp/build/buildinfo.cmake") else() message(FATAL_ERROR "Dependencies not linked.") endif() endif() endmacro()
这个命令的路径处理逻辑更严谨,能避免变量展开时可能出现的潜在问题。
3. 修正 fallback 路径的上下文依赖
如果你的tmp/build/buildinfo.cmake路径是相对于定义宏的CMake文件,而非调用宏的文件,建议将${CMAKE_CURRENT_SOURCE_DIR}替换为${CMAKE_CURRENT_LIST_DIR}:
cmake_path(SET fallback_path "${CMAKE_CURRENT_LIST_DIR}/tmp/build/buildinfo.cmake" NORMALIZE)
CMAKE_CURRENT_LIST_DIR指向当前正在处理的CMake文件(即宏定义所在的文件)的目录,不受宏调用位置影响,能保证路径指向稳定。
内容的提问来源于stack exchange,提问作者Farnsworth
相关产品推荐
相关产品推荐

