C++ 20 Modules Update

I’ve only been following this discussion loosely, so my apologies if this was already covered. Would such a change mean that a project would not be able to define any modules that are kept private to the project? In other words, would the project be forced to make all modules available for consumption outside the project, even if they didn’t want them to be visible outside the project? Or is this proposed change an opt-in thing?

Enforcement would be done by a CMake component that would plumb out the P1689 output and error on visibility (just like is done in Ninja today). We should be able to give better error messages too. I suppose the “owning target” could be named there… Theoretically yes, but the target name mapping would need plumbed through from somewhere; I don’t think anything has it at the moment.

FYI, I opened a feature request with MSVC to add support for a file-based mechanism for specifying the list of public modules for DLLs.

This is already the status quo for static libraries on MSVC. And from what I can see there doesn’t seem to be a mechanism in MSVC’s static library toolchain that allows to restrict this, so Ben’s suggestion to enforce it on the CMake level instead may be the only option here.

Note that we need the mechanism regardless because we need to write install and export bits for these modules. While “can use from elsewhere” may be a possible IDE thing, writing out these files is certainly outside the scope.

I followed these

to create:

  • Module interface partition unit.
  • Internal module partition unit.

So I have:

Details.cpp with module RToolBox:MetaInfo.Details;
Details.cppm with export module RToolBox:MetaInfo.Details;

When building I get the following error:

[build] ninja: build stopped: multiple rules generate CMakeFiles/RToolBox.dir/Debug/RToolBox-MetaInfo.Details.ifc.

I add them like that:

target_sources("${PROJECT_NAME}"
PUBLIC
  FILE_SET cxx_modules TYPE CXX_MODULES
  FILES
    "src/MetaInfo/Details.cpp"
    "src/MetaInfo/Details.cppm"

It looks like not all of the proposal is implemented (or I do not understand it yet):

Your code is invalid: you have two TUs in module ‘RToolBox’ with the same partition name ‘MetaInfo.Details’. A named module shall not contain multiple module partitions with the same module-partition

1 Like

@DanielaE Thank you for pointing me to the specification. I looked everywhere but there (I assumed it going to be too techincal). This example tied up the loose ends.
I got confused that partition implementation TUs are a thing.

While trying to understand modules. I watched this talk (entirely by coincidence - noticed a YouTube message a few days ago): https://www.youtube.com/watch?v=DJTEUFRslbI
So if I understand correctly we are supposed to compile std on our own for every project.

Will in that case make sense for the build system (in our case CMake) to provide standard facilities to automate this task? This is something I haven’t yet seen discussed anywhere else but in the talk in the link.

Ah,that latest talk of mine :blush:

Your proposal makes sense. MSBuild does it since msvc 17.6 (or .5? I can’t remember).

2 Likes

Yes. The idea is that we inspect information from the compiler about the standard library in use and make a target like CMake::CXX23 that provides the modules. It would be implicitly linked by anything using cxx_std_23. Note that adding flags like -std=c++23 not through a CMake-recognized standard-setting mechanism would likely not be something we notice.

The .cpp file is not a module file (i.e., it does not produce a BMI). It is instead an implementation unit of a module; it does not belong in CXX_MODULES filesets.

Wat?
Sorry, but a module TU with a partition name will always create a BMI because it is either a module interface partition (that contributes to the externally visible module interface) or an internal partition (that may or may not contribute to the externally reachable entitities of a module).

Oh, that : hid itself very well (I missed that . can be in the partition name too…). Anyways, MSVC does have an extension to allow such things (“implementation of partition” units; these don’t officially exist and should instead just use the module name only). Those files belong in the normal sources list.

We don’t like “extensions”, do we? :scream:

But you’re right: module implementation units (the ones without a partition name) belong into the regular FILES section because they don’t create BMIs.

BTW: I’m experimenting with CMake 3.27 right now. Unfortunately it broke my (admittedly very brittle) “implementation” of ‘compiling header units with CMake workaround’ that worked in 3.26.

Sounds good. All three vendors have agreed to support STD modules in C++20 mode as an extension. CMake should probably do too: Supporting `import std;` in C++20 · Issue #3945 · microsoft/STL · GitHub

The issue @RobN created got closed. I got the impression that this is considered a problem of the build tools and not clang itself. So I would like to ask if there are any workarounds for this issue. Currently touching a single file can result in cascade of recompilations.

There’s some work that would be needed to do this, but it isn’t required to make modules work, hence it not being done right now. The basic requirement is that the collator has the compiler write the BMI to a temporary file and then communicate with a command in the same rule that does cmake -E copy_if_different to the real location. How exactly this gets communicated needs worked out though.

Are header units supported in cmake 3.27?
I am getting an error:

error: header file (aka ‘/usr/bin/…/lib/gcc/x86_64-linux-gnu/13/…/…/…/…/include/c++/13/vector’) cannot be imported because it is not known to be a header unit

Unfortunately no, they are not (yet).

1 Like