Enabling C++20 modules causes non-modular files to be compiled for every library that depends on it
In CMake 3.27.7, given the following CMakeLists.txt file with two empty source files a.cpp
and b.cpp
:
cmake_minimum_required(VERSION 3.27 FATAL_ERROR)
project(asdf LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED On)
set(CMAKE_CXX_EXTENSIONS Off)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "aa1f7df0-828a-4fcd-9afc-2dc80491aca7")
add_library(a STATIC)
target_sources(a PUBLIC
a.cpp
)
add_library(b STATIC)
target_sources(b PUBLIC
b.cpp
)
target_link_libraries(b a)
Then after
touch a.cpp b.cpp
cmake -Wno-dev -B build -G"Ninja" -DCMAKE_CXX_COMPILER="clang++"
cmake --build build -- --verbose
We get
-- The CXX compiler identification is Clang 16.0.6
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.4s)
-- Generating done (0.0s)
-- Build files have been written to: build
[1/10] "/usr/bin/clang-scan-deps" -format=p1689 -- /usr/bin/clang++ -std=c++20 -x c++ b.cpp -c -o CMakeFiles/b.dir/b.cpp.o -MT CMakeFiles/b.dir/b.cpp.o.ddi -MD -MF CMakeFiles/b.dir/b.cpp.o.ddi.d > CMakeFiles/b.dir/b.cpp.o.ddi
[2/10] "/usr/bin/clang-scan-deps" -format=p1689 -- /usr/bin/clang++ -std=c++20 -x c++ a.cpp -c -o CMakeFiles/a.dir/a.cpp.o -MT CMakeFiles/a.dir/a.cpp.o.ddi -MD -MF CMakeFiles/a.dir/a.cpp.o.ddi.d > CMakeFiles/a.dir/a.cpp.o.ddi
[3/10] "/usr/bin/clang-scan-deps" -format=p1689 -- /usr/bin/clang++ -std=c++20 -x c++ a.cpp -c -o CMakeFiles/b.dir/a.cpp.o -MT CMakeFiles/b.dir/a.cpp.o.ddi -MD -MF CMakeFiles/b.dir/a.cpp.o.ddi.d > CMakeFiles/b.dir/a.cpp.o.ddi
[4/10] /usr/bin/cmake -E cmake_ninja_dyndep --tdi=CMakeFiles/a.dir/CXXDependInfo.json --lang=CXX --modmapfmt=clang --dd=CMakeFiles/a.dir/CXX.dd @CMakeFiles/a.dir/CXX.dd.rsp
[5/10] /usr/bin/cmake -E cmake_ninja_dyndep --tdi=CMakeFiles/b.dir/CXXDependInfo.json --lang=CXX --modmapfmt=clang --dd=CMakeFiles/b.dir/CXX.dd @CMakeFiles/b.dir/CXX.dd.rsp
[6/10] /usr/bin/clang++ -std=c++20 -MD -MT CMakeFiles/b.dir/a.cpp.o -MF CMakeFiles/b.dir/a.cpp.o.d @CMakeFiles/b.dir/a.cpp.o.modmap -o CMakeFiles/b.dir/a.cpp.o -c a.cpp
[7/10] /usr/bin/clang++ -std=c++20 -MD -MT CMakeFiles/b.dir/b.cpp.o -MF CMakeFiles/b.dir/b.cpp.o.d @CMakeFiles/b.dir/b.cpp.o.modmap -o CMakeFiles/b.dir/b.cpp.o -c b.cpp
[8/10] /usr/bin/clang++ -std=c++20 -MD -MT CMakeFiles/a.dir/a.cpp.o -MF CMakeFiles/a.dir/a.cpp.o.d @CMakeFiles/a.dir/a.cpp.o.modmap -o CMakeFiles/a.dir/a.cpp.o -c a.cpp
[9/10] : && /usr/bin/cmake -E rm -f liba.a && /usr/bin/llvm-ar qc liba.a CMakeFiles/a.dir/a.cpp.o && /usr/bin/llvm-ranlib liba.a && :
[10/10] : && /usr/bin/cmake -E rm -f libb.a && /usr/bin/llvm-ar qc libb.a CMakeFiles/b.dir/b.cpp.o CMakeFiles/b.dir/a.cpp.o && /usr/bin/llvm-ranlib libb.a && :
Removing setting the CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API
variable removes this behavior.
This can be reproduced in clang main by instead using
cmake_minimum_required(VERSION 3.27 FATAL_ERROR)
project(asdf LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED On)
set(CMAKE_CXX_EXTENSIONS Off)
add_library(a STATIC)
target_sources(a PUBLIC
a.cpp
)
add_library(b STATIC)
target_sources(b PUBLIC
FILE_SET CXX_MODULES
BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}"
FILES
b.cpp
)
target_link_libraries(b a)
With an empty a.cpp
and with b.cpp
being
export module b;
Then after
cmake -B build -G"Ninja" -DCMAKE_CXX_COMPILER="clang++"
cmake --build build -- --verbose
we get
-- The CXX compiler identification is Clang 16.0.6
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.3s)
-- Generating done (0.0s)
-- Build files have been written to: build
[1/7] /usr/bin/clang++ -std=c++20 -MD -MT CMakeFiles/a.dir/a.cpp.o -MF CMakeFiles/a.dir/a.cpp.o.d -o CMakeFiles/a.dir/a.cpp.o -c a.cpp
[2/7] /usr/bin/clang++ -std=c++20 -MD -MT CMakeFiles/b.dir/a.cpp.o -MF CMakeFiles/b.dir/a.cpp.o.d -o CMakeFiles/b.dir/a.cpp.o -c a.cpp
[3/7] "/usr/bin/clang-scan-deps" -format=p1689 -- /usr/bin/clang++ -std=c++20 -x c++ b.cpp -c -o CMakeFiles/b.dir/b.cpp.o -MT CMakeFiles/b.dir/b.cpp.o.ddi -MD -MF CMakeFiles/b.dir/b.cpp.o.ddi.d > CMakeFiles/b.dir/b.cpp.o.ddi
[4/7] cmake -E cmake_ninja_dyndep --tdi=CMakeFiles/b.dir/CXXDependInfo.json --lang=CXX --modmapfmt=clang --dd=CMakeFiles/b.dir/CXX.dd @CMakeFiles/b.dir/CXX.dd.rsp
[5/7] : && cmake -E rm -f liba.a && /usr/bin/llvm-ar qc liba.a CMakeFiles/a.dir/a.cpp.o && /usr/bin/llvm-ranlib liba.a && :
[6/7] /usr/bin/clang++ -std=c++20 -MD -MT CMakeFiles/b.dir/b.cpp.o -MF CMakeFiles/b.dir/b.cpp.o.d @CMakeFiles/b.dir/b.cpp.o.modmap -o CMakeFiles/b.dir/b.cpp.o -c b.cpp
[7/7] : && cmake -E rm -f libb.a && /usr/bin/llvm-ar qc libb.a CMakeFiles/b.dir/a.cpp.o CMakeFiles/b.dir/b.cpp.o && /usr/bin/llvm-ranlib libb.a && :
Edited by Brad King