# 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:** 20\
**Page:** 1

<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, 2024, 8:29am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/1 "2024-12-03T08:29:11Z")

</div>

Do you know this paper: [C++20 modules and Boost: deep dive](https://anarthal.github.io/cppblog/modules2)?

I have a PR which show the current state and problems:

> <https://github.com/ClausKlein/asio/pull/4>
>
> \- \[x\] Add and use \`cmake workflow presets\` file
> \- \[x\] Use \`CMAKE\_VERIFY\_INTERFA…CE\_HEADER\_SETS\`
> \- \[x\] Use \`ccache\` if available
> \- \[x\] use debug postfix
> \- \[x\] install libray to lib
> \- \[x\] install less verbose
> \- \[x\] test installed cmake config package
> \- \[x\] install the c++20 \`CXX\_MODULE\`
> \- \[x\] compiles with Apple clang version 16.0.0 (std=c++2b, but no \`CXX\_MODULE\` support yet!)
> \- \[x\] compiles with clang version 19.1.4 (std=c++2b)
> \- \[x\] \*\*MSVC\*\* works on \*\*CI\*\* (std=c++20, but fails to compile the \`CXX\_MODULE\`)
> \- \[x\] Activate the \`find installed CXX\_MODULE\` test on \*\*CI\*\*!
> \- \[\] g++-14 fails on \`macOS\` with both versions?
> 
> see too https://anarthal.github.io/cppblog/modules2
> 
> and \[fmt-module\](https://github.com/ClausKlein/fmt-module)

---

<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, 2024, 12:25am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/2 "2024-12-05T00:25:14Z")

</div>

Thanks Claus –

Thanks for the link. This is a good update on the state of things. I’d note that on the gcc side, a couple weeks ago they merged support for `import std` and compat into main. So it seems like we’re getting closer to real modules support.

Also, be aware that @dietmarkuehl while in Poland was hacking his cmake for beman execution. Should we try with additional repos? Not sure where we go next with this.

---

<div class="post-metadata">

**Author:** ![dietmarkuehl](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/dietmarkuehl/32/60_2.png) [@dietmarkuehl](https://discourse.bemanproject.org/u/dietmarkuehl)\
**Post date:** [December 5, 2024, 12:58am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/3 "2024-12-05T00:58:14Z")

</div>

I think Claus’s efforts on modules were triggered somewhat by me creating a [PR](https://github.com/bemanproject/execution26/pull/91) with a modularized version of [`beman::execution26`](https://github.com/bemanproject/execution26). Based on the comments and linked articles it will need some work to make the compilers happy.

---

<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, 2024, 1:06pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/4 "2024-12-05T13:06:29Z")

</div>

That’s fair. It would be interesting to give gcc15 (aka the current trunk) a whirl because as was reported in Poland `import std` recently got merged.

---

<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 10, 2024, 6:52am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/5 "2024-12-10T06:52:52Z")

</div>

Some [Professional CMake](https://crascit.com/professional-cmake/) recommendations:

### from 17.4. Recommended Practices

```auto
Projects should avoid setting compiler and linker flags directly to control the
language standard used. The required flags vary from compiler to compiler, so it
is more robust, more maintainable, and more convenient to use the features that
CMake provides and allow it to populate the flags appropriately. The
CMakeLists.txt file will also more clearly express the intent, since human-
readable variables and properties are used instead of often cryptic raw compiler
and linker flags.

The simplest method for controlling language standard requirements is to use the
CMAKE_<LANG>_STANDARD, CMAKE_<LANG>_STANDARD_REQUIRED, and
CMAKE_<LANG>_EXTENSIONS variables. These can be used to set the language
standard behavior for the entire project, ensuring consistent usage across all
targets. These variables should ideally be set just after the first project()
command in the top level CMakeLists.txt file. Projects should always set all
three variables together to make clear how the language standard requirements
should be enforced, and whether compiler extensions are permitted. Omitting
CMAKE_<LANG>_STANDARD_REQUIRED or CMAKE_<LANG>_EXTENSIONS can lead to unexpected
behavior, as the defaults may not be what some developers intuitively expect.

Projects should check to see if CMAKE_<LANG>_STANDARD and
CMAKE_<LANG>_EXTENSIONS are already set before setting them to a particular
value. Some scenarios may require enforcing stronger settings than the project’s
own minimum requirements, such as it being incorporated into a larger parent
project that needs to use a higher language version. This becomes critical if
C++20 modules are used, since they require a consistent language standard to be
used throughout the build.

If using CMake 3.8 or later, compile features can be used to specify the desired
language standard on a per-target basis. The target_compile_features() command
makes this easy and clearly specifies whether such requirements are PRIVATE,
PUBLIC, or INTERFACE. The main advantage of specifying a language requirement
this way is that it can be enforced transitively on other targets via PUBLIC and
INTERFACE relationships. These requirements are also preserved when targets are
exported and installed (see Chapter 35, Installing).

```

#### If a target exports any C++20 modules, it must set a compile feature requiring C++20 or later.

```auto
Avoid the more granular compile features like cxx_override and cxx_constexpr.
They are hard to use, difficult to maintain, and serve little practical use with
most compilers in active use today. Prefer instead to use only the higher level
meta- features that specify the language standard directly, such as cxx_std_17,
c_std_11, and so on.

Avoid directly setting the <LANG>_STANDARD and <LANG>_EXTENSIONS properties on
individual targets. Express the language standard requirement with a
<lang>_std_<value> compile feature instead, or use appropriate logic at the top
of the project to check if the standard has been set by a parent project before
setting it globally for the whole build with a CMAKE_<LANG>_STANDARD variable.
This ensures a parent project can enforce a higher language standard if it needs
to. Similarly, use top level logic to conditionally set CMAKE_<LANG>_EXTENSIONS
so it applies consistently to the whole build, but still allows a parent project
to enable extensions if needed. There is no compile feature for enabling or
disabling extensions, so this can only be safely controlled with the
CMAKE_<LANG>_EXTENSIONS variable.

If policy CMP0128 is not set to NEW, the <LANG>_EXTENSIONS properties and their
associated variables often only take effect if the corresponding <LANG>_STANDARD
is also set. This is due to how compilers frequently combine the two into a
single flag. Therefore, unless using CMake 3.22 or later with policy CMP0128 set
to NEW, it is difficult to escape having to specify CMAKE_<LANG>_STANDARD, even
when compile features are used.

```

---

<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:** [January 20, 2025, 6:34pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/6 "2025-01-20T18:34:44Z")

</div>

There’s an update to the Boost progress on modules. [C++20 modules and Boost: a prototype](https://anarthal.github.io/cppblog/modules3)

---

<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:** [March 10, 2025, 12:38pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/7 "2025-03-10T12:38:21Z")

</div>

Recent reddit update on cmake 4 and gcc15 supporting import std; [Reddit - Dive into anything](https://www.reddit.com/r/cpp/comments/1j7vplc/gcc_support_std_module_with_cmake_40_now/)

---

<div class="post-metadata">

**Author:** ![bretbrownjr](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/bretbrownjr/32/43_2.png) [@bretbrownjr](https://discourse.bemanproject.org/u/bretbrownjr)\
**Post date:** [March 17, 2025, 1:30pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/8 "2025-03-17T13:30:52Z")

</div>

Yeah, given the GCC 15 release, we should make an issue for Exemplar to provide C++ modules. To get started, see modules talks:

- [C++ Modules - Getting started today - Andreas Weis - Meeting C++ 2024](https://www.youtube.com/watch?v=NI7dAiWwibY)
- [Bill Hoffman at CppCon 2024 for resources on how to get started.](https://www.youtube.com/watch?v=7WK42YSfE9s)

It looks like Andreas is giving an updated version of his talk at ACCU. Anyone who feels like they couldn’t make the relevant PR to Exemplar, I recommend checking out that version of that talk when you can get access. Either of the above should be updated enough otherwise.

---

<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:** [May 30, 2025, 11:55am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/9 "2025-05-30T11:55:37Z")

</div>

I’ve opened a issue (PR shortly) to add module support to scope. I’ve done basic tests by hand with g+±15 and `import std` and it’s nice!

> <https://github.com/bemanproject/scope/issues/33>
>
> Since I'm going to a side experiment on using modules for other reasons I decide…d to try out making a module for beman.scope. For scope this seems to be pretty simple. Unlike fmtlib, which seems to just use a macros and not have an independent file for the module, I've created beman.scope.cppm in the include folder and successfully compiled a modular example using \`import std;\` and \`import beman.scope\`. 
> 
> The PR for this issue will at least check in the cppm file with examples and tests - cmake tbd.

It appears that fmtlib has a special file for doing modules test, but I saw noted in a recent PR that they don’t have CI for modules – that would be something nice to setup, but I imagine might require cmake 4 - (@vito.gamberini do you know for sure – I’m using 4.02 locally now).

---

<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:** [May 31, 2025, 1:45am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/10 "2025-05-31T01:45:28Z")

</div>

CMake 3.28 is all that’s required for modules, which is what ships in the current Ubuntu LTS (the internationally recognized signal for “OK to put as your minimum version”).

---

<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:** [May 31, 2025, 1:47am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/11 "2025-05-31T01:47:30Z")

</div>

Throwing my hat in the “this is what modules might look like” ring

> <https://github.com/bemanproject/exemplar/pull/167>
>
> This is a big block of changes (well, as big as it gets with exemplar) that does… two things:
> \* Incorporates lessons learned from updating \`beman.scope\` to be packageable, as well as discussions had at C++Now
> \* Converts \`beman.exemplar\` to be "modules-first", which is to say it requires module support from the toolchain in order to run tests and build examples, but still supports using the traditional header files when installed as a library
> 
> This does not violate anything in the Beman standard, but rather makes use of things we might want to have concrete consensus on now that they've arisen as issues.
> 
> I do not intend for this to be merged outright, it's more a piece of performance art. It's easier to debate pros and cons with a concrete implementation of all those pros and cons laid out.
> 
> \*\*Related Discussions:\*\*
> \* All of the commentary from https://github.com/bemanproject/scope/pull/31 is the same here, please give that a read through.
> \* This re-asserts the changes being discussed in https://github.com/bemanproject/exemplar/issues/166, so please divert testing discussion there
> \* For some background on why I did this, see the modules discussion here https://github.com/bemanproject/scope/pull/34, but this is an appropriate PR to kvetch about how hard modules are if you need to get that out of your system. I am a sympathetic shoulder.

A much more intrusive take that assumes you have a compiler with pretty good named module support. None of the CI containers met that assumption. Working on it.

---

<div class="post-metadata">

**Author:** ![Sdowney](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/sdowney/32/73_2.png) [@Sdowney](https://discourse.bemanproject.org/u/Sdowney)\
**Post date:** [May 31, 2025, 10:39pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/12 "2025-05-31T22:39:05Z")

</div>

I just noticed that the gcc-15 Ubuntu 25.04 package installs the module interface definitions in /usr/include. Not sure if anyone at ubuntu or debian noticed, since they are in ‘bits’ but it’s at least something:

```txt
/usr/include/c++/15/bits/std.compat.cc
29:export module std.compat;

/usr/include/c++/15/bits/std.cc
37:export module std;

```

---

<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 2, 2025, 2:27pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/13 "2025-06-02T14:27:48Z")

</div>

> [@Sdowney](#):
>
> gcc-15 Ubuntu 25.04 package installs the module interface definitions in /usr/include.

Interesting – and geez I almost forgot about compat.

As a progress report I’ll say that scope has ‘crossed the rubicon’ to being ‘modules-ready’. It’s been tested on 3 compilers and the cmake is updated to test it on those platforms. Import std or compat is not involved since that’s a higher bar. I think the remaining issues we have come down to needing g++15 in CI system and fixing clang compiles to work with cmake 3.28.

Thanks to all that participated in _the adventure_, I know I learned a lot about the state of modules 🙂

---

<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:** [June 17, 2025, 9:39am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/14 "2025-06-17T09:39:49Z")

</div>

With ubuntu 25.4 I have a working eperimantal example tested with `cxx_modules` and `import std`:

> **[No SOURCES given to target: \_\_CMAKE\_\_CXX26 on ubuntu 25.04](https://discourse.cmake.org/t/no-sources-given-to-target-cmake-cxx26-on-ubuntu-25-04/14240/12?u=clausklein)**
>
> So I have to set for clang-20 if($ENV{CXX} MATCHES "clang" OR CMAKE\_CXX\_COMPILER MATCHES "clang") set(ENV{CXXFLAGS} -stdlib=libc++) endif() before project(...) in my CMakeLists.txt! And for gcc-15 this workaround helps: sudo mkdir -p...

---

<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 17, 2025, 12:52pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/15 "2025-06-17T12:52:38Z")

</div>

There’s no rush to incorporate `import std` work before CMake stabilizes support. It missed the train for the 4.1 branch so it has more time to cook before seeing daylight.

I think it’s very unlikely the current usage will remain the idiomatic one. I think C++23 and above targets will get “automatic” `import std` from supported compilers when support is stabilized in CMake.

---

<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:** [June 17, 2025, 5:53pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/16 "2025-06-17T17:53:11Z")

</div>

but we need to be prepared and to have a concept how to work with compilers, that does not support CXX\_MODULES!

see i.e.: [Add cmake-init generated CMake files by ClausKlein · Pull Request #4 · ClausKlein/asio · GitHub](https://github.com/ClausKlein/asio/pull/4)

---

<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, 12:16am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/17 "2025-06-18T00:16:18Z")

</div>

There’s really only two options:

- Libraries targeting C++20 support really mean C++20 support, if your compiler doesn’t support C++20, it can’t package the library. “C++20” includes modules.

- You seperate out the call to `target_sources(FILE_SET CXX_HEADER)` based on whether the compiler supports modules. This is pretty simple but hurts packaging reproducability, different compilers producing different packages for the same library is _bad_.

So both suck, I leave it to the other Bemanites to vote on which they hate less.

---

<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:** [June 18, 2025, 7:29am UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/18 "2025-06-18T07:29:39Z")

</div>

> [@vito.gamberini](#):
>
> “C++20” includes modules.

That is not really true:

- [C++ Language Support - Xcode - Apple Developer](https://developer.apple.com/xcode/cpp/#c++20)
- [Clang - C++ Programming Language Status](https://clang.llvm.org/cxx_status.html#cxx20)
- [C++ Standards Support in GCC - GNU Project](https://gcc.gnu.org/projects/cxx-status.html#cxx20)

i.e.:

```bash
bash-5.2$ cmake -S . -B build --fresh -D CMAKE_CXX_STANDARD=20
-- The CXX compiler identification is AppleClang 16.0.0.16000026
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test COMPILER_HAS_HIDDEN_VISIBILITY
-- Performing Test COMPILER_HAS_HIDDEN_VISIBILITY - Success
-- Performing Test COMPILER_HAS_HIDDEN_INLINE_VISIBILITY
-- Performing Test COMPILER_HAS_HIDDEN_INLINE_VISIBILITY - Success
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR - Success
-- Configuring done (1.3s)
CMake Error in CMakeLists.txt:
  The target named "Algo" has C++ sources that may use modules, but the
  compiler does not provide a way to discover the import graph dependencies.
  See the cmake-cxxmodules(7) manual for details. Use the
  CMAKE_CXX_SCAN_FOR_MODULES variable to enable or disable scanning.

-- Generating done (0.0s)
CMake Generate step failed. Build files cannot be regenerated correctly.
bash-5.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, 4:50pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/19 "2025-06-18T16:50:21Z")

</div>

It is really true.

C++20 is a language standard, it include modules, they’re not an optional part of the standard. No compiler fully supports C++20, but that’s a separate discussion.

The `CMAKE_CXX_STANDARD=20` tells CMake what to ask the compiler for. CMake only verifies the compiler supports such a flag, it doesn’t verify that the compiler actually supports the entire language standard.

It is a totally valid choice for a project to say “I only support compilers which support C++20, including named modules.”

---

<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, 5:14pm UTC](https://discourse.bemanproject.org/t/c-20-modules-in-beman-project-libraries/279/20 "2025-06-18T17:14:38Z")

</div>

Anyway, on the topic of AppleClang, I’m unclear if it actually doesn’t support modules (ie, won’t accept `-fmodule-file` flags), or if they simply don’t ship `clang-scan-deps` and thus lack a scanner (well, I know for certain they don’t ship a scanner).

If it’s only the latter we might be able to hack something into upstream CMake that allows the user to specify a module scanner and backdoor module support into AppleClang via the upstream clang-scan-deps.

EDIT: Ya it supports modules, I’m going to explore a solution to the scanner problem.

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