You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CMake中INCLUDE引入文件内FILE GLOB路径异常问题咨询

问题:CMake中FILE(GLOB)在INCLUDE与ADD_SUBDIRECTORY场景下行为差异?

环境与项目结构

  • 系统:Windows
  • CMake版本:3.22.2
  • 项目文件结构:
    • go.bat
    • CMakeLists.txt
    • extensions/LookForExtensions.cmake
    • subprojects/CMakeLists.txt

go.bat内容

:: launch an out-of-source build, to avoid clutter; generator could be anything
@cmake -G "Visual Studio 16" -H%~dp0 -B%~dp0build

根目录CMakeLists.txt内容

CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
PROJECT( mve )
INCLUDE( extensions/LookForExtensions.cmake )  # 通过INCLUDE()调用脚本
ADD_SUBDIRECTORY( subprojects )                # 通过ADD_SUBDIRECTORY()加载子项目

subprojects/CMakeLists.txt 与 extensions/LookForExtensions.cmake 内容(两者完全一致)

SET( here ${CMAKE_CURRENT_LIST_DIR} )
MESSAGE( "Looking for files/directories in " ${here} ) # 两种场景下路径均正确
FILE( GLOB contents RELATIVE ${here} * )   # 行为出现差异
FOREACH( match ${contents} )
    MESSAGE( "* found " ${match} )
ENDFOREACH()

执行输出(带注释)

C:\cmake-trouble>go
-- Selecting Windows SDK version 10.0.19041.0 to target Windows 10.0.22621.
Looking for files/directories in C:/cmake-trouble/extensions  # 路径正确
* found ../CMakeLists.txt           # 结果错误,列出了上级目录内容
* found ../build                    # 结果错误
* found ../go.bat                   # 结果错误
* found ../subprojects              # 结果错误
Looking for files/directories in C:/cmake-trouble/subprojects  # 路径正确
* found CMakeLists.txt    # 结果正确
-- Configuring done
-- Generating done
-- Build files have been written to: C:/cmake-trouble/build

核心疑问

为何相同代码在两种调用场景中FILE(GLOB)表现差异巨大?如何让LookForExtensions.cmake中的FILE(GLOB)正常工作?${here}路径正确,但RELATIVE ${here}似乎未生效。


解答

差异原因

问题核心在于CMake工作目录与源码目录的区别:

  • 使用ADD_SUBDIRECTORY(subprojects)时,CMake会自动切换工作目录到build/subprojects(对应子项目的构建目录),此时FILE(GLOB *)是在该构建目录下查找内容,再通过RELATIVE ${here}(即源码目录C:/cmake-trouble/subprojects)转换路径,得到的是相对源码目录的正确结果。
  • 使用INCLUDE(extensions/LookForExtensions.cmake)时,CMake工作目录仍为根构建目录build,此时FILE(GLOB *)查找的是build目录下的所有内容,再通过RELATIVE ${here}(即源码目录C:/cmake-trouble/extensions)转换路径,自然得到../开头的相对路径——因为build目录的内容相对于extensions目录就是上级目录的文件。

简言之:FILE(GLOB)的通配符*是相对于**当前工作目录(构建目录)**而非CMAKE_CURRENT_LIST_DIR(源码目录)查找的,RELATIVE仅负责将找到的绝对路径转换为相对指定目录的路径,并非限定查找范围。

修复方法

要让LookForExtensions.cmake正确查找extensions目录下的内容,需明确指定查找路径为${here}/*,修改后的代码如下:

SET( here ${CMAKE_CURRENT_LIST_DIR} )
MESSAGE( "Looking for files/directories in " ${here} )
# 明确指定查找路径为当前源码目录下的所有内容
FILE( GLOB contents RELATIVE ${here} "${here}/*" )
FOREACH( match ${contents} )
    MESSAGE( "* found " ${match} )
ENDFOREACH()

修改后,无论CMake当前工作目录在哪里,FILE(GLOB)都会直接查找${here}(即extensions源码目录)下的内容,再通过RELATIVE ${here}转换为相对该目录的路径,即可得到正确结果。

额外提示:CMake官方不推荐用FILE(GLOB)做依赖管理,因为它不会自动检测文件的新增/删除。如果需要跟踪文件变化,建议手动列出文件或结合其他机制,但这不属于当前问题的核心修复范围。

内容的提问来源于stack exchange,提问作者jez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 21:13:17