文章目錄

  • 1. 為什麼使用 Modules
  • 2. 項目搭建
  • 2.1 工程結構
  • 2.2 代碼編寫
  • 3. cmakelist.txt 配置
  • 3.1 查看 CMAKE_EXPERIMENTAL_CXX_IMPORT_STD 值
  • 3.2 Cmakelist.txt 編寫
  • 3.3 項目編譯配置
  • 4. 編譯運行測試
  • 5. 代碼

1. 為什麼使用 Modules

模塊(Modules)是 C++20 引入了一個重要的新特性,解決頭文件(如編譯速度慢、宏污染、重複包含、依賴管理混亂等問題。使用體驗上更現代,和其他語言類似。所以使用modules一是為了體驗新特性的使用,學習c++ 新標準,也是為了以後項目遷移做準備。

2. 項目搭建

2.1 工程結構

Visual Studio 2022 Preview 使用 C++20 Module__#c++ modules

2.2 代碼編寫

io.cppm :

export module io;

export void print_result(const char* label, int value);

io_impl.cpp:

module;                  // 開啓全局模塊段
#include <iostream>      // 實現中使用標準庫也需要前置包含

module io;               // 指定所屬模塊

void print_result(const char* label, int value) {
    std::cout << label << value << std::endl;
}

這裏 module 用於開啓全局模塊段, 在兼容導入原始頭文件時使用,在實現中使用標準庫也需要前置包含。module io, 用於指定所屬模塊。
math.cppm:

export module math;                // 聲明並導出模塊

export int add(int a, int b);      // 導出函數聲明
export int multiply(int a, int b); // 另一個導出函數

math_impl.cpp:

module math;  // 指定所屬模塊

int add(int a, int b) {
    return a + b;
}

int multiply(int a, int b) {
    return a * b;
}

main.cpp:

import std;

import io;    // 導入IO模塊
import math;  // 導入數學模塊

int main() {
    std::println("Use std module on {}", "hello");
    
    int sum = add(3, 4);       // 使用模塊導出函數
    int product = multiply(3, 4);
    print_result("Sum:    ", sum);
    print_result("Product:", product);
    return 0;
}

import std, 是c++ 23提供的modules 標準庫模塊。 std::println(“Use std module on {}”, “hello”); 是c++ 23 提供的插值表達式。

3. cmakelist.txt 配置

要使用c++ 23 import std 支持需要比較新的編譯器和cmke版本支持,構建工具使用ninja, make 目前不支持。環境搭建和工具安裝參考前面章節。

3.1 查看 CMAKE_EXPERIMENTAL_CXX_IMPORT_STD 值

地址:https://github.com/Kitware/CMake/blob/v4.2.0/Help/dev/experimental.rst 根據自己cmake版本來查詢對應的版本, 此提供很多支持。

Visual Studio 2022 Preview 使用 C++20 Module__導出函數_02

類別

特性

核心用途

C++ 語言特性

C++ import std support

啓用 C++23 標準庫模塊導入。

包管理

Export Package Dependencies

自動導出包的依賴關係,方便下游使用。

包管理

Export CPS Package Information

以標準化的 CPS 格式導出包元數據。

包管理

Find/Import CPS Packages

支持查找符合 CPS 規範的包。

構建工具集成

Build database support

導出構建信息數據庫,供 IDE 和分析工具使用。

高級構建分析

Instrumentation

在構建過程中插入自定義邏輯,收集額外數據。

如果只使用 import std 只需要引入對應的就行,這裏為了方便,直接導入全部。

3.2 Cmakelist.txt 編寫

cmake_minimum_required(VERSION 4.2.0)

set(CMAKE_CXX_MODULE_STD ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_CXX_EXTENSIONS ON)

# 啓用 C++23 標準庫模塊導入
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD  "d0edc3af-4c50-42ea-a356-e2862fe7a444")
# 自動導出包的依賴關係,方便下游使用
set(CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_DEPENDENCIES  "1942b4fa-b2c5-4546-9385-83f254070067")
# 以標準化的 CPS 格式導出包元數據
set(CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO  "b80be207-778e-46ba-8080-b23bba22639e")
# 支持查找符合 CPS 規範的包
set(CMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES  "e82e467b-f997-4464-8ace-b00808fff261")
# 導出構建信息數據庫,供 IDE 和分析工具使用
set(CMAKE_EXPERIMENTAL_EXPORT_BUILD_DATABASE  "73194a1d-c0b5-41b9-9190-a4512925e192")
# 在構建過程中插入自定義邏輯,收集額外數據
set(CMAKE_EXPERIMENTAL_INSTRUMENTATION  "ec7aa2dc-b87f-45a3-8022-fe01c5f59984")


