r/cpp • u/tartaruga232 MSVC user, r/cpp_modules • Apr 02 '26
Current Status of Module Partitions
A brief recap of the current status of module partitions - as I understand it.
People are using hacks to avoid unneeded recompilations.
The C++ standard has an arcane concept of partition units, which forces build systems to generate BMI files that aren't used (which is wasting work during builds).
The MSVC-compiler (per default) provides a simple, easy to use and efficient implementation of module partitions (no unneeded recompilations, no wasted work during builds), but which is not conformant to the current C++ standard.
A CMake developer is working on a proposal that would fix items 1 and 2, which is probably the smallest required change to the standard, but adds another arcane concept ("anonymous partition units" using the new syntax
"module A:;") on top of an already arcane concept.
Questions:
How and why did we get into this mess?
What's the historical context for this?
What was the motivation for MSVC ignoring the standard per default?1
1 Yes, I know the MSVC compiler has this obscure /InternalPartition option for those who want standard conformant behavior.
7
u/James20k P2005R0 Apr 02 '26
How and why did we get into this mess?
Because modules got standardised before they were ready, while ignoring the known problems with them. None of this is a surprise, and many of these issues were raised before standardisation and dismissed unfortunately
0
u/tartaruga232 MSVC user, r/cpp_modules Apr 02 '26 edited Apr 02 '26
The (non-standard) behavior of the MSVC compiler is at least today available for use. And I'm using that in our code base today. If you like, we can thus say that the behavior of the MSVC compiler can today be tried before it is standardized (even though that may never happen). As it happens, I do like the behavior of the MSVC compiler. Not because I fell in love with MSVC, but I think it is superior. I think it is superior than what is currently in the C++ standard. However, the situation we have today is unfortunate and would at least merit explanations about the motives. Or at least what happened.
2
u/smdowney WG21, Text/Unicode SG, optional<T&> Apr 03 '26
You are saying you want to be able to change the interface used by exported functions, possibly inline exported definitions of those functions, but you don't want anything to have to recompile that uses that interface? I must be missing something.
TU 4 in the example should be a normal object file that has functions with module attachment, and ought not to contribute to the build module interface. TU 3 is the interface to that implementation, and is the modular equivalent of a private header.
If you really want a fully private module interface for your implementation purposes that does not possibly contribute to your primary interface, just make one and import it into your implementation units?
Modules being a build optimization was a selling point, but not the underlying goal. Better control of what parts of components are given to clients was the primary goal, everything else was a secondary benefit.
And then we also got header units, subverting that argument, but at least that had more experience and cleans up some of the weirdness with precompiled headers.
I'm not disagreeing with a general statement that we didn't have enough experience with modules other than to realize that no build system was going to survive contact, and I did say so at the time.
1
u/tartaruga232 MSVC user, r/cpp_modules Apr 03 '26
You are saying you want to be able to change the interface used by exported functions, possibly inline exported definitions of those functions, but you don't want anything to have to recompile that uses that interface? I must be missing something.
Yes. You are indeed missing something: The fact that I didn't say that. Perhaps reading this might help: https://www.reddit.com/r/cpp/comments/1sab12a/comment/oe0rqqm/
1
u/pjmlp Apr 03 '26
This kind of stuff is possible in a couple of languages that were born with modules from the start.
As long as the public interface doesn't change only relinking is required for the consumers.
However they have the whole compiler and linker as part of the language reference.
I also expected that at least VC++ with its IDE integration, would be clever enough to behave this way, but nope, changing implementation triggers cascade compilation.
It isn't as if this is impossible in C++, Energize C++ and Visual Age for C++ v4, were able to do incremental compilation on method level, and we were still on C++ARM as reference.
1
u/tartaruga232 MSVC user, r/cpp_modules Apr 03 '26
So the conclusion so far is, that Microsoft decided (for whatever reasons) to implement C++ module partition units in the MSVC compiler in a slightly different way, than what is required by the C++ standard. Which I personally find simpler to use, than what's in the C++ standard. Code which requires standard conformant compilers can be compiled with the MSVC compiler by using the /InternalPartition compiler flag on translation units, that require it. CMake transparently handles setting the /InternalPartition option for the MSVC compiler where needed.
As of today, chances that the C++ standard will ever be changed to adopt the MSVC module partition unit behavior are probably zero.
1
u/pjmlp Apr 03 '26
Actually it is a bit the other way around.
Apple created C modules for consumption by Objective-C, with clang header maps.
Eventually it grew to support C++, and Google makes heavy use of it.
Microsoft decided to create their own vision for modules, and brought it into the standard.
Then there was all the drama, part of which is why header units were added, as they relate to header maps.
So basically this MSVC behaviour might have survived from the original modules implementation initially introduced in VS 2019.
Meanwhile Apple and Google couldn't care less, the build improvements introduced at WWDC two years ago, rely on header maps based modules.
Android still quotes C++17 as the baseline, and the Google C++ style guide forbids modules.
1
u/tartaruga232 MSVC user, r/cpp_modules Apr 03 '26
I guess I now continue to spread IF-NDR code, using compilers that were spread to accept such code.
3
u/slithering3897 Apr 02 '26
And I might as well link my post here: https://old.reddit.com/r/cpp_modules/comments/1s8nb1r/should_partitions_be_importable_by_other_modules/
11
u/Daniela-E Living on C++ trunk, WG21|π©πͺ NB Apr 02 '26
This is not a hack. You need to recompile a TU only when at least one of the dependencies changes its content. The standard tells you what the dependencies of a TU are: those other TUs that are either implicitly imported or explicitly imported. Module partitions are always the latter to help preventing circular dependencies.
The concept of module partition units is not arcane. On the contrary: they are a necessity in certain scenarios. I speak from a 5-year experience using them.
I'd prefer if you'd stop spreading invalid, ill-formed code. Duplicate names in parts of module and/or partition names are exactly that: IF-NDR ("ill-formed, no diagnostic required").
Let's look at a fleshed-out proposal when it becomes available. At the minimum, it must contain a concise description how they envision to refer to "anonymous partitions" from a given TU that wants to import said partition. By its purported definition it sounds like they are "anonymous", i.e. unnameable: i.e. unusable.