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> 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" $
