# CMake Clang C++20 Modules possible Mismatch

**URL:** https://discourse.cmake.org/t/cmake-clang-c-20-modules-possible-mismatch/12921
**Category:** Code
**Tags:** os:linux, gen:ninja
**Created:** [November 9, 2024, 12:46am UTC](https://discourse.cmake.org/t/cmake-clang-c-20-modules-possible-mismatch/12921 "2024-11-09T00:46:18Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![Kelarov](https://discourse.cmake.org/user_avatar/discourse.cmake.org/kelarov/32/4927_2.png) [@Kelarov](https://discourse.cmake.org/u/Kelarov)
#### Post date: [November 9, 2024, 12:46am UTC](https://discourse.cmake.org/t/cmake-clang-c-20-modules-possible-mismatch/12921/1 "2024-11-09T00:46:18Z")

</div>

Hi, all.  
I am trying out C++20 Modules as well as CMake’s experimental support for `import std;` and have come across something curious.  
It’s about what clang calls [“internal module partition unit”](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#module-and-module-unit) and cppreference calls [“module partition implementation unit”](https://en.cppreference.com/w/cpp/language/modules) [see the **Module Partitions** section], namely:  
From cppreference:

```cpp
/////// A-C.cpp 
module A:C; // partition module implementation unit
 
// WorldImpl() is visible by any module unit of 'A' importing ':C'.
char const* WorldImpl() { return "World"; }

```

Now, back to what I’m trying to do [simplified setup, just to demonstrate the key points]. I have:

### `utils.cppm` - primary module interface unit

```cpp
export module utils;
import std;

export import :random;

export namespace utils {
// ...
}

```

### `utils-random.cppm` - partition module interface unit [naming as per cppreference]

Though I’d rather call this _module partition interface unit_ as clang does.

```cpp
export module utils:random;
import std;

export namespace utils::random {
constexpr std::string part_name {"utils::random"};
void print_partition_name();
}

```

The key point comes now: I thought of having a `utils-random.cc` to be the module partition implementation unit for the `:random` partition, so I did:

```cpp
// utils-random.cc
module utils:random;

namespace utils::random {
void print_partition_name() { std::println("{}", utils::random::part_name); }
}

```

and had the CMake listfile [1] do:

```cmake
add_library(utils STATIC)
target_sources(utils
  PRIVATE
    utils-random.cc
    PUBLIC
      FILE_SET CXX_MODULES
      FILES
        utils.cppm
        utils-random.cppm)
target_compile_features(utils
  PRIVATE cxx_std_26
  INTERFACE cxx_std_23)

```

I then get the following CMake Error:

```sh
CMake Error: Output bin/lib/utils/CMakeFiles/utils.dir/utils-random.cc.o 
provides the `utils:random` module but it is not found in a 
`FILE_SET` of type `CXX_MODULES`

```

The thing is:  
CMake [or Clang, I don’t know], thinks that I am creating a new primary module or module interface partition and should put the file under a `CXX_MODULES` file set, when I’m actually just trying to implement the `:random` partition.  
For that same reason, if I were to add `utils-random.cc` to the `CXX_MODULES` Fileset as with the other files, I’d get:

```sh
[10/24] Generating CXX dyndep file bin/lib/utils/CMakeFiles/utils.dir/CXX.dd
ninja: build stopped: multiple rules generate bin/lib/utils/CMakeFiles/utils.dir/utils-random.pcm.

```

What solves the problem?  
In `utils-random.cc` writing `module utils;` instead of `module utils:random;`  
Result:

```cpp
// utils-random.cc
module utils; // uses `import std;` from the primary mod interface unit
// no need to `import std;` here

namespace utils::random {
void print_partition_name(){std::println("{}", utils::random::part_name);}
// another funny thing:
// I can see `part_name` without a `import :random;` haha
}

```

The CMake listfile stays as in [1].

Now, this isn’t what I wanted. I wanted `utils-random.cc` to provide implementations for the `:random` partition only, not general `utils` stuff.  
If I had a, say, `utils::hello()` in `utils.cppm`, then I could have its implementation in a `utils.cc` file.

I mean, having `module utils;` be needed in files that implement stuff from separate partitions is confusing. So, yeah, I’d like to have it as both clang and cppreference state it in the docs: `module A:B` be the implementation file for the `B` partition of the `A` primary module.

## Question

Am I the problem [maybe I’m completely misunderstanding all of this and messing all up] or is there some sort of mismatch in the implementations of modules, either in CMake or clang?

Please, feel free to also suggest any tips, feedback, etc.  
I just would like to work with Modules as they make things way neater, so I’m learning and experimenting with all this.

Thanks in advance.

---

<div class="post-metadata">

### Author: ![Kelarov](https://discourse.cmake.org/user_avatar/discourse.cmake.org/kelarov/32/4927_2.png) [@Kelarov](https://discourse.cmake.org/u/Kelarov)
#### Post date: [November 9, 2024, 1:10am UTC](https://discourse.cmake.org/t/cmake-clang-c-20-modules-possible-mismatch/12921/2 "2024-11-09T01:10:56Z")

</div>

PS1:  
I also tried:

```cpp
// utils.cppm
export module utils;
import std;
import :random_impl;
export import :random;

export namespace utils {}

// utils-random.cc
module utils:random_impl;
import :random;

namespace utils::random {
void print_partition_name() { std::println("{}", utils::random::part_name); }
}

```

as clang kinda does in their docs, though I get the same error:

```sh
CMake Error: Output bin/lib/utils/CMakeFiles/utils.dir/utils-random.cc.o provides the `utils:random_impl` module but it is not found in a `FILE_SET` of type `CXX_MODULES`

```

PS2:  
I also tried doing what they do in their [examples](https://clang.llvm.org/docs/StandardCPlusPlusModules.html#module-and-module-unit), and compiling and linking from the command line, so, no CMake involved, and it, surprisingly, works.

I found that extremely weird.  
They do: `module <primary_module>:<name_1>` and `import :<part_to_be_implemented>` [in the implementation file] and `import :<name_1>;` in the `.cppm`, primary module file. Totally different from cppreference.  
According to cppreference, `<name_1>` should be **module partition interface unit** we’re implementing, and there should be no `import :<partition_to_be_implemented>;`, since this would be clear from `module <primary_module>:<partition_to_be_implemented>;` statement.

Nevertheless, that’s why I decided to post here first, since, via clang++ only, the example works ok, regardless of being weird or not.

PS3: I know this is all experimental,and will, therefore, have some rough edges. As I said, I’m just trying to experiment with what we have to see what works and what doesn’t, how this all works, etc.
