只链接 fmt 头文件目标,仍报 clang-scan-deps 缺失:关闭未用模块目标
C++20 工程通过 add_subdirectory 引入 fmt,即使只链接头文件目标,也可能生成模块构建。未使用模块时,应在引入前明确关闭 FMT_MODULE。
工程只使用 fmt::fmt-header-only,构建却在扫描 C++ 模块依赖时失败:
CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS-NOTFOUND: not found
如果父项目启用 C++20、通过 add_subdirectory 引入 fmt,应查看是否额外生成了 fmt-module。消费头文件目标,并不保证同一 CMake 配置中不会同时存在模块目标。
fmt 12.2.0 提供 FMT_MODULE 开关,默认值来自其 CMake 模块判断。在 Clang 可用而 clang-scan-deps 未被找到,或 clang-cl 的前端能力不符合该模块路径时,额外目标可能让本不使用模块的工程构建失败。
在引入 fmt 之前关闭不需要的模块
确认工程确实不使用 import fmt 后,可在父项目引入位置配置:
set(FMT_MODULE OFF CACHE BOOL "Build a module library." FORCE)
add_subdirectory(external/fmt)
external/fmt 是示例目录,应替换为实际源码路径。设置必须发生在 fmt 的 CMakeLists.txt 被读取之前;在子项目目标创建后才改变量,不能撤销已经生成的目标。
FORCE 会覆盖该 CMake 构建目录中已有的同名缓存选项。它应属于明确不提供模块的工程策略,不要在同时支持模块与传统链接的通用工程中强行覆盖用户选择。需要让使用者可选时,应采用项目自己的受控选项传递方式。
使用模块的工程应补齐工具链
如果实际要构建 C++ 模块,就不能用关掉模块的办法代替功能。应核对 CMake、编译器前端、依赖扫描器及构建生成器的支持组合,让扫描工具与编译器来自兼容安装。
不要把 CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS 随便指向另一版本的程序,或仅让命令名称存在。clang-cl 的编译器 ID 为 Clang,也不等于所有原生 Clang 模块路径都自动可用。
改动后重新配置受影响的构建目录,检查缓存中 FMT_MODULE 的实际值,并确认生成命令不再调用未请求的模块扫描目标。再构建真实消费 fmt 的业务目标,核对原格式化功能。无需删除整个编译缓存或降低父项目的 C++ 标准。
保留原缓存选项与 CMake 差异;若有其他目标依赖 fmt::fmt-module,关闭后出现的缺目标错误应促使重新梳理模块需求,不能把它当成另一份可忽略警告。


