# Advice on C++20 modules (Boost)

**URL:** https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641
**Category:** Usage
**Created:** [April 11, 2024, 2:58pm UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641 "2024-04-11T14:58:25Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![anarthal](https://discourse.cmake.org/user_avatar/discourse.cmake.org/anarthal/32/4486_2.png) [@anarthal](https://discourse.cmake.org/u/anarthal)
#### Post date: [April 11, 2024, 2:58pm UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641/1 "2024-04-11T14:58:25Z")

</div>

Hi all,

I’m a Boost author exploring the possibilities offered by C++20 modules for our codebase. My objective is enabling my users to import my libraries, as per `import boost.xyz`. I’ve done some research ([C++20 modules and Boost: an analysis](https://anarthal.github.io/cppblog/modules)) and the topic seems to have gained some traction on the Boost mailing list.

Our idea is to create a module interface unit per library, exporting what we currently have in our headers. We’d distribute both the headers (as we do today) and the new module code. Since BMIs seem pretty non-portable, we’d ask users to build these module unit themselves (as the standard libraries currently do).

Our official way of consuming Boost code is using CMake, so I’ve gone ahead and played with the new FILE\_SET CXX\_MODULES feature (which works great). I’m trying to figure out the best way to use this feature for our project:

- My first attempt was to build a library with a PUBLIC FILE\_SET in our CMake, and then install() it, creating a package consumable with find\_package. When the consumer uses it (using find\_package, then linking against the IMPORTED module target), the module is built (good!). However, the module is built only once - if the users has two executables with BMI-incompatible build flags, the module can’t be used for both.
- I then wrapped the code required to build a module library in a function that would be made available using find\_package ([C++20 modules and Boost: an analysis](https://anarthal.github.io/cppblog/modules#_consuming_boost_using_modules)). This looks like a workaround, but allows for building the module as many times as required.
- While the latter point works great for libraries without dependencies (I used standalone Asio as a playground), I don’t think it scales well to our complex dependency tree. As a user, I’d like to say “I need Boost.Beast” and get all of Beast’s dependent modules built automatically.

Do you have any advice the best way to achieve this?

Many thanks,  
Ruben.

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [April 11, 2024, 3:44pm UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641/2 "2024-04-11T15:44:28Z")

</div>

Please note [C++20 Modules, CMake, And Shared Libraries - Crascit](https://crascit.com/2024/04/04/cxx-modules-cmake-shared-libraries/)

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 11, 2024, 5:44pm UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641/3 "2024-04-11T17:44:58Z")

</div>

> [@anarthal](#):
>
> However, the module is built only once - if the users has two executables with BMI-incompatible build flags, the module can’t be used for both.

Known issue; on the roadmap. I’ll try to remember to report back here or loop you in when I have something testable.

---

<div class="post-metadata">

### Author: ![anarthal](https://discourse.cmake.org/user_avatar/discourse.cmake.org/anarthal/32/4486_2.png) [@anarthal](https://discourse.cmake.org/u/anarthal)
#### Post date: [April 11, 2024, 6:28pm UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641/4 "2024-04-11T18:28:39Z")

</div>

That’s great. I’m happy to help by testing the feature early if that helps.

Will you support building the entire module depency chain (i.e. linking to Boost::beast builds Boost::asio, Boost::system and so on)? Or would dependencies need to be specified manually? Is there an ETA for this?

Many thanks!  
Ruben.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 11, 2024, 6:51pm UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641/5 "2024-04-11T18:51:46Z")

</div>

> [@anarthal](#):
>
> Or would dependencies need to be specified manually?

Dependencies are specified by `target_link_libraries`. If `beast` needs `asio`, it needs to list it in its link interface.

> [@anarthal](#):
>
> Is there an ETA for this?

Nothing I can commit to, sorry. Work needed for it is on the roadmap for this year (hopefully this summer), but “going all the way” isn’t yet planned out.

---

<div class="post-metadata">

### Author: ![anarthal](https://discourse.cmake.org/user_avatar/discourse.cmake.org/anarthal/32/4486_2.png) [@anarthal](https://discourse.cmake.org/u/anarthal)
#### Post date: [April 11, 2024, 7:00pm UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641/6 "2024-04-11T19:00:35Z")

</div>

That’s great, thanks for your help!

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 11, 2024, 7:55pm UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641/7 "2024-04-11T19:55:05Z")

</div>

This is the issue to watch: [https://gitlab.kitware.com/cmake/cmake/-/issues/25539](https://gitlab.kitware.com/cmake/cmake/-/issues/25539)

---

<div class="post-metadata">

### Author: ![anarthal](https://discourse.cmake.org/user_avatar/discourse.cmake.org/anarthal/32/4486_2.png) [@anarthal](https://discourse.cmake.org/u/anarthal)
#### Post date: [April 12, 2024, 2:56pm UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641/8 "2024-04-12T14:56:06Z")

</div>

Thanks. Just to make sure I understood correctly (since I see a lot of seemingly unrelated stuff in this issue), a consumer code like the following:

```auto
# Boost::beast is an imported library target, only composed of headers and a C++20 module interface unit
find_package(Boost REQUIRED COMPONENTS Beast)
set(CMAKE_CXX_EXTENSIONS OFF)

add_executable(exe1 exe1.cpp)
target_compile_features(exe1 PRIVATE cxx_std_20)
target_link_libraries(exe1 PRIVATE Boost::beast)

add_executable(exe2 exe2.cpp)
target_compile_features(exe2 PRIVATE cxx_std_23)
target_link_libraries(exe2 PRIVATE Boost::beast)

```

Will compile the Boost.Beast module and their dependents twice, using the consumer flags (`-std=c++20` for `exe1` and `-std=c++23` for `exe2`)?

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 12, 2024, 5:13pm UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641/9 "2024-04-12T17:13:02Z")

</div>

> [@anarthal](#):
>
> Will compile the Boost.Beast module and their dependents twice, using the consumer flags (`-std=c++20` for `exe1` and `-std=c++23` for `exe2`)?

That is the end goal, yes.

---

<div class="post-metadata">

### Author: ![anarthal](https://discourse.cmake.org/user_avatar/discourse.cmake.org/anarthal/32/4486_2.png) [@anarthal](https://discourse.cmake.org/u/anarthal)
#### Post date: [April 12, 2024, 5:18pm UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641/10 "2024-04-12T17:18:01Z")

</div>

Another point: some libraries (like Asio) are infamous by their number of configuration macros. For instance, some third-party libraries rely on `BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT` for compatibility, or on `BOOST_ASIO_DISABLE_THREADS` for optimizations. Enabling users to build such configurations would be a killing point.

Thanks.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 12, 2024, 5:22pm UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641/11 "2024-04-12T17:22:37Z")

</div>

Only ABI-compatible usages can be serviced as the object files are only built once; everything else will use BMI-only outputs and not have a way to satisfy non-inline symbols not provided by the main library. The only real rule that’s going to have to be enforced is that source-specific flags will be assumed to not affect BMI consumption (otherwise we have a BMI set per source file flag set, not just target flag set).

---

<div class="post-metadata">

### Author: ![anarthal](https://discourse.cmake.org/user_avatar/discourse.cmake.org/anarthal/32/4486_2.png) [@anarthal](https://discourse.cmake.org/u/anarthal)
#### Post date: [April 15, 2024, 9:32am UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641/12 "2024-04-15T09:32:11Z")

</div>

I forgot to mention - all these libraries with lots of configuration macros are header-only. As a user, I’d currently just include the Asio headers in my application, and define macros like `BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT` to customize behavior.

In a module world, the user would need to have a way to specify which of these macros need to be defined when building their Asio module. There’s a high chance that these macros won’t have been defined when we built and exported the Asio module - since some of them are incompatible. If it helps CMake anyhow, we could list for each library which macros represent configuration options affecting the BMI.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 17, 2024, 8:37pm UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641/13 "2024-04-17T20:37:11Z")

</div>

As long as any possible ABI symbol is present in the library the `boost_asio` library provides (including module initializers), things should be fine. If everything is inline, then the library just needs to provide module initializers for every possible module.

> [@anarthal](#):
>
> In a module world, the user would need to have a way to specify which of these macros need to be defined when building their Asio module.

I’m not sure how this will look in CMake, but I suspect that something needs to be done as the only place is `-D` on the command line. Maybe something like:

```cpp
#if __has_include(<boost/asio/user/config.hpp>)
#include <boost/asio/user/config.hpp>
#endif
// Polyfills anything not specified with defaults.
#include <boost/asio/default/config.hpp>

```

?

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [December 2, 2024, 8:42am UTC](https://discourse.cmake.org/t/advice-on-c-20-modules-boost/10641/14 "2024-12-02T08:42:59Z")

</div>

@anarthal Dit you try to compile `asio` with **MSVC** and `CXX_MODULE` enabled too?

I have massive problems with this use case on Windows CI:

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

@DanielaE May you have a look at this **PR**?

see too [Add GNUmakefile and CI script to help fix problems on OSX with clang++-18 and cmake v3.30 by ClausKlein · Pull Request #1 · anarthal/boost-modules-bench · GitHub](https://github.com/anarthal/boost-modules-bench/pull/1/commits/99a645c152466620ddf2207289114b887e2e0e51)
