Having difficulty compiling with import std; support; cmake can't build std.cppm

Hi there,

I’m looking for some help with a cmake-directed build of a C++ modules project containing import std;

I’ve followed along with:

https://www.kitware.com/import-std-in-cmake-3-30/

The sample provided there compiles just fine with my clang-20 compiler on Ubuntu Linux. I’m using cmake 4.2.3 (compiled from source).

The problem comes when I run cmake on my own project. I get these errors as cmake attempts to build the std.cppm.o and std.compat.cppm.o object files:

[21:21:56 bclang] ninja range1
[5/16] Scanning /usr/lib/llvm-20/share/libc++/v1/std.compat.cppm for CXX dependencies
FAILED: CMakeFiles/__cmake_cxx23.dir/usr/lib/llvm-20/share/libc++/v1/std.compat.cppm.o.ddi 
"/usr/bin/clang-scan-deps-20" -format=p1689 -- /usr/bin/clang++-20  -I/usr/lib/llvm-20/bin/../lib/../share/libc++/v1 -g -Wall -Wextra -Wpedantic -pedantic-errors -Werror -Wfatal-errors -Wno-psabi -O3 -fconstexpr-steps=500000000 -DMATHS_HAVE_STD_FORMAT  -std=gnu++23 -Wno-reserved-module-identifier -x c++ /usr/lib/llvm-20/share/libc++/v1/std.compat.cppm -c -o CMakeFiles/__cmake_cxx23.dir/usr/lib/llvm-20/share/libc++/v1/std.compat.cppm.o -resource-dir "/usr/lib/llvm-20/lib/clang/20" -MT CMakeFiles/__cmake_cxx23.dir/usr/lib/llvm-20/share/libc++/v1/std.compat.cppm.o.ddi -MD -MF CMakeFiles/__cmake_cxx23.dir/usr/lib/llvm-20/share/libc++/v1/std.compat.cppm.o.ddi.d > CMakeFiles/__cmake_cxx23.dir/usr/lib/llvm-20/share/libc++/v1/std.compat.cppm.o.ddi.tmp && mv CMakeFiles/__cmake_cxx23.dir/usr/lib/llvm-20/share/libc++/v1/std.compat.cppm.o.ddi.tmp CMakeFiles/__cmake_cxx23.dir/usr/lib/llvm-20/share/libc++/v1/std.compat.cppm.o.ddi
Error while scanning dependencies for /usr/lib/llvm-20/share/libc++/v1/std.compat.cppm:
/usr/lib/llvm-20/share/libc++/v1/std.compat.cppm:16:10: fatal error: '__config' file not found
[6/16] Scanning /usr/lib/llvm-20/share/libc++/v1/std.cppm for CXX dependencies
FAILED: CMakeFiles/__cmake_cxx23.dir/usr/lib/llvm-20/share/libc++/v1/std.cppm.o.ddi 
"/usr/bin/clang-scan-deps-20" -format=p1689 -- /usr/bin/clang++-20  -I/usr/lib/llvm-20/bin/../lib/../share/libc++/v1 -g -Wall -Wextra -Wpedantic -pedantic-errors -Werror -Wfatal-errors -Wno-psabi -O3 -fconstexpr-steps=500000000 -DMATHS_HAVE_STD_FORMAT  -std=gnu++23 -Wno-reserved-module-identifier -x c++ /usr/lib/llvm-20/share/libc++/v1/std.cppm -c -o CMakeFiles/__cmake_cxx23.dir/usr/lib/llvm-20/share/libc++/v1/std.cppm.o -resource-dir "/usr/lib/llvm-20/lib/clang/20" -MT CMakeFiles/__cmake_cxx23.dir/usr/lib/llvm-20/share/libc++/v1/std.cppm.o.ddi -MD -MF CMakeFiles/__cmake_cxx23.dir/usr/lib/llvm-20/share/libc++/v1/std.cppm.o.ddi.d > CMakeFiles/__cmake_cxx23.dir/usr/lib/llvm-20/share/libc++/v1/std.cppm.o.ddi.tmp && mv CMakeFiles/__cmake_cxx23.dir/usr/lib/llvm-20/share/libc++/v1/std.cppm.o.ddi.tmp CMakeFiles/__cmake_cxx23.dir/usr/lib/llvm-20/share/libc++/v1/std.cppm.o.ddi
Error while scanning dependencies for /usr/lib/llvm-20/share/libc++/v1/std.cppm:
/usr/lib/llvm-20/share/libc++/v1/std.cppm:16:10: fatal error: '__config' file not found
ninja: build stopped: subcommand failed.

The __config file is found in /usr/lib/llvm-20/include/c++/v1/ but for some reason, that directory is not incorporated in the commands.

Can anyone suggest the best/right way to encode that directory in the base CMakeLists.txt? I tried adding a simple include_directories line, but this doesn’t seem to get passed to clang-scan-deps-20

My code can be found at

Steps to reproduce this on Debian/Ubuntu would be:

compile/install cmake 4.2.3
Install clang and libc++ (and ninja-build):
sudo apt install clang-20 clang-tools-20 libc++-20-dev ninja-build

$ git clone https://github.com/sebsjames/maths.git
$ git checkout dev/modules_import_std # Important to get on the right branch!
$ cd maths
$ mkdir build
$ cd build
$ CC=clang-20 CXX=clang++-20 cmake .. -GNinja -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_EXE_LINKER_FLAGS="-stdlib=libc++ -lc++abi"
$ ninja range1