project(app LANGUAGES CXX)

# 生成 compile_command.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(TARGET app)


############## 模塊配置 ##############################################
# 創建數學模塊庫
add_library(math_mod)
target_sources(math_mod
    PUBLIC
        # 模塊接口文件集
        FILE_SET cxx_modules TYPE CXX_MODULES
            BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/math
            FILES src/math/math.cppm
    
    PRIVATE
        # 實現文件
        src/math/math_impl.cpp
)

# io 模塊
add_library(io_mod)
target_sources(io_mod
    PUBLIC
        # 模塊接口文件集
        FILE_SET cxx_modules TYPE CXX_MODULES
            BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/io
            FILES src/io/io.cppm
    
    PRIVATE
        # 實現文件
        src/io/io_impl.cpp
)



############## 三方庫配置 #############################################

############### 項目配置 ##############################################
# 頭文件
include_directories(${CMAKE_SOURCE_DIR}/include)

# 源文件
file(GLOB SRC_FILES
    ${CMAKE_SOURCE_DIR}/src/*.cpp
)

# 創建主程序
add_executable(${TARGET} src/app/main.cpp)
target_link_libraries(${TARGET} PRIVATE math_mod io_mod)

3.3 項目編譯配置

這裏使用llvm-mingw, 使用mingw 測試編譯有問題, 編譯器下載及環境安裝參考之前章節。

  • 項目配置: .vscode/settings.json
{
    "cmake.generator": "Ninja",
    "clangd.path": "C:/software/llvm-mingw-20251118-ucrt-x86_64/bin/clangd.exe",
    "clangd.arguments": [
        "--compile-commands-dir=${workspaceFolder}/build",
        "--query-driver=C:/software/llvm-mingw-20251118-ucrt-x86_64/bin/g++.exe",
        "--log=verbose",
        "--pretty",
        "--all-scopes-completion",
        "--completion-style=bundled",
        "--cross-file-rename",
        "--header-insertion=never",
        "--background-index",
        "--clang-tidy",
        "--clang-tidy-checks=cppcoreguidelines-*,performance-*,bugprone-*,portability-*,modernize-*,google-*",
        "-j=2",
        "--pch-storage=disk",
        "--function-arg-placeholders=false",
        "--experimental-modules-support"
    ]
}

上述項目配置會有些提示,忽略就可以:

Visual Studio 2022 Preview 使用 C++20 Module__#c++ modules_03

4. 編譯運行測試

選擇編譯器:

ctrl + shift + p 後選擇 CMake: Select a Kit

Visual Studio 2022 Preview 使用 C++20 Module__c++_04


選擇之前安裝的最新版llvm-mingw:

Visual Studio 2022 Preview 使用 C++20 Module__#c++ modules_05


點擊左下角編譯運行:

Visual Studio 2022 Preview 使用 C++20 Module__c++_06

  • 測試結果:
  • 如果出現編譯通過, vscode 代碼提示 import 未找到或者不能識別的問題,檢查clangd插件環境,嘗試重啓vscode, 重新編譯來解決。