cmake-cxxmodules(7)

於 3.28 版本新增。

C++ 20 在語言中引入了「模組」的概念。此設計要求建置系統在彼此之間對編譯進行排序,以可靠地滿足 import 陳述式。CMake 的實作方式是要求編譯器在建置期間掃描原始檔以查找模組依賴性,整理掃描結果以推斷排序約束,並告知建置工具如何動態更新建置圖。

編譯策略

使用 C++ 模組時,編譯一組 C++ 原始碼不再是易於並行的。也就是說,任何給定的原始碼可能首先需要先編譯另一個原始檔,以便提供 C++ 編譯器用來滿足其他原始碼中 import 陳述式的「CMI」(編譯的模組介面)或「BMI」(二進制模組介面)。使用標頭檔時,原始碼可以共享它們的宣告,以便任何消費者都可以獨立編譯。使用模組時,宣告現在由編譯器在編譯期間根據原始檔的內容及其 export 陳述式產生到這些 BMI 檔案中。

編譯所需的順序需要建置時解析順序,因為順序是由原始碼的內容控制的。這表示需要在建置期間從原始碼中提取順序,以避免透過配置和產生階段為每個原始碼變更重新產生建置圖,以取得正確的建置。

一般策略是使用「掃描器」來提取排序依賴資訊,並透過採用每個原始碼的掃描結果(以 P1689R5 檔案表示)並「整理」目標內以及目標可見的目標所產生之模組的依賴性,來更新現有邊緣之間的新邊緣的建置圖。主要任務是產生「模組對應」檔案,將滿足 import 陳述式所需的 BMI 路徑傳遞給每個編譯規則。整理器還具有使用建置時資訊來填寫資訊的任務,包括模組介面單元、其 BMI 的 install 規則,以及任何具有 C++ 模組的匯出目標的屬性。

注意

CMake 專注於正確的建置,然後才考慮效能改進。在選定的策略中,有一些已知的方法可以提供建置效能的改進。但是,這些方法將被推遲到我們有一個可供比較的工作模型之後。同樣重要的是要注意,在某種情況下有用的方法(例如,清除建置)在不同的情況下(例如,增量建置)可能沒有效能。尋找平衡並提供控制項來選擇方法是未來的工作。

掃描控制

是否掃描來源以查找 C++ 模組的使用情況,取決於以下查詢。使用提供是/否答案的第一個查詢。

  • 如果原始檔屬於類型為 CXX_MODULES 的檔案集,則會掃描它。

  • 如果目標未使用至少 C++ 20,則不會掃描它。

  • 如果原始檔不是 CXX 語言,則不會掃描它。

  • 如果設定了 CXX_SCAN_FOR_MODULES 原始檔屬性,則會使用其值。

  • 如果設定了 CXX_SCAN_FOR_MODULES 目標屬性,則會使用其值。設定 CMAKE_CXX_SCAN_FOR_MODULES 變數,以便在建立所有目標時初始化此屬性。

  • 否則,如果編譯器和產生器支援掃描,則會掃描原始檔。請參閱原則 CMP0155

請注意,任何掃描的來源都將從任何統一建置中排除(請參閱 UNITY_BUILD),因為模組相關的陳述式只能在 C++ 轉譯單元中的一個位置發生。

編譯器支援

CMake 原生支援模組依賴性掃描的編譯器包括

  • MSVC 工具集 14.34 及更新版本(隨 Visual Studio 17.4 及更新版本提供)

  • LLVM/Clang 16.0 及更新版本

  • GCC 14(針對開發中的分支,在 2023-09-20 之後)及更新版本

import std 支援

import std 的支援僅限於以下工具鏈和標準程式庫組合

  • Clang 18.1.2 及更新版本,使用 -stdlib=libc++

  • MSVC 工具集 14.36 及更新版本(隨 Visual Studio 17.6 Preview 2 及更新版本提供)

可以使用 CMAKE_CXX_COMPILER_IMPORT_STD 變數,以偵測具有現用 C++ 工具鏈的標準層級的支援。

注意

只有在 CMAKE_EXPERIMENTAL_CXX_IMPORT_STD 閘道啟用 import std; 的實驗性支援時,才會提供此支援。

產生器支援

支援掃描來源以查找 C++ 模組的產生器列表包括

限制

CMake 中目前的 C++ 模組支援存在許多已知的限制。這不會記錄編譯器中已知的限制或錯誤,因為這些限制或錯誤可能會隨著時間而改變。

對於所有產生器

  • 不支援標頭單元。

  • 沒有內建支援 import std; 或其他編譯器提供的模組。

對於 Ninja 產生器

  • 需要 1.11 或更新版本的 ninja

對於 Visual Studio 產生器

  • 僅限 Visual Studio 2022 和 MSVC 工具集 14.34 (Visual Studio 17.4) 及更新版本。

  • 不支援匯出或安裝 BMI 或模組資訊。

  • 不支援從具有 C++ 模組的 IMPORTED 目標編譯 BMI(包括 import std)。

  • 沒有診斷從 PUBLIC 模組來源使用 PRIVATE 來源提供的模組。