Hello community,

I tried to build code of c++20 modules with recursive GNU Makefile.
My example code has a foo library and the main client code.
The CMake supports building code of c++20 modules with Ninja,
but not with GNU Makefile.

$ cmake -B build -S src # -G Ninja
CMake Error in foo/CMakeLists.txt:
The target named "foo" has C++ sources that may use modules, but modules
are not supported by this generator: Unix Makefiles

Modules are supported only by Ninja, Ninja Multi-Config, and Visual Studio
generators for VS 17.4 and newer. See the cmake-cxxmodules(7) manual for
details. Use the CMAKE_CXX_SCAN_FOR_MODULES variable to enable or disable
scanning.
$

I use this to tell main where the gcm cache of foo is:
CXXFLAGS += '-fmodule-mapper=|@g++-mapper-server -r../foo/gcm.cache'

I got a minor issue. It tries to build the client main every time,
even if both main and foo source files are up to date.

The rebuild is also triggered for the syntax with a plain text file:
CXXFLAGS += '-fmodule-mapper=../foo/module.map'

# foo/module.map
foo gcm.cache/foo.gcm

How can i fix this?


Thanks


$ make
make[1]: Entering directory '/home/ljh/Documents/hello_cpp/src/foo'
g++ -g -fPIC -std=c++23 -fmodules -MMD -MP -c -o foo.o foo.cppm
g++ -g -fPIC -std=c++23 -fmodules -MMD -MP -c -o bar.o bar.cpp
g++ -shared foo.o bar.o -o foo
cp foo libfoo.so
make[1]: Leaving directory '/home/ljh/Documents/hello_cpp/src/foo'
make[1]: Entering directory '/home/ljh/Documents/hello_cpp/src/main'
g++ -g -std=c++23 -fmodules '-fmodule-mapper=|@g++-mapper-server 
-r../foo/gcm.cache' -MMD -MP -I../foo -c -o main.o main.cpp
g++ -L../foo main.o -lfoo -o main
make[1]: Leaving directory '/home/ljh/Documents/hello_cpp/src/main'
$

$ make
make[1]: Entering directory '/home/ljh/Documents/hello_cpp/src/foo'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/home/ljh/Documents/hello_cpp/src/foo'
make[1]: Entering directory '/home/ljh/Documents/hello_cpp/src/main'
g++ -g -std=c++23 -fmodules '-fmodule-mapper=|@g++-mapper-server 
-r../foo/gcm.cache' -MMD -MP -I../foo -c -o main.o main.cpp
g++ -L../foo main.o -lfoo -o main
make[1]: Leaving directory '/home/ljh/Documents/hello_cpp/src/main'
$

$ LD_LIBRARY_PATH=foo ./main/main
foo
bar
main
bar
$

$ LD_LIBRARY_PATH=foo ldd ./main/main
linux-vdso.so.1 (0x00007329f7ea0000)
libfoo.so => foo/libfoo.so (0x00007329f7e8e000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 
(0x00007329f7a00000)
libc.so.6 => /usr/lib/x86_64-linux-gnu/libc.so.6 (0x00007329f7600000)
libm.so.6 => /usr/lib/x86_64-linux-gnu/libm.so.6 (0x00007329f7d58000)
/lib64/ld-linux-x86-64.so.2 (0x00007329f7ea2000)
libgcc_s.so.1 => /usr/lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007329f7d2a000)
$

$ pwd
/home/ljh/Documents/hello_cpp/src
$

$ find . | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
.
|____notes.txt
|____CMakeLists.txt
|____Makefile
|____foo
| |____CMakeLists.txt
| |____foo.cppm
| |____Makefile
| |____bar.h
| |____bar.cpp
|____main
| |____main.cpp
| |____CMakeLists.txt
| |____Makefile
$

$ cat Makefile
subdirs = main foo
all: $(subdirs)
main: foo
.PHONY: all clean install $(subdirs)
.ONESHELL:
$(subdirs): ; @$(MAKE) -C $@

clean:
 @for dir in $(subdirs)
 do
 $(MAKE) -C $$dir $@
 done
$

$ cat foo/Makefile
# build dynamic library with -fPIC -shared
CXXFLAGS = -g -fPIC -std=c++23 -fmodules # -O3 # CXXFLAGS for .cpp
CPPFLAGS = -MMD -MP # -I../foo -DNDEBUG
LDFLAGS = -shared # -L../foo -static
LDLIBS = # -lfoo
CC = $(CXX) # link with CXX for .cpp

CPP_OBJECTS = $(patsubst %.cpp,%.o,$(wildcard *.cpp))
CPPM_OBJECTS = $(patsubst %.cppm,%.o,$(wildcard *.cppm))

all: foo libfoo.so
libfoo.so: foo; cp foo libfoo.so

# target name is basename of one of the source files
foo: $(CPP_OBJECTS) $(CPPM_OBJECTS) # .cpp
-include *.d
clean: ; rm -fr *.o *.d foo libfoo.so gcm.cache
.PHONY: clean

%.o :%.cppm ; $(COMPILE.cpp) $(OUTPUT_OPTION) $<
$
$ cat main/Makefile
# build dynamic library with -fPIC -shared
CXXFLAGS = -g -std=c++23 -fmodules # -O3 -fPIC # CXXFLAGS for .cpp
CPPFLAGS = -MMD -MP -I../foo # -DNDEBUG
LDFLAGS = -L../foo # -shared -static
LDLIBS = -lfoo
CC = $(CXX) # link with CXX for .cpp

CPP_OBJECTS = $(patsubst %.cpp,%.o,$(wildcard *.cpp))

# target name is basename of one of the source files
main: $(CPP_OBJECTS) # .cpp
-include *.d
clean: ; rm -fr *.o *.d main
.PHONY: clean

CXXFLAGS += '-fmodule-mapper=|@g++-mapper-server -r../foo/gcm.cache'

%.c++-module: ;
$

$ g++ --version
g++ (Ubuntu 15.2.0-16ubuntu1) 15.2.0
Copyright (C) 2025 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$

$ make --version
GNU Make 4.4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
<https://gnu.org/licenses/gpl.html&gt;
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=26.04
DISTRIB_CODENAME=resolute
DISTRIB_DESCRIPTION="Ubuntu 26.04 LTS"
$

Reply via email to