)
構(gòu)建工具開發(fā)工具CLI【免費下載鏈接】CMakeMirror of CMake upstream repository項目地址https://gitcode.com/gh_mirrors/cm/CMake點擊查看免費下載導(dǎo)讀CMP0047 是 CMake 自 3.0 起引入的一項兼容性策略它解決了一個在 QNX 嵌入式開發(fā)中非常具體的問題當(dāng)使用 QNX 的qcc編譯器驅(qū)動時CMake 應(yīng)當(dāng)把CMAKE_LANG_COMPILER_ID報告為QCC還是舊有的GNU。本文以 CMP0047.rst 文檔為主體結(jié)合本倉庫中 cmPolicies.h 的策略注冊與 Modules/Compiler/QCC-*.cmake 的編譯器實現(xiàn)完整講解該策略的 OLD/NEW 行為、設(shè)置時機、遷移方式以及 QNX 工具鏈的底層細(xì)節(jié)。讀完本文你將掌握如何在舊項目與現(xiàn)代 CMake 之間正確對齊 QNX 交叉編譯的 Compiler ID并理解這一變更對特性檢測、編譯旗標(biāo)選擇的影響。一、策略背景為什么 qcc 需要自己的 Compiler IDQNX 實時操作系統(tǒng)RTOS的官方編譯器驅(qū)動名為qcc針對 C/C其底層通常封裝了 GCC 兼容的代碼生成后端。在 CMake 3.0 之前CMake 只把qcc當(dāng)作 GNU 編譯器家族的一員處理CMAKE_LANG_COMPILER_ID一律報告為GNU。這種簡化在早期可行但存在隱患qcc驅(qū)動在命令行語義上與裸gcc有明顯差異例如 C 語言模式需要顯式傳入-lang-c或-x c這樣的驅(qū)動級旗標(biāo)而不是由 gcc 默認(rèn)推斷項目無法通過 Compiler ID 精確區(qū)分真正的 GCC和QNX 的 qcc 封裝導(dǎo)致針對性的工具鏈適配邏輯無從下手。CMake 3.0 起CMake 正式承認(rèn) QNXqcc驅(qū)動與 GNU 編譯器是兩回事并引入獨立編譯器 IDQCC參見CMAKE_ _COMPILER_ID變量文檔中QCC— QNX C/C compiler 這一取值。但考慮到存量項目可能依然假設(shè) qcc 的 ID 是GNU直接改默認(rèn)值會破壞這些項目的條件判斷于是通過策略 CMP0047 讓新舊行為平滑過渡。二、策略定義CMP0047 的 OLD 與 NEW 行為根據(jù) CMP0047.rst該策略的語義如下行為效果OLD舊行為對 qcc 與 QCC 兩類編譯器驅(qū)動CMAKE_LANG_COMPILER_ID報告為GNUNEW新行為對 qcc 與 QCC 兩類編譯器驅(qū)動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.與文檔標(biāo)題完全一致。策略注冊位于cmPolicies.h的策略表中意味著它在 CMake 的cmake_minimum_required版本判定體系內(nèi)是標(biāo)準(zhǔn)策略之一可通過常規(guī)的 cmake_policy() 機制被讀取與設(shè)置。關(guān)鍵約束必須在使用前設(shè)置文檔明確指出該策略必須在project()或enable_language()被調(diào)用之前設(shè)置因為語言啟用過程會讀取編譯器信息、寫入CMAKE_LANG_COMPILER_ID策略在那一刻才決定用哪個 ID。錯過時機再調(diào)用cmake_policy(SET CMP0047 ...)將不會對已啟用的語言生效。推薦的設(shè)置方式cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0047 NEW) # 顯式選擇 QCC 編譯器 ID project(MyQnxProject C CXX) # 語言啟用發(fā)生在策略設(shè)置之后或直接依賴版本聲明隱式啟用cmake_minimum_required(VERSION 3.5) # 3.0 的策略默認(rèn)即 NEW需要說明在 CMake 3.0 至 4.0 之前的版本中若項目沒有顯式設(shè)置該策略CMake 會按默認(rèn)策略行為處理并可通過CMAKE_POLICY_WARNING_CMP0047變量參見 CMAKE_POLICY_WARNING_CMP 控制是否輸出策略警告。默認(rèn)情況下該策略在 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設(shè)置為NEW。這帶來兩個直接影響最低版本 ≥ 4.0 的項目cmake_minimum_required(VERSION 4.0)會讓 CMP0047 自動處于NEW狀態(tài)QNX 下 Compiler ID 必然是QCC無需額外處理最低版本 4.0 的存量項目若代碼中仍存在針對GNUID 的 QNX 分支例如if(CMAKE_C_COMPILER_ID STREQUAL GNU)在升級 CMake 到 4.0 后該分支將不再命中需要遷移為檢查QCC。這正是該策略與其他已移除 OLD 行為策略如 CMP0001–CMP00xx 系列中同樣標(biāo)注 REMOVED 的策略一致的演進(jìn)路徑先以默認(rèn)舊行為兼容存量再通過警告提醒最終在新大版本中強制新行為。四、源碼縱深QCC 編譯器模塊在倉庫中的真實實現(xiàn)策略 CMP0047 的落地不止于cmPolicies.h中的一條注冊記錄還配套了一整套以QCC命名的編譯器模塊。在 Modules/Compiler 目錄下可以看到QCC-C.cmake、QCC-CXX.cmake、QCC-ASM.cmake各語言的編譯/鏈接規(guī)則入口QCC-C-FeatureTests.cmake、QCC-CXX-FeatureTests.cmake語言特性探測QCC.cmake公共宏__compiler_qcc的定義以 QCC-C.cmake 為例其實現(xiàn)非常精簡# To include compiler feature detection include(Compiler/GNU-C) include(Compiler/QCC) __compiler_qcc(C)注意第一行QCC 的 C 語言特性檢測直接復(fù)用了Compiler/GNU-C。這一點與策略背景相互印證——qcc 的代碼生成后端與 GCC 兼容因此絕大多數(shù) GNU 編譯旗標(biāo)與特性宏依然適用但 Compiler ID 卻獨立為QCC使項目既能復(fù)用 GCC 特性語義又能識別出驅(qū)動差異。QCC-CXX.cmake 則展示了更實質(zhì)的驅(qū)動差異——C 語言模式旗標(biāo)隨 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)從中可以讀出兩個關(guān)鍵事實驅(qū)動不是 gccqcc 驅(qū)動默認(rèn)并不自動選擇 C 語言模式CMake 必須顯式傳入語言旗標(biāo)這正是 Compiler ID 必須區(qū)別于GNU的底層原因版本分支qcc 12.2.0QNX 8.0 工具鏈之前的版本使用-lang-c之后的版本使用-x c且鏈接階段無需語言旗標(biāo)。這說明CMAKE_CXX_COMPILER_VERSION在 QNX 工具鏈上同樣可用項目可以安全地用它做版本判斷。此外QCC-ASM.cmake 僅包含include(Compiler/QCC)與__compiler_qcc(ASM)兩行表明 QCC 編譯器 ID 同樣適用于 ASM 語言而 Modules/Platform/QNX-Initialize.cmake 則負(fù)責(zé) QNX 平臺層的初始化與編譯器層的 QCC 模塊協(xié)同完成整套 QNX 交叉編譯支持。五、實戰(zhàn)遷移舊項目到 QCC Compiler ID假設(shè)你有一個面向 QNX 的存量 CMake 工程其配置文件中曾有如下分支if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) # 誤把 qcc 當(dāng)成 GNU 處理的舊邏輯 add_compile_options(-fno-exceptions) endif()在 CMake 3.0 中若項目仍隱式處于 CMP0047 的 OLD 行為上述分支在 qcc 下依然命中但語義是碰巧的一旦切到 NEW 行為或升級到 CMake 4.0該分支將失效。正確遷移步驟聲明策略在project()之前顯式cmake_policy(SET CMP0047 NEW)或?qū)make_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在配置階段打印確認(rèn)message(STATUS QNX Compiler ID ${CMAKE_CXX_COMPILER_ID}) message(STATUS QNX Compiler Version ${CMAKE_CXX_COMPILER_VERSION})回歸測試特性檢測由于 QCC-C/CXX 模塊復(fù)用了 GNU 的特性測試見 QCC-C-FeatureTests.cmakecheck_cxx_compiler_flag、write_compiler_detection_header等依賴 Compiler ID 的機制會以QCC作為 ID 前綴生成檢測頭請同步檢查任何硬編碼了GNU的檢測頭消費代碼。常見問題Q不設(shè)置該策略會怎樣在 CMake 3.x–3.27 等版本中默認(rèn)沿用舊行為報告GNU策略本身默認(rèn)不告警因此存量項目不會立即報錯但跨過 CMake 4.0 后舊行為被移除編譯器 ID 會突然變?yōu)镼CC提前遷移可避免升級沖擊。QCMAKE_CXX_COMPILER_ID為QCC與CMAKE_CXX_COMPILER指向qcc/QCC有區(qū)別嗎Compiler ID 是 CMake 通過編譯探測CompilerId 工程識別出的廠商標(biāo)識qcc與QCC兩個驅(qū)動都會得到QCC這個 ID而QCC-CXX.cmake中的版本分支正是為了兼容驅(qū)動名為 qcc 但版本口徑不同的兩種工具鏈形態(tài)。Q策略設(shè)置時機為什么如此嚴(yán)格因為project()/enable_language()在啟用語言的同時完成編譯器探測并固化CMAKE_LANG_COMPILER_IDCMP0047 正是這一探測結(jié)果的顯示器自然必須先行設(shè)置。這一約束在 CMP0047.rst 文檔中已明確強調(diào)。六、與其他 QNX 相關(guān)機制的關(guān)系CMP0047 只是 CMake QNX 支持的一部分。從倉庫結(jié)構(gòu)看QNX 支持由多層協(xié)同構(gòu)成策略層CMP0047.rst 決定 Compiler ID 的取值口徑編譯器層Modules/Compiler/QCC-*.cmake 系列模塊按 IDQCC提供各語言的編譯/鏈接規(guī)則與特性檢測平臺層Modules/Platform/QNX-Initialize.cmake 完成系統(tǒng)級初始化變量層CMAKE_ _COMPILER_ID文檔中QCC被登記為 QNX C/C compiler 的官方取值可供所有項目在條件判斷中引用。理解這一層次關(guān)系后遇到 QNX 工具鏈問題時可以按ID 是否對 → 規(guī)則是否生效 → 平臺初始化是否正確的順序排查而 CMP0047 正是第一環(huán)。總結(jié)CMP0047 是 CMake 3.0 引入、并在 CMake 4.0 中強制收口的 QNX 編譯器識別策略O(shè)LDqcc/QCC 驅(qū)動報告GNU編譯器 IDNEWqcc/QCC 驅(qū)動報告獨立的QCC編譯器 ID必須在project()/enable_language()之前設(shè)置配套實現(xiàn)見 cmPolicies.h 與 Modules/Compiler/QCC-*.cmake其中 QCC-CXX 的版本分支qcc 12.2.0 前后使用不同的 C 語言旗標(biāo)說明了 ID 獨立化的根本動機——qcc 并非 GNU 編譯器只是與其兼容的 QNX 驅(qū)動。對于維護(hù) QNX 交叉編譯工程的開發(fā)者建議在 CMake 4.0 落地前完成 Compiler ID 的顯式對齊把所有針對 qcc 的GNU判斷遷移為QCC從而讓工具鏈識別更精確、升級路徑更平滑。贊分享構(gòu)建工具開發(fā)工具CLI【免費下載鏈接】CMakeMirror of CMake upstream repository項目地址https://gitcode.com/gh_mirrors/cm/CMake點擊查看免費下載相關(guān)推薦Meson 對 QNX qcc/q 編譯器驅(qū)動的支持交叉編譯配置、實現(xiàn)原理與已知限制Meson 對 QNX qcc/q 編譯器驅(qū)動的支持交叉編譯配置、實現(xiàn)原理與已知限制 Meson Build System 自本版本起正式支持 QNX S構(gòu)建工具CMake 策略 CMP0025 深度解析Apple Clang 編譯器標(biāo)識從 Clang 到 AppleClang 的演進(jìn)CMake 策略 CMP0025 深度解析Apple Clang 編譯器標(biāo)識從 Clang 到 AppleClang 的演進(jìn) 本指南以 CMake 官方策略文構(gòu)建工具開發(fā)工具CLICMake CMP0129 政策解析MCST LCC 編譯器識別從 GNU 到 LCC 的遷移指南CMake CMP0129 政策解析MCST LCC 編譯器識別從 GNU 到 LCC 的遷移指南 導(dǎo)讀 本文深入剖析 CMake 3.23 引入的策略 CM構(gòu)建工具開發(fā)工具CLI上一篇終極Ventoy指南如何制作一個永久可用的多系統(tǒng)啟動U盤下一篇Mermaid Live Editor終極指南零代碼創(chuàng)建專業(yè)圖表的免費神器創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考