Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

C++20 Modules

This project uses C++20 modules instead of traditional headers. Here’s what I learned getting them to work with CMake + Clang on MSYS2.

File convention

  • Module interface files: .cppm extension
  • Regular source files: .cpp (use import to consume modules)

Both live under src/.

CMake setup

CMake 3.28+ has native support for C++20 modules via FILE_SET CXX_MODULES:

cmake_minimum_required(VERSION 3.28)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS "src/*.cpp")
file(GLOB_RECURSE MODULE_FILES CONFIGURE_DEPENDS "src/*.cppm")

add_executable(${PROJECT_NAME})
target_sources(${PROJECT_NAME} PRIVATE ${SOURCE_FILES})
target_sources(${PROJECT_NAME} PRIVATE FILE_SET CXX_MODULES FILES ${MODULE_FILES})

Ninja is required

MinGW Makefiles does not support C++20 modules. You must use Ninja:

cmake -B build -G Ninja \
  -DCMAKE_C_COMPILER=clang \
  -DCMAKE_CXX_COMPILER=clang++

If you try -G "MinGW Makefiles", CMake will fail to resolve module dependencies.

Writing a module

A .cppm file looks like this:

module;

// global module fragment — #include traditional headers here
#include <vulkan/vulkan.h>
#include <GLFW/glfw3.h>

export module app;

export class App {
public:
  void Run();

private:
  void InitWindow();
  void InitVulkan();
  void MainLoop();
  void Cleanup();
};

Key points:

  • module; starts the global module fragment — put all #include directives here
  • export module <name>; declares the module name
  • export before declarations makes them visible to importers

Consuming a module

In a .cpp file:

import app;

int main() {
  App app;
  app.Run();
  return 0;
}

Gotchas

  1. Include order matters: All #include lines must go in the global module fragment (between module; and export module). Putting #include after export module is a hard error.

  2. clangd support: clangd needs compile_commands.json (generated by CMake with CMAKE_EXPORT_COMPILE_COMMANDS ON). Module support in clangd is still evolving — occasional false errors are normal.

  3. Build order: CMake + Ninja handle module dependency scanning automatically. No manual ordering needed.