# C++20 modules in beman project libraries

**URL:** <https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279>\
**Category:** Beman Project Development\
**Tags:** cmake, packaging\
**Created:** [December 3, 2024, 8:29am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279 "2024-12-03T08:29:11Z")\
**Posts on this page:** 19\
**Page:** 2

<div class="post-metadata">

**Author:** ![vito.gamberini](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/vito.gamberini/32/261_2.png) [@vito.gamberini](https://discourse.bemanproject.org/u/vito.gamberini)\
**Post date:** [June 18, 2025, 7:12pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/21 "2025-06-18T19:12:56Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Jeff-Garland](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/jeff-garland/32/23_2.png) [@Jeff-Garland](https://discourse.bemanproject.org/u/Jeff-Garland)\
**Post date:** [June 19, 2025, 4:36am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/22 "2025-06-19T04:36:09Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)\
**Post date:** [November 30, 2025, 5:16pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/23 "2025-11-30T17:16:27Z")

</div>

FYI: see [Distributing C++20 modules as source - #4 by ClausKlein - Usage - CMake Discourse](https://discourse.cmake.org/t/distributing-c-20-modules-as-source/13246/4?u=clausklein)

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)\
**Post date:** [December 1, 2025, 5:52pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/24 "2025-12-01T17:52:30Z")

</div>

From Boost any how to check if `import std;` is possible:

```auto
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!

---

<div class="post-metadata">

**Author:** ![Jeff-Garland](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/jeff-garland/32/23_2.png) [@Jeff-Garland](https://discourse.bemanproject.org/u/Jeff-Garland)\
**Post date:** [December 2, 2025, 2:08pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/25 "2025-12-02T14:08:03Z")

</div>

> [@ClausKlein](#):
>
> ```auto
> 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()
> 
> ```

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

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)\
**Post date:** [December 2, 2025, 4:48pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/26 "2025-12-02T16:48:35Z")

</div>

> [@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

---

<div class="post-metadata">

**Author:** ![Jeff-Garland](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/jeff-garland/32/23_2.png) [@Jeff-Garland](https://discourse.bemanproject.org/u/Jeff-Garland)\
**Post date:** [December 3, 2025, 4:29pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/27 "2025-12-03T16:29:51Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)\
**Post date:** [December 3, 2025, 6:02pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/28 "2025-12-03T18:02:14Z")

</div>

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!

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)\
**Post date:** [December 3, 2025, 6:31pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/29 "2025-12-03T18:31:55Z")

</div>

> [@Jeff-Garland](#):
>
> So this is the essence of the check, but where does the cmake\_cxx\_compiler\_import\_std come from? And what’s in it?

This comes from cmake:

```auto
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
# ...

```

```bash
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

```

---

<div class="post-metadata">

**Author:** ![Jeff-Garland](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/jeff-garland/32/23_2.png) [@Jeff-Garland](https://discourse.bemanproject.org/u/Jeff-Garland)\
**Post date:** [December 5, 2025, 2:33am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/30 "2025-12-05T02:33:21Z")

</div>

> [@ClausKlein](#):
>
> No, boost try to work with cmake 3.13 … 3.x, for me 3.30…4.2 would be right today.

Agree – I think 3.28 is the absolute minimum, but happy with 3.30 as well.

> [@ClausKlein](#):
>
> But beman wants to compile with older gcc and clang compilers, which is also a NoGo for me.

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.

> [@ClausKlein](#):
>
> `MSVS 2022`, `clang-20`, and `gcc-15` is currently my minimum requirement!

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.

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)\
**Post date:** [December 7, 2025, 10:38am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/31 "2025-12-07T10:38:23Z")

</div>

I have prepared a prototype to test with `CXX_MODULES` with `import std;`

see [Feature/prepare cxx modules support by ClausKlein · Pull Request #194 · bemanproject/execution · GitHub](https://github.com/bemanproject/execution/pull/194)

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)\
**Post date:** [December 7, 2025, 5:43pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/32 "2025-12-07T17:43:29Z")

</div>

what is the right `cmake export package` tree:

```bash
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
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
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$ 

```

---

<div class="post-metadata">

**Author:** ![Jeff-Garland](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/jeff-garland/32/23_2.png) [@Jeff-Garland](https://discourse.bemanproject.org/u/Jeff-Garland)\
**Post date:** [December 8, 2025, 1:16pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/33 "2025-12-08T13:16:17Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)\
**Post date:** [December 9, 2025, 6:19am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/34 "2025-12-09T06:19:04Z")

</div>

Please note the [Beman Standard CMake recommendations](https://discourse.bemanproject.org/t/new-beman-standard-cmake-recommendations-implicit-defaults-and-no-single-use-variables/429) 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:

```diff
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)
 

