| icmodmap(1) | initializes C++ projects using modules | icmodmap(1) |
icmodmap - Initializes the maintenance of C++ projects using modules
icmodmap [Options] [arg]
Although modules have already been available for quite some time, the Gnu g++ compiler still shows a number of bugs related to C++ modules (cf. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103524). It’s possible that you stumble across some of these (or new) bugs when using modules. The number of reported bugs is gradually reducing, and the current state of affairs at least allows you to gain some experience in using modules.
Modules cannot mutually import each other. Consequently there’s always a linear, non-circular module hierarchy, which should be acknowledged when compiling files defining and using modules. Icmodmap determines this order and prepares the construction of programs using modules. Once icmodmap has done its job your favorite build-utility can be used as before. Just make sure that compilation uses the same C++ standard as used by icmodmap, and provide the -fmodules-ts compiler option when compiling source files.
Icmodmap assumes that modules are defined in separate sub-directories. For your own documentation it’s advised that filenames containing module (and partition) interface units start with mod (e.g., modsupport.cc. If a program defines two modules First and Second (e.g., in sub-directories first and second and second/modsecond.cc imports module First then first/modfirst.cc must be compiled before compiling second/modsecond.cc. This requirement is handled by icmodmap. Once the source files containing module interface units have been compiled the program’s remaining source files can be compiled as usual.
By default icmodmap expect projects using modules to be organized this way:
module
module/part1
module/part2
Icmodmap inspects each directory specified in the CLASSES file, including the top-level directory. It recognizes interface units and source files implementing module components. It ignores comment, but the individual parts of specifications can be separated by spaces or tabs but not by comment. E.g., export /* */ module Support; is not recognized.
When compiling source files containing interface units the compiler is called using at least the following options (see also the options --colors, --extension and --subdir in section Options):
If the environment variable ttICMAKE_CPP) standard is not defined then the C++ standard used by default by the compiler is used. To define it use e.g., export ICMAKE_CPPSTD=--std=c++26.
/bin/g++ ${ICMAKE_CPPSTD} -fmodules-ts -c -Wall
The program’s argument can be omitted or it can be specified in various ways:
Icmodmap supports the following options:
indicating that modules Square and DepSquare are defined by the current project, and the module DepSquare depends on the module Square.
Dependencies:
LOCAL module Square
LOCAL module DepSquare
imports LOCAL module Square
In this example module RectAngle is a module made available by some other project. The local modue DepSquare, as before, depends on Square. In this example the RectAngle.gcm file must be available in the project’s gcm.cache directory before module Square can be compiled (it’s normally made available via a soft-link to the actual file);
Dependencies:
LOCAL module Square
imports EXTERN module RectAngle
LOCAL module DepSquare
imports LOCAL module Square
EXTERN module RectAngle
The following program defines a module Square in its sub-directory square, containing this modsquare.cc file:
export module Square;
export
{
double square(double value);
class Square
{
double d_amount;
public:
Square(double amount = 0); // initialize
void amount(double value); // change d_amount
double amount() const; // return d_amount
double lastSquared() const; // returns g_squared
double square() const; // returns sqr(d_amount)
};
}
double g_squared;
The main function imports the Square module and uses its facilities. It also imports the iostream module-compiled system header. That header is not inspected by icmodmap, and must be available before the main.cc file can be compiled. Here is the main.cc source file:
import Square;
import <iostream>;
int main(int argc, char **argv)
{
std::cout << "the square of " << argc << " is "
<< square(argc) << ’\n’;
Square obj{12};
std::cout << "the square of 12 is " << obj.square() << "\n"
"the last computed square is " <<
obj.lastSquared() << ’\n’;
}
Executing icmodmap -d shows Square as a local module:
Dependencies:
LOCAL module Square
Executing icmodmap -V performs and shows the compilation of square/module.cc as well as the names of the source files implementing (declaring) its components or merely importing the module:
Defining a soft-link from gcm.cache/usr -> /usr
Inspecting square/
scanning square1.cc
declares module Square
scanning amount1.cc
declares module Square
scanning square.cc
declares module Square
scanning square2.cc
declares module Square
scanning modsquare.cc
defines module Square
scanning amount2.cc
declares module Square
scanning lastsquared.cc
declares module Square
Inspecting ./
scanning main.cc
imports module Square
Compiling...
in square: /bin/g++ --std=c++26 -fdiagnostics-color=never -c
-fmodules-ts -Wall -o ../tmp/o/1modsquare.o modsquare.cc
None reported.
This is free software, distributed under the terms of the GNU General Public License (GPL).
Frank B. Brokken (f.b.brokken@rug.nl).
| 1992-2025 | icmake.13.02.00 |