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 who 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)