Skip to content

C++20 modules support in CMake#455

Open
fdr400 wants to merge 36 commits into
Neargye:masterfrom
fdr400:feature/cxx20-modules
Open

C++20 modules support in CMake#455
fdr400 wants to merge 36 commits into
Neargye:masterfrom
fdr400:feature/cxx20-modules

Conversation

@fdr400
Copy link
Copy Markdown

@fdr400 fdr400 commented May 10, 2026

Hi @Neargye ! I saw your awesome project has magic_enum.cppm file with C++20 module structure but, unfortunately, there is neither CMake support nor CI tests for modules build.

So the PR introduces:

  • transparent C++20 modules support for the library
  • CMake target of CXX_MODULE type
  • modules usage example
  • CI workflows that build library as a magic_enum module and run all tests using the module
  • CI workflow with CMake install support was added
  • fixes for build with libc++ and ctest run in install test workflow

I have some experience in C++ modules and supported modules for some of Boost libraries (for example, Boost.stacktrace).

The idea for modules in Boost is not the same as for magic_enum.cppm that currently includes all headers in global module fragment and exports all public symbols.

Key concept is to make modules migration transparent for library clients (without changing their code). So the library (magic_enum in this context) provides its interface via same headers as in non-module build, but headers are preprocessed into import magic_enum if library was build with modules-on flag.

Also all function is attached to the library module, not the global module, and exported explicitly using the export keyword (that is hidden with macros to support non-module build).
So that it is harder to forget to export some public function because public interface is already in-closed into export {} block. And, again, such concept allows to build library module and consume it transparently as a header.
However, it is an ABI break because symbols have @magic_enum suffix, but I believe this is not significant problem (probably, I am wrong).

Theoretically, modules + magic_enum can significantly speed up compilation speed for library consumers because of huge number of constexpr functions and classes but I did not test it.

Current CMake modules support is not full, especially there is no two-phase compilation, and there are many troubles when targets are build with different compiler flag. But it somehow works anyway.

I can split PR into some logical parts and explain some solutions and possibly rework some of them. But firstly I want to know your opinion about all of this and are you actually interested in modules support :)

Because this is fully (I believe) backward compatibly change for all library clients, it's worth it

P.S. Thanks for the great library!

@fdr400
Copy link
Copy Markdown
Author

fdr400 commented May 13, 2026

@Neargye hello! What do you think about that?

@Neargye
Copy link
Copy Markdown
Owner

Neargye commented May 17, 2026

Hey @fdr400, great work! The CMake infrastructure, CI integration, and per-test module libraries are really well done.

One thing I'd prefer to keep different: the magic_enum.cppm rework. Honestly, I wasn't maintaining it well before, but going forward, I'll keep a closer eye on it. The explicit using style is just easier for me to review and maintain, the interface is visible in one place, and detail:: symbols can't accidentally leak. Could you revert that file to the explicit approach and just add the missing symbols?

Also a couple of small bugs found during review:

Unmatched #pragma push without #pragma pop in magic_enum.cppm
CXX_MODULES_BMI DESTINATION "" installs BMI files to install prefix root
Thanks for the contribution!

@fdr400
Copy link
Copy Markdown
Author

fdr400 commented May 22, 2026

Hi @Neargye ! I understand your opinion about primary module interface unit, so I returned the explicit using-based style and added all required exports. The transparent modules migration is also possible because of automatic import inside headers
Moreover, I added import std tests to CI. Unfortunately, import std with CMake 3.30 (The Ubuntu 24.04 default CMake) works only with clang-19 because of somehow broken llvm debian packages (I am not sure that the problem actually in llvm packages but at least it seems that way, because on newer cmake versions the import std also does not work with default settings and some strange configuration options should be used. link for details).

CXX_MODULES_BMI DESTINATION "" installs BMI files to install prefix root

CMake documentation says An empty DESTINATION may be used to suppress installing these files (for use in generic code). So the BMI is not installed. I believe BMI should not be installed because it is compiler/version specific file, so .cppm and headers are enough to compile the BMI when building user library with installed magic_enum

@fdr400
Copy link
Copy Markdown
Author

fdr400 commented May 22, 2026

I believe that resolves #396 and #349

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants