PrevUpHome

day-25: Special: c++ modules gcc


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"

First: import std;

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.

Next: Make a c++ module

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

Next: Modules Shared Library

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

Next: Module Partition

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

Next: Header Unit

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

Next: Split Definitions for Shared Library (Module Unit and Module Implementation Unit)

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++!

About Module Declaration

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

constexpr and template declared api can not be splitted into two declaration and definition module files.

Next: c++ Modules in B2 Build System

c++ modules gcc can be used in b2 build by flags settings trick.

First: About import std;

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.

c++ source files

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):

File: jamroot

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 ;

Build the project

(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++!

Last: Glossary

Module Declaration

...

Module definition

...

Export Declaration

...

Import Declaration

...

Translation Unit

...

Module Unit

A module unit is a translation unit which has a module declaration.

Module Partition Unit

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

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;

Date

Written on Apr 24, 2025

Latest update on May 14, 2025

Back to index

Index

cpp/c++

c++ std::exception:

std::cout.write(err.data(), err.size());

std::cout << std::endl;

caught:

  ===================================
  #  The c++ programming language.  #
  #                                 #
  #  Join c++                       #
  #  Deck                           #
  ===================================

Home: cppfx.xyz


PrevUpHome