
构建工具开发工具CLI【免费下载链接】CMakeMirror of CMake upstream repository项目地址https://gitcode.com/gh_mirrors/cm/CMake点击查看免费下载CMP0194 是 CMake 4.1 引入的一项兼容性策略它修正了 Windows 平台下启用ASM语言时误将 MSVC 的cl编译器当作汇编器的历史缺陷。本指南将围绕该策略的来龙去脉、OLD/NEW 两种行为差异、底层源码实现以及项目迁移方案展开讲解读完你可以在自己的 Windows 构建工程中准确判断该策略的影响并正确选择兼容或新行为。策略背景cl 为什么会被当成汇编器在 CMake 中启用ASM语言时CMake 会把 C 编译器的驱动程序driver作为汇编器候选来探测。这一设计在 GCC/Clang 生态中是合理的——gcc/clang既能编译 C 源码也能直接汇编.s/.asm源文件。然而在 Windows MSVC 工具链上这一假设出了问题CMake 4.0 及更早版本会意外地把 MSVC 的cl编译器选为CMAKE_ASM_COMPILER从而允许在 Windows 上成功启用ASM语言即使cl根本不支持汇编源文件项目虽然配置成功但一旦真正编译汇编源就会失败或行为异常。CMake 4.1 起官方决定优先拒绝把cl作为汇编器候选这是 CMP0194 的 NEW 行为。但社区中存在不少在 Windows 上无条件启用ASM、却从不添加汇编源文件的项目这些项目依赖旧行为才能继续配置通过。CMP0194 正是为这类项目提供兼容通道而引入的。策略行为OLD 与 NEW 的完整对比依据 Help/policy/CMP0194.rst 的官方定义行为含义适用场景OLD即使cl是唯一可用的候选也成功启用ASM语言在 Windows 上无条件enable_language(ASM)、但不真正编译汇编源的老项目NEW不再把cl作为ASM语言的汇编器候选使用真实汇编器如ml/ml64宏汇编器或通过交叉编译指定了其他汇编器的项目从源码看两种行为不仅影响是否允许cl进入候选列表还影响编译器身份ID识别的判定标准在 Modules/CMakeDetermineASMCompiler.cmake 中NEW行为下 CMake 使用更严格的过滤正则if(_CMAKE_ASM_CMP0194 STREQUAL NEW) set(_CMAKE_ASM_REGEX_MSVC ^(MSVC)$) set(_CMAKE_ASM_REGEX_CL (^|/)[Cc]Ll) set(_CMAKE_ASM_MAYBE_CL ) else() # OLD任何情况都不排除且把 cl 加入候选 set(_CMAKE_ASM_REGEX_MSVC CMP0194_OLD_MSVC_NOT_EXCLUDED) set(_CMAKE_ASM_REGEX_CL CMP0194_OLD_MSVC_NOT_EXCLUDED) set(_CMAKE_ASM_MAYBE_CL cl) endif()解读这段代码NEW 行为如果已加载的 C/C 编译器 ID 匹配^(MSVC)$或编译器路径匹配cl文件名正则(^|/)[Cc]Ll则该编译器不会被放进CMAKE_ASM_COMPILER_LIST默认候选列表里也不追加cl而是从cc、gcc、xlc等真实汇编器/编译器驱动中探测。OLD 行为_CMAKE_ASM_REGEX_MSVC/_CMAKE_ASM_REGEX_CL被设置为一个不可能匹配的哨兵字符串CMP0194_OLD_MSVC_NOT_EXCLUDED相当于不做任何排除同时cl被显式追加进默认候选列表从而复现 CMake 4.0 及更早版本的行为。编译器 ID 识别差异OLD/NEW 还影响 MSVC 厂商识别vendor detection正则在 Modules/CMakeDetermineASMCompiler.cmakelist(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS MSVC) set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_MSVC -?) if(_CMAKE_ASM_CMP0194 STREQUAL NEW) # 仅当探测输出包含 “Macro Assembler” 字样ml/ml64才算 MSVC 厂商 set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_MSVC Microsoft.*Macro Assembler) else() # OLD任何 “Microsoft” 输出包括 cl都会被视为 MSVC 厂商 set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_MSVC Microsoft) endif()也就是说在 NEW 行为下只有当候选汇编器运行-?参数输出包含Microsoft ... Macro Assembler即真正的ml/ml64宏汇编器时其编译器 ID 才会被识别为MSVC而cl的-?输出只有Microsoft (R) C/C Optimizing Compiler不再匹配从而被正确排除。源码实现剖析策略如何被读取与告警CMP0194 的完整生命周期在仓库中由三处代码协作完成策略注册与默认告警级别Source/cmPolicies.h 中注册了该策略SELECT(POLICY, CMP0194, MSVC is not an assembler for language ASM., 4, 1, 0, WARN)其中4, 1表示策略在 CMake 4.1 引入WARN表示未显式设置该策略时 CMake 会发出警告。策略读取Modules/CMakeDetermineASMCompiler.cmake 在探测汇编器前执行cmake_policy(GET CMP0194 _CMAKE_ASM_CMP0194)将策略值存入内部变量_CMAKE_ASM_CMP0194后续所有分支候选列表构造、厂商识别都依据该变量取值NEW/OLD/ 空决定行为。警告触发探测完成后如果最终选出的汇编器 ID 恰为MSVC且策略未设置空值则触发策略警告 Modules/CMakeDetermineASMCompiler.cmakeif(ASM${ASM_DIALECT} STREQUAL ASM AND CMAKE_ASM_COMPILER_ID STREQUAL MSVC AND _CMAKE_ASM_CMP0194 STREQUAL ) cmake_policy(ISSUE_WARNING CMP0194) endif()由此可以推断出完整的告警链路cl在 OLD/未设置状态下被选为汇编器 → ID 被识别为 MSVC → 策略未设置 →cmake_policy(ISSUE_WARNING CMP0194)发出警告同时按未设置时的默认行为即 OLD继续配置。如何在项目中设置与切换该策略CMP0194 可通过标准的策略机制进行设置对应文档见 Help/policy/include/STANDARD_ADVICE.rst方式一cmake_minimum_required推荐在CMakeLists.txt顶部声明最小版本cmake_minimum_required(VERSION 4.1)由于 CMP0194 于 4.1 引入cmake_minimum_required(VERSION 4.1)及以上会将所有 4.1 及更早的策略默认设为 NEW包括 CMP0194。如果你的项目本就不依赖cl充当汇编器这是最干净的迁移路径。方式二cmake_policy(SET) 显式设置# 维持旧行为允许 cl 作为 ASM 汇编器候选仅限确需兼容的场景 cmake_policy(SET CMP0194 OLD) # 采用新行为排除 cl cmake_policy(SET CMP0194 NEW)对应的命令语法定义在 Help/command/cmake_policy.rstcmake_policy(SET CMPNNNN NEW|OLD)与cmake_policy(GET CMPNNNN variable)。注意cmake_policy(SET ...)必须在任何受影响的命令执行之前调用且应在目录顶层尽早完成。方式三CMAKE_POLICY_DEFAULT_CMP0194 外部覆盖如果项目本身未更新、而你作为构建方希望临时决定策略走向可在配置命令行通过缓存变量注入默认值见 Help/variable/CMAKE_POLICY_DEFAULT_CMPNNNN.rst# 强制采用新行为排除 cl cmake -S . -B build -DCMAKE_POLICY_DEFAULT_CMP0194NEW # 保持旧行为并抑制警告 cmake -S . -B build -DCMAKE_POLICY_DEFAULT_CMP0194OLD该变量专门用于外部指定项目自身尚未更新的策略默认值官方文档明确建议项目不要在 CMake 代码中通过它来设置自己的策略而应使用cmake_policy(SET)。迁移建议与适用前提结合策略定义与源码实现可以给出以下决策路径项目在 Windows 上启用 ASM 并真正编译汇编源应依赖ml/ml64MSVC 宏汇编器或 MASM 方言ASM_MASM并显式cmake_policy(SET CMP0194 NEW)。此时cl被排除ml/ml64会被正确识别为MSVC厂商匹配Microsoft.*Macro Assembler正则。项目在 Windows 上无条件enable_language(ASM)但从不添加汇编源这是策略文档点名的典型存量场景。可选择保持 OLD 行为继续配置但请注意OLD 行为按官方定义Help/policy/include/DEPRECATED.rst是被弃用的未来版本可能被移除更稳妥的做法是去掉无用的enable_language(ASM)或在代码中按平台条件启用从根本上消除对cl充当汇编器的依赖。交叉编译或使用独立汇编器NEW 行为不影响通过CMAKE_ASM_COMPILER/CMAKE_ASM_COMPILER_INIT显式指定的汇编器候选列表仅在未显式指定时参与探测可放心启用 NEW。版本与告警行为汇总属性取值依据引入版本CMake 4.1Help/policy/CMP0194.rst 中.. versionadded:: 4.1未设置时行为发出警告并按 OLD 处理Source/cmPolicies.h 中WARN标志NEW 核心变更cl不再作为ASM汇编器候选Modules/CMakeDetermineASMCompiler.cmakeOLD 语义cl可继续当选ASM照常启用Modules/CMakeDetermineASMCompiler.cmake总而言之CMP0194 是对 CMake 4.0 及更早版本在 Windows 平台ASM语言探测缺陷的一次行为修正同时为存量项目保留了显式兼容开关。理解其 OLD/NEW 语义和 Modules/CMakeDetermineASMCompiler.cmake 中的正则逻辑就能在升级到 CMake 4.1 时对 Windows 汇编语言支持做出准确、可控的决策。赞分享构建工具开发工具CLI【免费下载链接】CMakeMirror of CMake upstream repository项目地址https://gitcode.com/gh_mirrors/cm/CMake点击查看免费下载相关推荐CMake 的 ASM\DIALECT\ 环境变量为不同汇编方言指定首选编译器的完整指南CMake 的 ASM\DIALECT\ 环境变量为不同汇编方言指定首选编译器的完整指南 导读 ASMDIALECT 是 CMake 中用于指定汇编语言方构建工具开发工具CLICMake 策略 CMP0223 详解空路径不再被视为任何路径的前缀CMake 策略 CMP0223 详解空路径不再被视为任何路径的前缀 导读 CMake 4.5 引入的 CMP0223 策略用于修正路径前缀判定的边界语义在构建工具开发工具CLICMake 策略 CMP0198 深度解析CMakeLists.txt 中不再定义 CMAKE_PARENT_LIST_FILECMake 策略 CMP0198 深度解析CMakeLists.txt 中不再定义 CMAKE_PARENT_LIST_FILE 导读 本文围绕 CMake构建工具开发工具CLI上一篇终极指南如何用QZoneExport为你的QQ空间时光打造永久数字档案馆下一篇Paddle-Lite Java API 完全解析MobileConfig、PaddlePredictor、PowerMode 与 Tensor 的使用与 JNI 底层实现创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考