Article by Ayman Alheraki on July 10 2026 02:43 AM
Download the winlibs Version : https://github.com/brechtsanders/winlibs_mingw/releases/download/16.1.0posix-14.0.0-ucrt-r3/winlibs-x86_64-posix-seh-gcc-16.1.0-mingw-w64ucrt-14.0.0-r3.zip
After years of waiting, testing, partial implementations, unusual compiler switches, and inconsistent behavior across platforms, I can finally confirm that a complete basic C++20 named-module workflow works successfully with GCC 16.1 on Windows 11.
By “complete workflow,” I mean that GCC successfully performed every essential stage:
Compiled a module interface unit.
Generated the Compiled Module Interface file.
Compiled another translation unit that imported the module.
Linked the generated object files.
Produced a native Windows executable.
Ran the program and returned the expected results.
This is an important practical milestone for programmers who use GCC and MinGW-w64 on Windows.
The test was performed on Windows 11 using this compiler:
g++.exe (MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders, r2) 16.1.0Copyright (C) 2026 Free Software Foundation, Inc.This configuration means:
GCC 16.1.0
64-bit x86-64 target
MinGW-w64
Microsoft Universal C Runtime, or UCRT
POSIX threading model
Structured Exception Handling, or SEH
WinLibs release 2
WinLibs provides standalone GCC and MinGW-w64 distributions for Windows, including GCC 16.1 builds using UCRT and POSIX threads.
No Visual Studio installation was required.
No MSYS2 environment was required.
The compiler was used directly from Windows Command Prompt.
C++ modules were standardized in C++20 to provide a modern alternative to the traditional textual inclusion model based on #include.
Instead of repeatedly copying header-file contents into translation units, modules introduce explicitly exported interfaces that compilers can process and reuse.
Their intended benefits include:
Better separation between interfaces and implementations.
Reduced dependence on preprocessor inclusion.
Improved isolation between libraries.
Potentially faster compilation in large projects.
Fewer macro-related conflicts.
More explicit dependency relationships.
GCC describes modules as a modular compilation system intended to improve build performance and library isolation.
However, module support in GCC has historically been experimental and incomplete. GCC 15 brought major improvements, and GCC 16 continues this progress.
The test consists of two source files:
xxxxxxxxxxcalculator.cppmmain.cppThe first file defines and exports a named module. The second imports and uses it.
calculator.cppmxexport module calculator;
export int add(int a, int b){ return a + b;}
export int multiply(int a, int b){ return a * b;}The declaration:
xxxxxxxxxxexport module calculator;declares a named module called calculator.
The exported functions:
xxxxxxxxxxexport int add(int a, int b);export int multiply(int a, int b);become part of the public module interface and can be used by translation units that import the module.
Unlike a conventional header file, this file is compiled as a module interface unit.
main.cppxxxxxxxxxximport calculator;
int main(){ std::cout << "20 + 22 = " << add(20, 22) << '\n'; std::cout << "6 * 7 = " << multiply(6, 7) << '\n';
return 0;}The important line is:
xxxxxxxxxximport calculator;There is no declaration of add() or multiply() inside main.cpp.
There is also no traditional header such as:
xxxxxxxxxxThe compiler obtains the exported declarations from the compiled interface of the calculator module.
The two files were placed in the same directory:
xxxxxxxxxxC:\Cpp\ModuleTestCommand Prompt was opened in that directory:
xxxxxxxxxxcd /d C:\Cpp\ModuleTestOld object files and module cache files were removed before compiling:
xxxxxxxxxxrmdir /s /q gcm.cache 2>nuldel /q calculator.o main.o module-test.exe 2>nulCleaning gcm.cache is useful during testing because an old Compiled Module Interface may no longer match the current source code or compiler configuration.
The module interface must be compiled before any source file that imports it:
xxxxxxxxxxg++ -std=c++20 -fmodules -Wall -Wextra -x c++ -c calculator.cppm -o calculator.oThe options mean:
xxxxxxxxxx-std=c++20 Compile using the C++20 language standard-fmodules Enable GCC module support-Wall Enable commonly useful warnings-Wextra Enable additional warnings-x c++ Explicitly treat the input as C++ source-c Compile without linking-o Select the output object filenameAlthough GCC 16 uses C++20 as its default C++ language mode, module support is not enabled automatically. The -fmodules option remains necessary.
The -x c++ option was used to ensure that the .cppm file was treated as C++ source by this particular Windows toolchain.
After compilation, GCC created two important outputs:
xxxxxxxxxxcalculator.ogcm.cache\calculator.gcmThe object file contains the compiled machine code.
The .gcm file contains GCC’s Compiled Module Interface, commonly abbreviated as CMI.
The generated module cache can be inspected with:
xxxxxxxxxxdir /s gcm.cacheThe presence of:
xxxxxxxxxxgcm.cache\calculator.gcmconfirms that GCC recognized and compiled the file as a module interface.
After the module interface was available, the consumer was compiled:
xxxxxxxxxxg++ -std=c++20 -fmodules -Wall -Wextra -flang-info-module-cmi -c main.cpp -o main.oThe option:
xxxxxxxxxx-flang-info-module-cmiasks GCC to report information about the Compiled Module Interface that it reads.
During this stage, GCC successfully found and loaded:
xxxxxxxxxxgcm.cache\calculator.gcmThis proves that the import calculator; declaration was resolved through the generated module interface rather than through a traditional header file.
The two object files were linked:
xxxxxxxxxxg++ calculator.o main.o -o module-test.exeThis generated a native Windows executable:
xxxxxxxxxxmodule-test.exeNotice that the .gcm file is not passed directly to the linker.
The CMI is needed during compilation of the importing source file. The linker works with the resulting object files:
xxxxxxxxxxcalculator.omain.oThe resulting program was executed:
xxxxxxxxxxmodule-test.exeThe output was:
xxxxxxxxxx20 + 22 = 426 * 7 = 42This confirms that:
The module interface was parsed correctly.
Its exported functions were compiled.
The CMI was generated.
The importing translation unit found the module.
Exported declarations were visible to the importer.
The object files linked correctly.
The resulting Windows executable ran successfully.
The entire test can be repeated using these commands:
xxxxxxxxxxcd /d C:\Cpp\ModuleTest
rmdir /s /q gcm.cache 2>nuldel /q calculator.o main.o module-test.exe 2>nul
g++ -std=c++20 -fmodules -Wall -Wextra -x c++ -c calculator.cppm -o calculator.o
dir /s gcm.cache
g++ -std=c++20 -fmodules -Wall -Wextra -flang-info-module-cmi -c main.cpp -o main.o
g++ calculator.o main.o -o module-test.exe
module-test.exeExpected output:
xxxxxxxxxx20 + 22 = 426 * 7 = 42This test proves that basic named C++20 modules work end-to-end with GCC 16.1 on Windows 11 using a 64-bit WinLibs MinGW-w64 UCRT toolchain.
The following features were tested successfully:
| Feature | Result |
|---|---|
| Module declaration | Successful |
| Exported functions | Successful |
.cppm module interface | Successful |
| CMI generation | Successful |
gcm.cache creation | Successful |
| Module import | Successful |
| Separate compilation | Successful |
| Object-file generation | Successful |
| Windows linking | Successful |
| Native executable generation | Successful |
| Runtime execution | Successful |
This was not merely a syntax test.
It was a complete compile-import-link-run test.
It would be inaccurate to conclude from this example that every part of the C++ module specification is now completely implemented.
GCC’s own documentation still states that its module support is not complete, and the GCC 16 release notes continue to classify C++20 module support as experimental.
Advanced projects may still encounter limitations involving areas such as:
Private module fragments.
Complex module partitions.
Header units.
Large dependency graphs.
Build-system dependency discovery.
Cross-compiler CMI portability.
Interaction with macros and legacy headers.
Mixing modules with complicated template libraries.
Automatic module build ordering.
A CMI generated by one compiler should also be treated as compiler-specific build output rather than as a portable binary library interface.
Therefore, the accurate conclusion is:
The complete basic named-module workflow works successfully with GCC 16.1 on Windows 11, but GCC’s implementation of the entire C++ modules specification remains experimental and has documented limitations.
For a long time, using C++ modules with GCC—especially on Windows—felt more like experimenting with compiler internals than using a production language feature.
Simple examples could fail because of:
Unsupported file extensions.
Missing compiler options.
Incorrect compilation order.
Stale module cache files.
Toolchain differences.
Incomplete module implementations.
Poor build-system integration.
With GCC 16.1, the fundamental workflow is now much clearer and more reliable:
xxxxxxxxxxModule interface ↓Compiled Module Interface ↓Importing translation unit ↓Object files ↓Native Windows executableThis does not mean that header files will disappear immediately.
It does mean that GCC users on Windows can now begin realistic experiments with named modules without depending exclusively on Microsoft Visual C++.
C++20 modules have finally reached a practically usable stage for basic applications with GCC 16.1 on Windows 11.
Using a WinLibs MinGW-w64 GCC 16.1 toolchain, I successfully:
Created a named module.
Exported functions from it.
Generated a GCC Compiled Module Interface.
Imported the module from another source file.
Compiled both translation units separately.
Linked them into a Windows executable.
Ran the program with the correct output.
The experiment was successful from beginning to end.
The most precise declaration is therefore:
C++20 named modules now work end-to-end with GCC 16.1 on Windows 11 for the complete basic compile, import, link, and execution workflow.
This is an encouraging milestone for GCC, MinGW-w64, WinLibs, and C++ developers who prefer an open-source Windows toolchain.
The age of C++ modules on GCC for Windows has not reached complete maturity yet—but it has unquestionably moved from theory into working practice.