The gcc used for this article is 16.0.0, built from gcc git source code. (Apr 24, 2025).
Alias gpp:
alias gpp="path/to/the/g++ -fmodules-ts -std=c++26"
import declaration: import module units, module partitions, header units.
Pre-compile gcc std.gcm :
> gpp -fmodule-only -fsearch-include-path bits/std.cc -c > ls gcm.cache/ std.gcm
It will generate gcm.cache/std.gcm at current working directory.
Pre-compiling std.gcm is a little slow, after compiling it, the compiling of using of "import std;" is very fast.
hello.cpp :
import std; int main() { std::cout << "Hello, c++ modules!" << std::endl; }
Compile program hello.cpp:
(very fast)
After the cache gcm.cache/std.gcm
is generated,
the compiling is super fast.
> gpp hello.cpp -o hello > ./hello Hello, c++ modules!
The cache ./gcm.cache/std.gcm will be reused for the rest parts of this article conveniently.
export declaration:
c++ module declaration starts with a keyword export or module.
E.X:
export module module-name;
Declares a primary module interface unit and export, its name is module-name .
export namespace namespace-name
{
...
export a namespace
Make a c++ module, source code: my_class.cppm ->
(Note that gcc supports both .cppm and .cpp as the c++ module source code file name extension.)
my_class.cppm :
export module my_module; import std; export namespace my_space { class my_class { public: void greeting() const { std::cout << "Cheers, c++!" << std::endl; } }; }
Use the module, source code: main.cpp
main.cpp :
import my_module; int main() { my_space::my_class my_object; my_object.greeting(); }
Compile them :
> gpp my_class.cppm main.cpp -o main > ./main Cheers, c++!
The compiling order is compiling my_class.cppm first, then main.cpp
Just compile the module source c++ file to shared library.
my_cpp.cppm :
export module my_module; export import std; export namespace my_space { class my_class { private: int __x; public: my_class(int x__): __x{x__} {} public: int get() const {return __x;} }; }
main.cpp :
import my_module; int main() { my_space::my_class object{234}; std::cout << "get: " << object.get() << std::endl; }
Compile :
> gpp my_cpp.cppm -c -fPIC -shared -o libmy_cpp.so > gpp main.cpp -L./ -lmy_cpp -o main > ./main get: 234
A module partition can be imported by module units of the same named module.
In this example, :my_partition can be imported by my_module, it can not be imported by other module.
my_cpp_part.cppm :
export module my_module:my_partition; export namespace my_space { class my_class_2 { public: int get() const { return -112233; } }; }
my_cpp.cppm :
export module my_module; export import :my_partition; export namespace my_space { class my_class { public: int get() const { return 3333; } }; }
main.cpp :
import my_module; import std; int main() { my_space::my_class obj1; std::cout << "v: " << obj1.get() << std::endl; my_space::my_class_2 obj2; std::cout << "v: " << obj2.get() << std::endl; }
Compile :
(compile order is important, my_cpp.cppm depends on my_cpp_part.cppm)
> gpp my_cpp_part.cppm my_cpp.cppm -c -fPIC > gpp *.o -shared -o libmy_cpp.so > gpp main.cpp -L./ -lmy_cpp -o main
> ./main v: 3333 v: -112233
First, precompile :
> gpp -xc++-system-header boost/parser/parser.hpp > gpp -xc++-system-header iostream
Then, use :
(program.cpp :)
import <boost/parser/parser.hpp>; import <iostream>; int main() { std::cout << "Hello, c++!" << std::endl; }
Compile :
> gpp program.cpp -o program
A module unit contains declaration :
export module my_module;
A module implementation unit is the implementation of module unit, which does not have export keyword :
module my_module;
my_cpp.cppm : (module unit)
export module my_module; export namespace my_space { class my_class { public: void greeting() const; void cheers() const; int get() const; virtual ~my_class(); }; }
my_cpp_src.cppm : (module implementation unit)
module my_module; import std; my_space::my_class::~my_class() { std::cout << "Bye, c++!" << std::endl; } void my_space::my_class::greeting() const { std::cout << "Greeting, c++!" << std::endl; } void my_space::my_class::cheers() const { std::cout << "Cheers, c++!" << std::endl; } int my_space::my_class::get() const { return 12345; }
main.cpp :
import my_module; import std; int main() { my_space::my_class my_object; my_object.greeting(); my_object.cheers(); std::cout << "get: " << my_object.get() << std::endl; }
Compile :
> gpp my_cpp.cppm my_cpp_src.cppm -c -fPIC > gpp my_cpp.o my_cpp_src.o -shared -o libmy_cpp.so > gpp main.cpp -L./ -lmy_cpp -o main
> ./main Greeting, c++! Cheers, c++! get: 12345 Bye, c++!
Declare Primary Module Unit
(Name is A)
export module A;
(Name is A.B)
export module A.B;
Declare Module Implementation Unit
module A;
module A.B;
constexpr and template declared api can not be splitted into two declaration and definition module files.
c++ modules gcc can be used in b2 build by flags settings trick.
First, generate gcm.cache/std.gcm cache in current working directory like talked in the beginning of this article, I am a little lazy of how to make it by a b2 jamfile trick.
The same c++ source files of previous section of this article will be used for this project:
(Split Definitions for Shared Library)
(Because b2 build does not support .cppm file name extension by default (which needs a simple patch), we have to rename them):
The file jamroot in current working directory:
jamroot :
project : requirements <cxxflags>"-fmodules-ts" : default-build <cxxstd>26 ; obj obj-my_cpp : my_cpp.cpp ; obj obj-my_cpp_src : my_cpp_src.cpp : <dependency>obj-my_cpp ; lib my_cpp : obj-my_cpp obj-my_cpp_src ; exe main : main.cpp : <library>my_cpp <dependency>my_cpp ;
(Requires toolset gcc version >= 15.2. I use 16.0)
Build:
> b2 -q -j7
Make sure the toolset used for this project is gcc. Visual c++ and clang++ has different compiler flags.
Run program:
> ls ./bin/gcc-latest/debug/cxxstd-26-iso/ libmy_cpp.so main main.o my_cpp.o my_cpp_src.o > > > > ./bin/gcc-latest/debug/cxxstd-26-iso/main Greeting, c++! Cheers, c++! get: 12345 Bye, c++!
...
...
...
...
...
A module unit is a translation unit which has a module declaration.
A module partition unit is a module unit which is included by a module unit and starts with a colon : , and is placed after the module name.
For example,
export module A:B;
export module A;
Module name is the name of the module unit, which consists of one or more identifiers separated by dots. Note that module partition unit is also module unit.
For example,
// Module name is A export module A;
// Module name is A.B.C export module A.B.C;
Written on Apr 24, 2025
Latest update on May 14, 2025
c++ std::exception:
std::cout.write(err.data(), err.size());
std::cout << std::endl;
caught:
=================================== # The c++ programming language. # # # # Join c++ # # Deck # ===================================