# C++ 20 Modules Update

**URL:** https://discourse.cmake.org/t/c-20-modules-update/7330
**Category:** Development
**Created:** [January 26, 2023, 8:20pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330 "2023-01-26T20:20:17Z")
**Posts on this page:** 20
**Page:** 2

<div class="post-metadata">

### Author: ![RobN](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/r/e9bcb4/32.png) [@RobN](https://discourse.cmake.org/u/RobN)
#### Post date: [March 7, 2023, 3:23pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/23 "2023-03-07T15:23:57Z")

</div>

> [@lomero](#):
>
> This is the output of console when try to create the dependencies for build
> 
> ```auto
> clang-scan-deps-17: Unknown command line argument '--p1689-targeted-file-name=/mnt/c/Repositories/DeSiGNAR/berti/cmakemodules/main.cpp'. Try: '/usr/bin/clang-scan-deps-17 --help'
> 
> ```

I’m in the same boat. I’d like to try C++ modules, but only if I can do it with the main branch of clang. Do we have an updated command line for this `clang-scan-deps` tool?

I just compiled llvm and clang from source, so I have:

```auto
./build/bin/clang-scan-deps --version
LLVM (http://llvm.org/):
  LLVM version 17.0.0git
  Optimized build.

```

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [March 7, 2023, 3:31pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/24 "2023-03-07T15:31:07Z")

</div>

> [@RobN](#):
>
> Do we have an updated command line for this `clang-scan-deps` tool?

See [this code](https://gitlab.kitware.com/cmake/cmake/-/blob/5f4dad37f03/Modules/Compiler/Clang-CXX.cmake#L34-44). CMake 3.26.0-rc6 and above will set `CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE` automatically with Clang 16+, but you’ll still need to set `CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API` and `CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP`.

---

<div class="post-metadata">

### Author: ![RobN](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/r/e9bcb4/32.png) [@RobN](https://discourse.cmake.org/u/RobN)
#### Post date: [March 7, 2023, 3:40pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/25 "2023-03-07T15:40:26Z")

</div>

Great, thanks!

I had another error below with cmake 3.25.2, but once I updated to 3.26 using `brew install cmake --HEAD`, now it works.

```plaintext
CMake Error: -E cmake_ninja_dyndep does not understand the clang module map format

```

---

<div class="post-metadata">

### Author: ![RobN](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/r/e9bcb4/32.png) [@RobN](https://discourse.cmake.org/u/RobN)
#### Post date: [March 9, 2023, 4:18pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/26 "2023-03-09T16:18:34Z")

</div>

I’m getting some errors because (I guess) it doesn’t know about new extensions, like `.ccm`.

I changed my file extension from `.cc` to `.ccm`, as instructed by the [Clang docs](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#file-name-requirement). That caused this error below about the “linker language”. I got past that by adding the `set_target_properties`.

```plaintext
CMake Error: CMake can not determine linker language for target: learn_modules_lib

```

```cmake
add_library(learn_modules_lib)
target_sources(learn_modules_lib
  PUBLIC
    FILE_SET cxx_modules TYPE CXX_MODULES FILES
    Learning/Modules/foo.ccm
)
# 'Fixes' error
set_target_properties(learn_modules_lib PROPERTIES LINKER_LANGUAGE CXX)

```

Now I get another error when I build…

```plaintext
FAILED: Learning/liblearn_modules_lib.a 
: && /usr/local/Cellar/cmake/HEAD-3d6075d/bin/cmake -E rm -f Learning/liblearn_modules_lib.a && /usr/bin/ar qc Learning/liblearn_modules_lib.a && /Users/rob/Dev/llvm-project/build/bin/llvm-ranlib Learning/liblearn_modules_lib.a && /usr/local/Cellar/cmake/HEAD-3d6075d/bin/cmake -E touch Learning/liblearn_modules_lib.a && :
ar: no archive members specified
usage: ar -d [-TLsv] archive file ...
	ar -m [-TLsv] archive file ...
	ar -m [-abiTLsv] position archive file ...
	ar -p [-TLsv] archive [file ...]
	ar -q [-cTLsv] archive file ...
	ar -r [-cuTLsv] archive file ...
	ar -r [-abciuTLsv] position archive file ...
	ar -t [-TLsv] archive [file ...]
	ar -x [-ouTLsv] archive [file ...]
ninja: build stopped: subcommand failed.

```

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [March 9, 2023, 4:21pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/27 "2023-03-09T16:21:56Z")

</div>

> [@RobN](#):
>
> it doesn’t know about new extensions, like `.ccm`.

[CMake MR 5926](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5926) added support for `.ixx` and `.cppm`, but not `.ccm`, `.cxxm`, or `.c++m`. I’ll look at adding those.

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [March 9, 2023, 4:47pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/28 "2023-03-09T16:47:53Z")

</div>

Added in [CMake MR 8308](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/8308), targeting CMake 3.27.

Meanwhile, just use `.cpp`, `.cc`, or other classic C++ file extensions for `CXX_MODULES` file set entries.

---

<div class="post-metadata">

### Author: ![RobN](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/r/e9bcb4/32.png) [@RobN](https://discourse.cmake.org/u/RobN)
#### Post date: [March 9, 2023, 4:49pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/29 "2023-03-09T16:49:09Z")

</div>

I’ve been using Emacs with `lsp-mode` and `clangd` for my C++ project. My cmake command contains arguments to export the `compile_commands.json` file, which `clangd` then uses. It’s been working great, but now with modules it’s reporting an error, even though everything compiles file.

Screen from Emacs:

 ![image](https://discourse.cmake.org/uploads/default/original/2X/7/725105f3efffe656afae861fc07c30fb3b277a20.png)

The module _is_ found and this file compiles and runs fine.

Any ideas on how to fix this?

This is the `cmake` command that has been successfully creating the `compile_commands.json` file for `clangd`:

```plaintext
cmake -B build-debug -S . -DCMAKE_TOOLCHAIN_FILE=/Users/rob/Dev/vcpkg/scripts/buildsystems/vcpkg.cmake 
   -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja -DCMAKE_BUILD_TYPE=Debug

```

---

<div class="post-metadata">

### Author: ![RobN](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/r/e9bcb4/32.png) [@RobN](https://discourse.cmake.org/u/RobN)
#### Post date: [March 9, 2023, 4:52pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/30 "2023-03-09T16:52:11Z")

</div>

> [@brad.king](#):
>
> Meanwhile, just use `.cpp`, `.cc`, or other classic C++ file extensions for `CXX_MODULES` file set entries.

Or `.cppm` I assume. After your previous post I switched it to that, and it seems to work.

---

<div class="post-metadata">

### Author: ![RobN](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/r/e9bcb4/32.png) [@RobN](https://discourse.cmake.org/u/RobN)
#### Post date: [March 9, 2023, 10:13pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/31 "2023-03-09T22:13:52Z")

</div>

More more thing, it seems `.mm` (Objective-C++) can’t `import` modules. I get errors like:

```plaintext
error: Objective-C was disabled in PCH file but is currently enabled
error: module file AppleInterop/CMakeFiles/AppleInterop.dir/AppleInterop.Strings.pcm cannot be loaded due to a configuration mismatch with the current compilation [-Wmodule-file-config-mismatch]
/Users/rob/Workspace/MonoRepo/AppleInterop/AppleInterop/UserDefaults.mm:10:2: error: unknown type name 'include'

```

If anyone knows how to get around that, please let me know. I need a few of those `.mm` files, to wrap certain Apple APIs.

---

<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: [March 10, 2023, 5:05am UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/32 "2023-03-10T05:05:44Z")

</div>

> [@brad.king](#):
>
> but not `.ccm`, `.cxxm`, or `.c++m`. I’ll look at adding those.

Ugh. We have enough extensions floating around. I see no reason for these new ones (it is, after all, just C++ code), but whatever. I don’t forsee progress on getting everyone to agree on one extension (or even a set that I can count on one hand).

> [@RobN](#):
>
> My cmake command contains arguments to export the `compile_commands.json` file, which `clangd` then uses. It’s been working great, but now with modules it’s reporting an error, even though everything compiles file.

`compile_commands.json` does not have enough information for modules prior to building the project (and before anyone asks, it cannot have enough when using explicit module builds which is all CMake supports). There’s a `@rspfile` argument we pass to the compiler that does not exist until sources have been scanned and the target’s collation command executed.

> [@RobN](#):
>
> If anyone knows how to get around that, please let me know. I need a few of those `.mm` files, to wrap certain Apple APIs.

I have no idea how this is supposed to work (beyond “ignore that it is Objective-C++ and treat it as C++ code”). Please work with Clang developers to see what Objective-C++ is doing with C++ module support.

---

<div class="post-metadata">

### Author: ![RobN](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/r/e9bcb4/32.png) [@RobN](https://discourse.cmake.org/u/RobN)
#### Post date: [March 10, 2023, 4:27pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/33 "2023-03-10T16:27:21Z")

</div>

> [@ben.boeckel](#):
>
> […] Please work with Clang developers to see what Objective-C++ is doing with C++ module support.

I [asked them](https://discourse.llvm.org/t/c-20-modules-and-objective-c-mm-files/69116), and learned about these compiler flags as a workaround.

```cmake
set_source_files_properties(MyLibrary/UserDefaults.mm
  PROPERTIES COMPILE_FLAGS "-Xclang -fno-validate-pch")

```

---

<div class="post-metadata">

### Author: ![RobN](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/r/e9bcb4/32.png) [@RobN](https://discourse.cmake.org/u/RobN)
#### Post date: [March 14, 2023, 2:56am UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/34 "2023-03-14T02:56:18Z")

</div>

What is the correct way to define, in one module, two classes that depend on each other? I tried the code below, and a few variations, but I get the error at the bottom about a cyclic dependency.

UI.cc

```plaintext
export module UI;
export import :Window;
export import :View;

```

Window.cc

```plaintext
module UI:Window;
import :View;
export class Window {
public:
    Window() {}
    View getMainView() { return View(); }
};

```

View.cc

```plaintext
module UI:View;
import :Window;
export class View {
public:
    View() {}    
    Window getWindow() {
        return Window();
    }
};

```

```plaintext
ninja: build stopped: dependency cycle: 
     Learning/CMakeFiles/learn_modules.dir/UI-Window.pcm 
  -> Learning/CMakeFiles/learn_modules.dir/UI-View.pcm 
  -> Learning/CMakeFiles/learn_modules.dir/UI-Window.pcm.

```

---

<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: [March 14, 2023, 5:20am UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/35 "2023-03-14T05:20:50Z")

</div>

Modules may not import each other (directly or transitively). This is [part of the standard](https://eel.is/c++draft/module.import#10). What you can do is put the declarations in the headers (though your interfaces still have a cycle) and put the _implementations_ into a TU looking something like this:

```plaintext
module UI;

Window::Window() {}
View Window::getMainView() { return View(); }

View::View() {}
Window View::getWindow() { return Window(); }

```

I don’t remember if you need to name the partitions or not (that seems weird to me as this TU imports _all_ of `UI` and therefore already has it “available”).

---

<div class="post-metadata">

### Author: ![RobN](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/r/e9bcb4/32.png) [@RobN](https://discourse.cmake.org/u/RobN)
#### Post date: [March 14, 2023, 1:00pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/36 "2023-03-14T13:00:13Z")

</div>

Okay, I got that to work by putting the class declarations in the primary module interface unit, and then creating a .cc file with your example code block. I guess that’s called “module implementation unit”.

But, that requires that I declare everything in the primary interface file. In real life I have lots of files, so I want to split them out, and I think that’s what “interface partitions” are for. Those seem to work with raw Clang commands (I can follow [their example here](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#quick-start)), but I can’t get them to work with CMake. Are they supported yet?

If I put the partition implementation files in the CXX\_MODULES files set, I get errors like:

```plaintext
ninja: build stopped: multiple rules generate Learning/CMakeFiles/learn_modules.dir/UI-Window.pcm.

```

If I put them them in the normal file set, I get:

```plaintext
CMake Error: Output Learning/CMakeFiles/learn_modules.dir/Learning/Modules/Vimpl.cc.o provides 
the `UI:View` module but it is not found in a `FILE_SET` of type `CXX_MODULES` (or 
`CXX_MODULE_INTERNAL_PARTITIONS` if it is not `export`ed)

```

I tried `CXX_MODULE_INTERNAL_PARTITIONS` but got:

```plaintext
target_sources File set TYPE may only be "HEADERS", "CXX_MODULES", or
"CXX_MODULE_HEADER_UNITS"

```

---

<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: [March 14, 2023, 3:52pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/37 "2023-03-14T15:52:21Z")

</div>

> [@RobN](#):
>
> Those seem to work with raw Clang commands (I can follow [their example here](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#quick-start)), but I can’t get them to work with CMake

Interface partitions work (and are tested). I don’t see a circular dependency anywhere there.

> [@RobN](#):
>
> Are they supported yet?

Circular dependencies are not planned to be supported as it is not standard C++. I think it might work with the two-phase compilation Clang has, but Clang is the only compiler to support that model (today) and even then it is known to not have the same behavior as the one-phase mechanism CMake is using (last I heard). Even when CMake supports the two-phase compilation, I’m partial to not allowing circular dependencies.

> [@RobN](#):
>
> If I put the partition implementation files in the CXX\_MODULES files set, I get errors like:

Sources which do not create a BMI (including module implementation files) belong in the “regular” source lists, not `CXX_MODULES` file sets.

> [@RobN](#):
>
> `CXX_MODULE_INTERNAL_PARTITIONS`

This is an MSVC extension and not relevant here. I suspect that this will “never” get used in practice.

---

<div class="post-metadata">

### Author: ![RobN](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/r/e9bcb4/32.png) [@RobN](https://discourse.cmake.org/u/RobN)
#### Post date: [March 14, 2023, 4:28pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/38 "2023-03-14T16:28:39Z")

</div>

> [@ben.boeckel](#):
>
> > [@RobN](#):
> >
> > Are they supported yet?
> 
> Interface partitions work (and are tested). […] Circular dependencies are not planned to be supported as it is not standard C++.

Thanks! I meant to ask if interface partitions, not circular dependencies, are supported. So that answers my question.

I think I got it working now. I had followed that Clang example, but made one mistake, which caused the error: _“multiple rules to generate … UI-Window.pcm”_.

My mistake was that I used the same name in the partition-implementation module as in the partition interface. It faked me out because with the non-partitions, their demo code does use the same name in multiple files.

File A: `export module M; ... interface stuff ...`  
File B: `module M; ... impl stuff ...`

But…

File C: `export module M:part; ... interface stuff ...`  
File D: `module M:part_impl;` ← Using `M:part` here causes problems.

---

<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: [March 14, 2023, 5:00pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/39 "2023-03-14T17:00:06Z")

</div>

> [@RobN](#):
>
> File C: `export module M:part; ... interface stuff ...`  
> File D: `module M:part_impl;` ← Using `M:part` here causes problems.

Yes, the standard confused a number of people in this regard (and is basically what the MSVC extension is from). Clarity would be nice, but there is no such thing as a “partition implementation unit” despite it being a hole that one would expect to be filled, but is excluded by not being defined at all. Implementation units always just name the module and don’t care about partitions at all.

---

<div class="post-metadata">

### Author: ![RobN](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/r/e9bcb4/32.png) [@RobN](https://discourse.cmake.org/u/RobN)
#### Post date: [March 16, 2023, 3:53pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/40 "2023-03-16T15:53:20Z")

</div>

One thing I just noticed: if I change code after a `module :private;` line (private module fragment), it triggers recompilation of dependent code. Not sure if that’s a cmake or a clang issue. (?)

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [March 16, 2023, 5:46pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/41 "2023-03-16T17:46:13Z")

</div>

> [@RobN](#):
>
> if I change code after a `module :private;` line (private module fragment), it triggers recompilation of dependent code.

CMake’s collator generates a ninja dyndep file that adds `restat = 1` to the compilation rule for the module interface unit’s object file. That tells ninja to `stat()` the outputs again after the compiler runs in order to check which outputs really changed. Ninja should recognize that consumers of unchanged outputs do not need to rebuild.

I tested this locally. When the module interface doesn’t change, clang writes an identical `.pcm` file, but it _still updates the timestamp_ of the `.pcm` file. That prevents Ninja from recognizing that the module interface hasn’t changed, so it still recompiles dependents. This is a problem in Clang.

---

<div class="post-metadata">

### Author: ![RobN](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/r/e9bcb4/32.png) [@RobN](https://discourse.cmake.org/u/RobN)
#### Post date: [March 16, 2023, 5:57pm UTC](https://discourse.cmake.org/t/c-20-modules-update/7330/42 "2023-03-16T17:57:26Z")

</div>

Interesting. I’ve never heard of a compiler not writing its output file because the one it’s replacing is the same. Is that part of how these `.pcm` files are supposed to work? Is that mentioned in the C++ standard or somewhere? If so, I can file a bug with the LLVM/Clang project, if there isn’t one already.

[Previous page](https://discourse.cmake.org/t/c-20-modules-update/7330.md?page=1)

[Next page](https://discourse.cmake.org/t/c-20-modules-update/7330.md?page=3)
