ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

CMake CMP0047 策略详解:QNX qcc 编译器的 Compiler ID 从 GNU 到 QCC 的演进

CMake CMP0047 策略详解:QNX qcc 编译器的 Compiler ID 从 GNU 到 QCC 的演进 构建工具开发工具CLI【免费下载链接】CMakeMirror of CMake upstream repository项目地址https://gitcode.com/gh_mirrors/cm/CMake点击查看免费下载导读CMP0047 是 CMake 自 3.0 起引入的一项兼容性策略它解决了一个在 QNX 嵌入式开发中非常具体的问题当使用 QNX 的qcc编译器驱动时CMake 应当把CMAKE_LANG_COMPILER_ID报告为QCC还是旧有的GNU。本文以 CMP0047.rst 文档为主体结合本仓库中 cmPolicies.h 的策略注册与 Modules/Compiler/QCC-*.cmake 的编译器实现完整讲解该策略的 OLD/NEW 行为、设置时机、迁移方式以及 QNX 工具链的底层细节。读完本文你将掌握如何在旧项目与现代 CMake 之间正确对齐 QNX 交叉编译的 Compiler ID并理解这一变更对特性检测、编译旗标选择的影响。一、策略背景为什么 qcc 需要自己的 Compiler IDQNX 实时操作系统RTOS的官方编译器驱动名为qcc针对 C/C其底层通常封装了 GCC 兼容的代码生成后端。在 CMake 3.0 之前CMake 只把qcc当作 GNU 编译器家族的一员处理CMAKE_LANG_COMPILER_ID一律报告为GNU。这种简化在早期可行但存在隐患qcc驱动在命令行语义上与裸gcc有明显差异例如 C 语言模式需要显式传入-lang-c或-x c这样的驱动级旗标而不是由 gcc 默认推断项目无法通过 Compiler ID 精确区分真正的 GCC和QNX 的 qcc 封装导致针对性的工具链适配逻辑无从下手。CMake 3.0 起CMake 正式承认 QNXqcc驱动与 GNU 编译器是两回事并引入独立编译器 IDQCC参见CMAKE_ _COMPILER_ID变量文档中QCC— QNX C/C compiler 这一取值。但考虑到存量项目可能依然假设 qcc 的 ID 是GNU直接改默认值会破坏这些项目的条件判断于是通过策略 CMP0047 让新旧行为平滑过渡。二、策略定义CMP0047 的 OLD 与 NEW 行为根据 CMP0047.rst该策略的语义如下行为效果OLD旧行为对 qcc 与 QCC 两类编译器驱动CMAKE_LANG_COMPILER_ID报告为GNUNEW新行为对 qcc 与 QCC 两类编译器驱动CMAKE_LANG_COMPILER_ID报告为QCC该策略在语言LANG被 project() 或 enable_language() 命令启用之后决定CMAKE_LANG_COMPILER_ID变量中报告哪一个 Compiler ID。在 CMake 源码中该策略注册于 cmPolicies.h注册摘要字符串即为Use QCC compiler id for the qcc drivers on QNX.与文档标题完全一致。策略注册位于cmPolicies.h的策略表中意味着它在 CMake 的cmake_minimum_required版本判定体系内是标准策略之一可通过常规的 cmake_policy() 机制被读取与设置。关键约束必须在使用前设置文档明确指出该策略必须在project()或enable_language()被调用之前设置因为语言启用过程会读取编译器信息、写入CMAKE_LANG_COMPILER_ID策略在那一刻才决定用哪个 ID。错过时机再调用cmake_policy(SET CMP0047 ...)将不会对已启用的语言生效。推荐的设置方式cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0047 NEW) # 显式选择 QCC 编译器 ID project(MyQnxProject C CXX) # 语言启用发生在策略设置之后或直接依赖版本声明隐式启用cmake_minimum_required(VERSION 3.5) # 3.0 的策略默认即 NEW需要说明在 CMake 3.0 至 4.0 之前的版本中若项目没有显式设置该策略CMake 会按默认策略行为处理并可通过CMAKE_POLICY_WARNING_CMP0047变量参见 CMAKE_POLICY_WARNING_CMP 控制是否输出策略警告。默认情况下该策略在 3.0 引入时不主动告警文档中WARNED_OR_DID_NOT_WARN替换为 didnotwarn by default。三、策略生命周期CMake 4.0 起 OLD 行为被移除文档开头的序言include 自 REMOVED_PROLOGUE.rst表明该策略的OLD行为已在CMake 4.0中被移除策略必须通过cmake_minimum_required或cmake_policy设置为NEW。这带来两个直接影响最低版本 ≥ 4.0 的项目cmake_minimum_required(VERSION 4.0)会让 CMP0047 自动处于NEW状态QNX 下 Compiler ID 必然是QCC无需额外处理最低版本 4.0 的存量项目若代码中仍存在针对GNUID 的 QNX 分支例如if(CMAKE_C_COMPILER_ID STREQUAL GNU)在升级 CMake 到 4.0 后该分支将不再命中需要迁移为检查QCC。这正是该策略与其他已移除 OLD 行为策略如 CMP0001–CMP00xx 系列中同样标注 REMOVED 的策略一致的演进路径先以默认旧行为兼容存量再通过警告提醒最终在新大版本中强制新行为。四、源码纵深QCC 编译器模块在仓库中的真实实现策略 CMP0047 的落地不止于cmPolicies.h中的一条注册记录还配套了一整套以QCC命名的编译器模块。在 Modules/Compiler 目录下可以看到QCC-C.cmake、QCC-CXX.cmake、QCC-ASM.cmake各语言的编译/链接规则入口QCC-C-FeatureTests.cmake、QCC-CXX-FeatureTests.cmake语言特性探测QCC.cmake公共宏__compiler_qcc的定义以 QCC-C.cmake 为例其实现非常精简# To include compiler feature detection include(Compiler/GNU-C) include(Compiler/QCC) __compiler_qcc(C)注意第一行QCC 的 C 语言特性检测直接复用了Compiler/GNU-C。这一点与策略背景相互印证——qcc 的代码生成后端与 GCC 兼容因此绝大多数 GNU 编译旗标与特性宏依然适用但 Compiler ID 却独立为QCC使项目既能复用 GCC 特性语义又能识别出驱动差异。QCC-CXX.cmake 则展示了更实质的驱动差异——C 语言模式旗标随 qcc 版本变化# If the toolchain uses qcc for CMAKE_CXX_COMPILER instead of QCC, the # default for the driver is not c. if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.2.0) # QNX 8.0 toolchain set(_cmake_qcc_cxx_lang_compile_flag -lang-c) set(_cmake_qcc_cxx_lang_link_flag -lang-c) else () set(_cmake_qcc_cxx_lang_compile_flag -x c) set(_cmake_qcc_cxx_lang_link_flag ) endif () set(CMAKE_CXX_COMPILE_OBJECT CMAKE_CXX_COMPILER ${_cmake_qcc_cxx_lang_compile_flag} DEFINES INCLUDES FLAGS -o OBJECT -c SOURCE) set(CMAKE_CXX_LINK_EXECUTABLE CMAKE_CXX_COMPILER ${_cmake_qcc_cxx_lang_link_flag} FLAGS LINK_FLAGS OBJECTS -o TARGET LINK_LIBRARIES)从中可以读出两个关键事实驱动不是 gccqcc 驱动默认并不自动选择 C 语言模式CMake 必须显式传入语言旗标这正是 Compiler ID 必须区别于GNU的底层原因版本分支qcc 12.2.0QNX 8.0 工具链之前的版本使用-lang-c之后的版本使用-x c且链接阶段无需语言旗标。这说明CMAKE_CXX_COMPILER_VERSION在 QNX 工具链上同样可用项目可以安全地用它做版本判断。此外QCC-ASM.cmake 仅包含include(Compiler/QCC)与__compiler_qcc(ASM)两行表明 QCC 编译器 ID 同样适用于 ASM 语言而 Modules/Platform/QNX-Initialize.cmake 则负责 QNX 平台层的初始化与编译器层的 QCC 模块协同完成整套 QNX 交叉编译支持。五、实战迁移旧项目到 QCC Compiler ID假设你有一个面向 QNX 的存量 CMake 工程其配置文件中曾有如下分支if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) # 误把 qcc 当成 GNU 处理的旧逻辑 add_compile_options(-fno-exceptions) endif()在 CMake 3.0 中若项目仍隐式处于 CMP0047 的 OLD 行为上述分支在 qcc 下依然命中但语义是碰巧的一旦切到 NEW 行为或升级到 CMake 4.0该分支将失效。正确迁移步骤声明策略在project()之前显式cmake_policy(SET CMP0047 NEW)或将cmake_minimum_required提升到 3.0 以上推荐直接显式 SET明确意图改写条件将所有针对 QNX 工具链的GNU判断改为QCCif(CMAKE_CXX_COMPILER_ID STREQUAL QCC) # QNX qcc 专用逻辑例如 add_compile_options(-fno-exceptions) elseif(CMAKE_CXX_COMPILER_ID STREQUAL GNU) # 真正的桌面/嵌入式 GCC 逻辑 endif()验证 Compiler ID在配置阶段打印确认message(STATUS QNX Compiler ID ${CMAKE_CXX_COMPILER_ID}) message(STATUS QNX Compiler Version ${CMAKE_CXX_COMPILER_VERSION})回归测试特性检测由于 QCC-C/CXX 模块复用了 GNU 的特性测试见 QCC-C-FeatureTests.cmakecheck_cxx_compiler_flag、write_compiler_detection_header等依赖 Compiler ID 的机制会以QCC作为 ID 前缀生成检测头请同步检查任何硬编码了GNU的检测头消费代码。常见问题Q不设置该策略会怎样在 CMake 3.x–3.27 等版本中默认沿用旧行为报告GNU策略本身默认不告警因此存量项目不会立即报错但跨过 CMake 4.0 后旧行为被移除编译器 ID 会突然变为QCC提前迁移可避免升级冲击。QCMAKE_CXX_COMPILER_ID为QCC与CMAKE_CXX_COMPILER指向qcc/QCC有区别吗Compiler ID 是 CMake 通过编译探测CompilerId 工程识别出的厂商标识qcc与QCC两个驱动都会得到QCC这个 ID而QCC-CXX.cmake中的版本分支正是为了兼容驱动名为 qcc 但版本口径不同的两种工具链形态。Q策略设置时机为什么如此严格因为project()/enable_language()在启用语言的同时完成编译器探测并固化CMAKE_LANG_COMPILER_IDCMP0047 正是这一探测结果的显示器自然必须先行设置。这一约束在 CMP0047.rst 文档中已明确强调。六、与其他 QNX 相关机制的关系CMP0047 只是 CMake QNX 支持的一部分。从仓库结构看QNX 支持由多层协同构成策略层CMP0047.rst 决定 Compiler ID 的取值口径编译器层Modules/Compiler/QCC-*.cmake 系列模块按 IDQCC提供各语言的编译/链接规则与特性检测平台层Modules/Platform/QNX-Initialize.cmake 完成系统级初始化变量层CMAKE_ _COMPILER_ID文档中QCC被登记为 QNX C/C compiler 的官方取值可供所有项目在条件判断中引用。理解这一层次关系后遇到 QNX 工具链问题时可以按ID 是否对 → 规则是否生效 → 平台初始化是否正确的顺序排查而 CMP0047 正是第一环。总结CMP0047 是 CMake 3.0 引入、并在 CMake 4.0 中强制收口的 QNX 编译器识别策略OLDqcc/QCC 驱动报告GNU编译器 IDNEWqcc/QCC 驱动报告独立的QCC编译器 ID必须在project()/enable_language()之前设置配套实现见 cmPolicies.h 与 Modules/Compiler/QCC-*.cmake其中 QCC-CXX 的版本分支qcc 12.2.0 前后使用不同的 C 语言旗标说明了 ID 独立化的根本动机——qcc 并非 GNU 编译器只是与其兼容的 QNX 驱动。对于维护 QNX 交叉编译工程的开发者建议在 CMake 4.0 落地前完成 Compiler ID 的显式对齐把所有针对 qcc 的GNU判断迁移为QCC从而让工具链识别更精确、升级路径更平滑。赞分享构建工具开发工具CLI【免费下载链接】CMakeMirror of CMake upstream repository项目地址https://gitcode.com/gh_mirrors/cm/CMake点击查看免费下载相关推荐Meson 对 QNX qcc/q 编译器驱动的支持交叉编译配置、实现原理与已知限制Meson 对 QNX qcc/q 编译器驱动的支持交叉编译配置、实现原理与已知限制 Meson Build System 自本版本起正式支持 QNX S构建工具CMake 策略 CMP0025 深度解析Apple Clang 编译器标识从 Clang 到 AppleClang 的演进CMake 策略 CMP0025 深度解析Apple Clang 编译器标识从 Clang 到 AppleClang 的演进 本指南以 CMake 官方策略文构建工具开发工具CLICMake CMP0129 政策解析MCST LCC 编译器识别从 GNU 到 LCC 的迁移指南CMake CMP0129 政策解析MCST LCC 编译器识别从 GNU 到 LCC 的迁移指南 导读 本文深入剖析 CMake 3.23 引入的策略 CM构建工具开发工具CLI上一篇终极Ventoy指南如何制作一个永久可用的多系统启动U盘下一篇Mermaid Live Editor终极指南零代码创建专业图表的免费神器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表