| name | module-file-template |
| description | Apply the C++26 module file structure used throughout this codebase. Use when creating any new .cc, .cppm, or test file, deciding between import gblib/import std vs include, choosing module partition names, or fixing module-related build errors. Covers global module fragment, import order, partition syntax, and when (rarely) #include is allowed. |
| user-invocable | false |
Module File Template
This codebase uses C++ Modules end-to-end. Every new translation unit follows a strict shape so the build stays clean and partition discovery works.
Implementation File (.cc)
module;
#include "gb/files.h"
import gblib;
import std;
module commands;
namespace GB::commands {
}
Rules:
- SPDX header on line 1.
module; opens the global module fragment. Only place #include may appear is between module; and any import.
import gblib; first, then import std; (prefer over import std.compat; in new code).
module <name>; declares which named module/partition this file implements. Must come after all imports.
- Tests typically also need
import dallib;.
Module Interface Partition (.cppm)
export module gblib:partition_name;
import std;
import :types;
import :services;
export class Foo { };
export void bar();
Rules:
- Single
export module ... declaration per file.
- Within
gblib, partitions are referenced as :partition (e.g. :types, :ships).
- Mark every public symbol with
export. Internal helpers stay unmarked.
- No
#include in interface partitions except inside module; if a legacy header is unavoidable.
Test File
import dallib;
import gblib;
import std;
#include <cassert>
int main() {
Database db(":memory:");
initialize_schema(db);
std::println("Test passed!");
return 0;
}
<cassert> may be included after the imports (assert is a macro, so import std doesn't expose it). See the database-test-pattern skill for the full test pattern.
When #include Is Allowed
Only for legacy artifacts that have not yet been modularized:
gb/files.h (path constants, file-name macros)
gb/buffers.h (legacy buffer macros)
<cassert> in tests
Anything else should be reached via import gblib, import dallib, import std, or import commands.
Adding a Source File to the Build
In gb/CMakeLists.txt, append the path under the appropriate target:
target_sources(commands PRIVATE
commands/foo.cc
commands/bar.cc
)
Module interface partitions are added with FILE_SET CXX_MODULES:
target_sources(gblib PUBLIC
FILE_SET CXX_MODULES FILES
gblib-foo.cppm
)
Match the pattern of nearby entries — don't invent a new shape.
Common Build Errors and Fixes
| Symptom | Cause | Fix |
|---|
| "module ... not found" | Missing partition import or partition not in CMake | Add import :name; and add .cppm to FILE_SET CXX_MODULES |
| "cannot use 'export' in non-module" | Missing export module ...; | Add the module declaration before export |
| "include after module" | #include placed after an import | Move includes inside the module; fragment |
| Symbol not found at link time | Symbol not marked export | Add export in the .cppm |
Anti-Patterns
- ❌ Mixing
#include for project headers when an import exists.
- ❌ Both
import std; and import std.compat; in the same file.
- ❌ Declaring a function in a
.cppm without export then using it from another TU.
- ❌ Putting includes after imports.
- ❌ Multiple
module xxx; lines per file.
Checklist