Ha, despite supporting all the flags for handling modules, and despite advertising being based on Clang 17, the latest AppleClang actually doesnβt parse C++20 modules syntax at all under any conditions. Ie, it doesnβt know about the module keyword no matter what set of flag magic you pass it.
Well so much for that plan.
This is precisely why I had the compiler detection logic in the scope cmake β yes Iβm afraid it feels like a horrible hack, but well things often donβt quite live up to whats on the tin. In the case of scope I only found Clang19+ and g++15 to be viable (msvc is probably fine but scope isnβt ported there yet). Clang 17 at this point is a quite old compiler so Iβm not suprised that it doesnβt work.
From Boost any how to check if import std; is possible:
if(BOOST_USE_MODULES)
add_library(boost_any)
target_sources(
boost_any
PUBLIC
FILE_SET modules_public
TYPE CXX_MODULES
FILES ${CMAKE_CURRENT_LIST_DIR}/modules/boost_any.cppm
)
target_compile_features(boost_any PUBLIC cxx_std_20)
target_compile_definitions(boost_any PUBLIC BOOST_USE_MODULES)
if(${CMAKE_CXX_STANDARD} IN_LIST CMAKE_CXX_COMPILER_IMPORT_STD)
set(CMAKE_CXX_MODULE_STD ON)
target_compile_definitions(boost_any PRIVATE BOOST_ANY_USE_STD_MODULE)
message(STATUS "Using `import std;`")
else()
message(WARNING "`import std;` is not available")
endif()
set(__scope PUBLIC)
else()
set(CMAKE_VERIFY_INTERFACE_HEADER_SETS ON)
add_library(boost_any INTERFACE)
set(__scope INTERFACE)
endif()
# ...
Simple and clear, too if one module depends on other boost modules!
So this is the essence of the check, but where does the cmake_cxx_compiler_import_std come from? And whatβs in it? It looks like itβs the standard version, which isnβt enough to be correctly enable support. Specifically clang-18, g++14 will accept c++23 (version for import std) but donβt correctly support modules, let alone import std. As I said above, I think thereβs currently support in 4-5 compilers clang-19+, g++15+, and msvc (not sure on versions here).
ClausKlein:
BOOST_USE_MODULES
Set this option to yes, and you get a clear cmake-configure error if you use the wrong toolchain, cmake generator, or c++ std version
Ok well obviously we could copy whatever cmake logic theyβre doing there, but it almost seems binary in a way we donβt want perhaps. Specifically, just because I have the ability to enable modules doesnβt mean that I wouldnβt want to have include based options as well.
So let me ask it this way. Would you recommend that we spend time now trying to do something similar to Boost? I can see that weβre going to need similar logic even after cmake provides support for import std in a released version. Specifically, conditionally compiling modules and import std type code only if itβs a supported compiler and cxx version. Thoughts?
No, boost try to work with cmake 3.13 β¦ 3.x, for me 3.30β¦4.2 would be right today.
But beman wants to compile with older gcc and clang compilers, which is also a NoGo for me.
MSVS 2022, clang-20, and gcc-15 is currently my minimum requirement!
1 Like
This comes from cmake:
bash-5.3$ make build/compile_commands.json
cmake -S . -B build -G Ninja --log-level=DEBUG -D CMAKE_BUILD_TYPE=Release \
-D CMAKE_EXPERIMENTAL_CXX_IMPORT_STD="d0edc3af-4c50-42ea-a356-e2862fe7a444" \
-D CMAKE_CXX_STDLIB_MODULES_JSON=/usr/local/Cellar/llvm/21.1.6/lib/c++/libc++.modules.json \
-D CMAKE_CXX_STANDARD=23 -D CMAKE_CXX_EXTENSIONS=ON -D CMAKE_CXX_STANDARD_REQUIRED=ON \
-D BUILD_SHARED_LIBS=ON -D BOOST_INCLUDE_LIBRARIES='any;type_index' \
-D BOOST_USE_MODULES=ON -D CMAKE_CXX_MODULE_STD=ON \
-D CMAKE_INSTALL_MESSAGE=LAZY # XXX -D BOOST_SKIP_INSTALL_RULES=ON # --fresh
# ...
-- Check for working CXX compiler: /usr/local/Cellar/llvm/21.1.6/bin/clang++ - skipped
-- Detecting CXX compile features
CMake Warning (dev) at /usr/local/share/cmake/Modules/Compiler/CMakeCommonCompilerMacros.cmake:248 (cmake_language):
CMake's support for `import std;` in C++23 and newer is experimental. It
is meant only for experimentation and feedback to CMake developers.
Call Stack (most recent call first):
/usr/local/share/cmake/Modules/CMakeDetermineCompilerSupport.cmake:113 (cmake_create_cxx_import_std)
/usr/local/share/cmake/Modules/CMakeTestCXXCompiler.cmake:83 (CMAKE_DETERMINE_COMPILER_SUPPORT)
CMakeLists.txt:20 (project)
This warning is for project developers. Use -Wno-dev to suppress it.
-- Detecting CXX compile features - done
-- CMAKE_CXX_COMPILER_IMPORT_STD=23;26
-- CMAKE_CXX_STANDARD=23
-- CMAKE_CXX_MODULE_STD=ON
-- CMAKE_CXX_SCAN_FOR_MODULES=ON
-- Boost: using system layout: include, bin, lib, lib/cmake, share
-- Boost: using CMake 4.2.0
-- Boost: Release build, shared libraries, MPI OFF, Python OFF, testing OFF
-- Boost: libraries included: any;type_index
-- Scanning dependencies: any;type_index
-- Scanning dependencies: config;throw_exception;container_hash
-- Scanning dependencies: assert;describe;mp11
-- Adding Boost library 'any'
-- Using `import std;`
-- Enabling installation for 'any'
-- boost_install_target: 'boost_any' has INTERFACE_CXX_MODULE_SETS=modules_public
# ...
set_property(TARGET __cmake_cxx23 PROPERTY CXX_SCAN_FOR_MODULES 1)
set_property(TARGET __cmake_cxx23 PROPERTY CXX_MODULE_STD 0)
target_compile_features(__cmake_cxx23 PUBLIC cxx_std_23)
target_sources(__cmake_cxx23
PUBLIC
FILE_SET std TYPE CXX_MODULES
BASE_DIRS "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/MSVC/14.44.35207/bin/../modules"
FILES "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/MSVC/14.44.35207/bin/../modules/std.ixx" "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/MSVC/14.44.35207/bin/../modules/std.compat.ixx")
endif ()
add_library(__CMAKE::CXX23 ALIAS __cmake_cxx23)
endif ()
if (TARGET "__CMAKE::CXX23")
list(APPEND CMAKE_CXX_COMPILER_IMPORT_STD "23")
endif ()
PARENT_SCOPE )
C:/hostedtoolcache/windows/Python/3.13.9/x64/Lib/site-packages/cmake/data/share/cmake-4.2/Modules/CMakeDetermineCompilerSupport.cmake(131): message(CHECK_PASS done )
-- Detecting CXX compile features - done
-- CMAKE_CXX_COMPILER_IMPORT_STD=23
-- CMAKE_CXX_MODULE_STD=ON
-- ALGO_USE_MODULES=ON
-- CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES=
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR - Failed
-- Performing Test COMPILER_HAS_DEPRECATED
-- Performing Test COMPILER_HAS_DEPRECATED - Success
-- Configuring done (6.5s)
CMake Warning:
Manually-specified variables were not used by the project:
BUILD_MCSS_DOCS
cmake-init-modules_DEVELOPER_MODE
-- Generating done (0.0s)
-- Build files have been written to: D:/a/cmake-init-modules/cmake-init-modules/build/dev
Agree β I think 3.28 is the absolute minimum, but happy with 3.30 as well.
I guess this is where I donβt see it as βbinaryβ. For include based things maybe the older compilers are fine, but clearly not for modules.
bingo β this is the set we need to enable, although Iβve also had success with clang-19 Iβm happy to restrict further. modules, unfortunately is still on the bleeding edge.
what is the right cmake export package tree:
bash-5.3$ tree _CPack_Packages/Darwin/TGZ/beman_execution-0.0.1-Darwin/lib/cmake/
_CPack_Packages/Darwin/TGZ/beman_execution-0.0.1-Darwin/lib/cmake/
βββ beman_execution
βββ beman_execution-config-version.cmake
βββ beman_execution-config.cmake
βββ beman_execution-targets-debug.cmake
βββ beman_execution-targets.cmake
βββ cxx-modules
β βββ execution.cppm
βββ cxx-modules-beman_execution-targets-Debug.cmake
βββ cxx-modules-beman_execution-targets.cmake
βββ target-execution-Debug.cmake
3 directories, 8 files
bash-5.3$
or this:
bash-5.3$ tree _CPack_Packages/Darwin/TGZ/beman.scope-0.0.1-Darwin/
_CPack_Packages/Darwin/TGZ/beman.scope-0.0.1-Darwin/
βββ include
β βββ beman
β βββ scope
β βββ beman.scope.cppm
β βββ scope.hpp
βββ lib
βββ cmake
β βββ beman.scope
β βββ beman.scope-config-version.cmake
β βββ beman.scope-config.cmake
β βββ beman.scope-targets-release.cmake
β βββ beman.scope-targets.cmake
β βββ bmi-GNU_Release
β β βββ beman.scope.gcm
β βββ cxx-modules
β βββ cxx-modules-beman.scope-targets-Release.cmake
β βββ cxx-modules-beman.scope-targets.cmake
β βββ target-scope-Release.cmake
βββ libbeman.scope.a
9 directories, 11 files
bash-5.3$
or even like this:
bash-5.3$ tree fmt/
fmt/
βββ bmi-Clang_
β βββ fmt.pcm
βββ bmi-Clang_Relase
β βββ fmt.pcm
βββ cxx-modules-fmtTargets-Relase.cmake
βββ cxx-modules-fmtTargets-noconfig.cmake
βββ cxx-modules-fmtTargets.cmake
βββ fmtConfig.cmake
βββ fmtConfigVersion.cmake
βββ fmtTargets-release.cmake
βββ fmtTargets.cmake
βββ module
β βββ fmt.cppm
β βββ format.cc
β βββ os.cc
βββ target-fmt-Relase.cmake
βββ target-fmt-noconfig.cmake
4 directories, 14 files
bash-5.3$
Good question. Scope is intended to be header only so the libbeman.scope.a shouldnβt be there. The include looks right β although I guess fmt does something different. If Iβm understanding fmt is including the binary from the module which surprises me. idk about the cmake aspect of things in the package. Maybe @vito.gamberini has thoughts.
Please note the Beman Standard CMake recommendations has a gab. It needs to define how to add and install CXX_MODULES.
Boost is working on it i.e. see my boost-make patch:
From fcb4edacb36a4037889cf9ac7a0005eec249e658 Mon Sep 17 00:00:00 2001
From: ClausKlein <claus.klein@arcormail.de>
Date: Thu, 4 Dec 2025 07:09:56 +0100
Subject: [PATCH] Feat: Add support to install FILE_SET too
---
include/BoostInstall.cmake | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/include/BoostInstall.cmake b/include/BoostInstall.cmake
index ca0997c..d7f0149 100644
--- a/include/BoostInstall.cmake
+++ b/include/BoostInstall.cmake
@@ -337,6 +337,16 @@ function(boost_install_target)
string(APPEND CONFIG_INSTALL_DIR "-static")
endif()
+ get_target_property(INTERFACE_CXX_MODULE_SETS ${LIB} INTERFACE_CXX_MODULE_SETS)
+ if(INTERFACE_CXX_MODULE_SETS)
+ boost_message(DEBUG "boost_install_target: '${__TARGET}' has INTERFACE_CXX_MODULE_SETS=${INTERFACE_CXX_MODULE_SETS}")
+ set(__INSTALL_CXX_MODULES FILE_SET ${INTERFACE_CXX_MODULE_SETS} DESTINATION ${CONFIG_INSTALL_DIR})
+ endif()
+ get_target_property(HEADER_SET ${LIB} HEADER_SET)
+ if(HEADER_SET)
+ boost_message(DEBUG "boost_install_target: '${__TARGET}' has HEADER_SET=${HEADER_SET}")
+ endif()
+
install(TARGETS ${LIB} EXPORT ${LIB}-targets
# explicit destination specification required for 3.13, 3.14 no longer needs it
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
@@ -344,8 +354,16 @@ function(boost_install_target)
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
PRIVATE_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
+ # explicit needed if used starting with cmake v3.28
+ FILE_SET CXX_MODULES DESTINATION ${CONFIG_INSTALL_DIR}
+ ${__INSTALL_CXX_MODULES}
+ CXX_MODULES_BMI DESTINATION ${CONFIG_INSTALL_DIR}/bmi-${CMAKE_CXX_COMPILER_ID}_$<CONFIG>
+ # explicit needed if used starting with cmake v3.23
+ FILE_SET HEADERS
+ FILE_SET ${HEADER_SET}
)
+ # TODO(CK): what is this for?
export(TARGETS ${LIB} NAMESPACE Boost:: FILE export/${LIB}-targets.cmake)
if(MSVC)
@@ -362,7 +380,9 @@ function(boost_install_target)
__boost_install_update_sources(${LIB} ${__EXTRA_DIRECTORY} ${__EXTRA_INSTALL_DIRECTORY})
endif()
- install(EXPORT ${LIB}-targets DESTINATION "${CONFIG_INSTALL_DIR}" NAMESPACE Boost:: FILE ${LIB}-targets.cmake)
+ install(EXPORT ${LIB}-targets DESTINATION "${CONFIG_INSTALL_DIR}" NAMESPACE Boost:: FILE ${LIB}-targets.cmake
+ CXX_MODULES_DIRECTORY .
+ )
set_target_properties(${LIB} PROPERTIES _boost_is_installed ON)
I am able to build boost v1.90.0 with c++20 and CXX_MODULES:
develop β feature/bump-to-boost-v1.90.0
opened 07:22PM - 05 Jan 26 UTC
### This version build most boost libs with c++20 and:
```cmake
if(UNIX)
β¦ option(BOOST_USE_MODULES "Do build with CXX_MODULES if possible" ON)
set(CMAKE_CXX_SCAN_FOR_MODULES ON)
set(CMAKE_CXX_MODULE_STD OFF) # TODO(CK): not yet!
endif()
```
β¦ But there is a general problem with header only libs as a CXX_MODULE on Windows:
It seems we have to export the classes on Windows.
see too C++20 Modules, CMake, And Shared Libraries - Crascit
The prof of concept for CXX_MODULES within beman project is ready:
main β ClausKlein:feature/add_cxx_module
opened 05:22PM - 16 Jan 26 UTC
## This is a prototype only to evaluate some concepts how we can work with CXX_M⦠ODULES
I added 3 `cmake modules` which can be included before and after `project()` call.
- include(cmake/prelude.cmake)
- project(...)
- include(cxx-modules-rules)
- if(BEMAN_HAS_MODULES)
### Require C++20 or newer with extensions for modules!
target_compile_definitions(beman.exemplar PUBLIC BEMAN_HAS_MODULES)
target_compile_features(beman.exemplar PUBLIC cxx_std_${CMAKE_CXX_STANDARD})
- endif()
- include(beman-install-library-config) # Local fix only to install modules right!
#### All 3 are prepared to be integrated / merged into `infra/cmake` repo
They add 3 new global options:
- BEMAN_HAS_MODULES:BOOL=ON
- BEMAN_USE_STD_MODULE:BOOL=OFF
- BEMAN_HAS_IMPORT_STD::BOOL=${CMAKE_CXX_SCAN_FOR_MODULES} # only if toolchain supports it.
## Create a self contained `CXX_MODULE`
## Add module usage example too that will be tested after staged install to build directory
8fbd480 Set BEMAN_USE_STD_MODULE=1 on gcc presets
76afe1e Disable BEMAN_USE_STD_MODULE for now
bb7b274 Add option BEMAN_USE_STD_MODULE
a77018c Disable CI tests with clang and libstdc++ for now
eb59178 Disable CI tests with gcc-13 for now
f1e4627 Add generic cmake modules to work with import std;
5afc6ca On UNIX Ninja is required to build CXX_MODULES
f0cb4e7 Require C++20 or newer with extensions for modules
83ddc05 Try to handle CI matrix complexity
fcd47ab Update googletest to v1.17.0 **(reverted again)**
0abf4a9 Modules opt in only on compilers that support it
0768b67 Use ctest --build-and-test to check the installed version
a4f2313 rm CMakeUserPresets.json **(accidentally added)**
18d3e51 Prepare CXX_MODULE usage
- [x] Local fix only to install modules right!
- [ ] Need to define the default / minimum `CMAKE_CXX_STANDARD` value (17 or 20)!
- [x] some historic compiler should not longer used / supported!
- [ ] install test on CI should not longer needed?
- [ ] `Cookiecutter` is a nightmare, _next week I will start to try_
### It depends on following PR:
- https://github.com/bemanproject/infra-workflows/pull/19
- https://github.com/bemanproject/infra/pull/13
- https://github.com/bemanproject/infra/pull/16
- https://github.com/bemanproject/infra/pull/17
fix https://github.com/bemanproject/exemplar/issues/287 too
First read cmake-cxxmodules(7)
Than we have to know and decide which variant of Standard C++ Modules we want:
Daniela's choice for the fmt library was export-extern-c-style
This seems to be useful for existing header-only libraries like asio , fmt , and i.e. beman.scope .
But note the performance tips and other recommendations:
Also note how we may want to Importing modules in other Beman libraries
and last but not least Including headers after import is not well-supported
Related boost cmake
C++20 modules in Boost