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” and cppreference calls “module partition implementation unit” [see the Module Partitions section], namely:
From cppreference:
/////// 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
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.
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:
// 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:
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:
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:
[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:
// 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.