Thanks for reading!
Seb James

On OSX I can build it with clang-22 and this GNUmakefile:

# Standard stuff

.SUFFIXES:

MAKEFLAGS+= --no-builtin-rules  # Disable the built-in implicit rules.
# MAKEFLAGS+= --warn-undefined-variables  # Warn when an undefined variable is referenced.

export hostSystemName=$(shell uname)

ifeq (${hostSystemName},Darwin)
  export LLVM_PREFIX:=$(shell brew --prefix llvm)
  export LLVM_DIR:=$(shell realpath ${LLVM_PREFIX})
  export PATH:=${LLVM_DIR}/bin:${PATH}
  # XXX CMAKE=cmake
  CMAKE?=/usr/local/bin/cmake

  export CMAKE_CXX_STDLIB_MODULES_JSON:=${LLVM_DIR}/lib/c++/libc++.modules.json
  export CXXFLAGS:=-stdlib=libc++
  export LDFLAGS:=-L$(LLVM_DIR)/lib/c++ -lc++abi # XXX -lc++
  export CXX:=clang++
  export GCOV:="llvm-cov gcov"

  ### TODO: to test g++-15:
  export GCC_PREFIX:=$(shell brew --prefix gcc)
  export GCC_DIR:=$(shell realpath ${GCC_PREFIX})

  #NO! export CMAKE_CXX_STDLIB_MODULES_JSON:=${GCC_DIR}/lib/gcc/current/libstdc++.modules.json
  #NO! export CXXFLAGS:=-stdlib=libstdc++
  # export CXX:=g++-15
  # export GCOV:="gcov"
else ifeq (${hostSystemName},Linux)
  export LLVM_DIR:=/usr/lib/llvm-20
  export PATH:=${LLVM_DIR}/bin:${PATH}
  export CXX:=clang++-20
  CMAKE=cmake
endif

.PHONY: all install coverage gclean distclean format demo

all: build/compile_commands.json
	ln -sf $< .
	ninja -C build

build/compile_commands.json: CMakeLists.txt GNUmakefile
	${CMAKE} --version
	${CMAKE} -S . -B build -G Ninja \
	 -D CMAKE_BUILD_TYPE=Release \
	 -D CMAKE_CXX_STANDARD=23 -D CMAKE_CXX_EXTENSIONS=YES -D CMAKE_CXX_STANDARD_REQUIRED=YES \
	 -D CMAKE_INSTALL_MESSAGE=LAZY \
	 -D CMAKE_CXX_STDLIB_MODULES_JSON=${CMAKE_CXX_STDLIB_MODULES_JSON} \
	 -D CMAKE_SKIP_INSTALL_RULES=NO \
	 --log-level=VERBOSE --fresh \
	 # -D CMAKE_CXX_FLAGS='-fno-inline --coverage' \
	 # --trace-expand --trace-source=use-fetch-content.cmake \
	 # --debug-find-pkg=GTest

install: build/cmake_install.cmake
	${CMAKE} --install build


# Anything we don't know how to build will use this rule.
% ::
	ninja -C build $(@)

I only changed this:

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b156e06..bd461fa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
 # 3.28.5 for basic C++20 modules; 3.30 to give access to import std;
-cmake_minimum_required(VERSION 3.30)
+cmake_minimum_required(VERSION 3.30...4.3)
 
 # This specific value changes as experimental support evolves. See
 # `Help/dev/experimental.rst` in the CMake source corresponding to
@@ -7,14 +7,14 @@ cmake_minimum_required(VERSION 3.30)
 # This value is ok for cmake versions from 3.31.11 up to 4.2.3 (Seb)
 set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444")
 
-project(maths LANGUAGES CXX)
+project(maths LANGUAGES CXX C)
 
 message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}")
 message(STATUS "  (This can be changed with `cmake -DCMAKE_INSTALL_PREFIX=/some/place`")
 
 set(CMAKE_CXX_STANDARD 23)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
-set(CMAKE_CXX_EXTENSIONS OFF)
+set(CMAKE_CXX_EXTENSIONS ON)
 # Tell CMake that we explicitly want `import std`. This will initialize the
 # property on all targets declared after this to 1
 set(CMAKE_CXX_MODULE_STD 1)
diff --git a/sm/histo b/sm/histo
index c0bfce8..6dfc805 100644
--- a/sm/histo
+++ b/sm/histo
@@ -8,6 +8,7 @@
  */
 module;
 
+#include <stdexcept>
 #include <type_traits>
 #include <memory>
 #include <limits>

Thanks Claus, I’ll go through that tomorrow and see what I can learn from it.

FYI:

98% tests passed, 2 tests failed out of 128

Label Time Summary:
build-failure    = 253.57 sec*proc (22 tests)

Total Test time (real) = 285.49 sec

The following tests FAILED:
	 86 - geometry_xyz_to_latlong (Failed)
	102 - polysolve_1 (Failed)
Errors while running CTest
Output from these tests are in: /Users/clausklein/Workspace/cpp/cxx23/maths/build/Testing/Temporary/LastTest.log
Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.
FAILED: [code=8] CMakeFiles/test.util 
cd /Users/clausklein/Workspace/cpp/cxx23/maths/build && /usr/local/bin/ctest
ninja: build stopped: subcommand failed.
make: *** [test] Error 8
bash-5.3$ 

This is needed for clang !!! (not for gcc)

1 Like