```

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)\
**Post date:** [January 9, 2026, 12:06am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/35 "2026-01-09T00:06:09Z")

</div>

I am able to build `boost v1.90.0` with **c++20** and `CXX_MODULES`:

> <https://github.com/ClausKlein/boost-cmake/pull/11>
>
> \### 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()
> \`\`\`

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)\
**Post date:** [January 11, 2026, 9:47am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/36 "2026-01-11T09:47:53Z")

</div>

… But there is a general problem with header only libs as a CXX\_MODULE on Windows:

> **[Linker error with CXX\_MODULES](https://discourse.cmake.org/t/linker-error-with-cxx-modules/15449/4?u=clausklein)**
>
> If I build static libs on Windows, it works:

It seems we have to export the classes on Windows.

see too [C++20 Modules, CMake, And Shared Libraries - Crascit](https://crascit.com/2024/04/04/cxx-modules-cmake-shared-libraries/#h-linker-symbol-visibility)

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)\
**Post date:** [January 11, 2026, 9:56pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/37 "2026-01-11T21:56:47Z")

</div>

@Jeff-Garland I would like if you have a lock at [Add Windows CI build too by ClausKlein · Pull Request #2 · ClausKlein/scope · GitHub](https://github.com/ClausKlein/scope/pull/2)

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)\
**Post date:** [January 22, 2026, 8:49pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/38 "2026-01-22T20:49:25Z")

</div>

The prof of concept for CXX\_MODULES within beman project is ready:

> <https://github.com/bemanproject/exemplar/pull/286>
>
> \## 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

---

<div class="post-metadata">

**Author:** ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)\
**Post date:** [March 3, 2026, 9:34am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/39 "2026-03-03T09:34:16Z")

</div>

First read [cmake-cxxmodules(7)](https://cmake.org/cmake/help/latest/manual/cmake-cxxmodules.7.html)

Than we have to know and decide which variant of **Standard C++ Modules** we want:

- [Transitioning to modules - abi-non-breaking-styles](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#https://clang.llvm.org/docs/StandardCPlusPlusModules.html#abi-non-breaking-styles)
- [Transitioning to modules - abi-breaking-style](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#abi-breaking-style)

`Daniela's` choice for the `fmt` library was [export-extern-c-style](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#export-extern-c-style)

This seems to be useful for existing header-only libraries like [asio](https://github.com/ClausKlein/asio/blob/feature/module/module/asio.ixx), [fmt](https://github.com/ClausKlein/fmt-module/blob/develop/module/fmt.cppm), and i.e. [beman.scope](https://github.com/bemanproject/scope/pull/53).

But note the performance tips and other recommendations:

- [The ABI of your library](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#the-abi-of-your-library)
- [Less duplicated generated code](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#less-duplicated-generated-code)
- [Providing a header to skip parsing redundant headers](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#providing-a-header-to-skip-parsing-redundant-headers)

Also note how we may want to [Importing modules](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#importing-modules) in other Beman libraries

and last but not least [Including headers after import is not well-supported](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#id61)

[Related boost cmake](https://github.com/boostorg/cmake/pull/105)  
[C++20 modules in Boost](https://github.com/anarthal/boost-cmake/blob/e29bc2a5bd3493d353bf597610d4b32b5a11d0dc/modules.md#c20-modules-in-boost)

[Previous page](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279.md?page=1)
