Uneeded Recompilations When Using Partitions
Our Core module is in
code/Core.
The file
Core/_Module.ixx
contains:
export module Core;
export import :Attach;
export import :Container;
export import :CopyRegistry;
export import :Diagram;
export import :Element;
export import :Grid;
export import :Interfaces;
export import :ObjectRegistry;
export import :ObjectWithID;
export import :Selection;
export import :Shift;
export import :Transaction;
export import :Undoer;
export import :Util;
export import :View;
export import :Weight;
This is the interface of the Core module. It contains a list of exported interface partitions.
The file
Core/Transaction/FinalizerDock.cpp
contains:
module Core;
...
This is an implementation file of the Core module, aka an “implementation unit”.
FinalizerDock.cpp only needs declarations from the :Transaction partition, but due to the
fact that "module Core;" implicitly imports the whole interface of the Core module (as
mandated by the standard), all partitions of
the Core module are implicitly imported as well.
If the interface partition
Core/Transaction/Transaction.ixx
is modified, ideally only the files which use declarations from it would need to be
recompiled. That is, the files:
Diagram/TransferSet.cppElement/Env.cppElement/IElement.cppTransaction/FinalizerDock.cppTransaction/Transaction.cppTransaction/TransactionImp.cpp
But due to the implicit imports of all the "module Core;" in every cpp-file,
the following files are recompiled instead:
Attach/IPointAttachment.cpp
Attach/ITerminal.cpp
Attach/ITerminalReshapeInfo.cpp
Container/IUpdateContainer.cpp
CopyRegistry/CopyRegistry.cpp
Diagram/CopyExtendSelection.cpp
Diagram/TransferSet.cpp
Element/ElementSet.cpp
Element/Env.cpp
Element/IElement.cpp
Interfaces/IDumpable.cpp
ObjectRegistry/ObjectRegistry.cpp
Selection/ExtendSelectionParam.cpp
Selection/SelectionHider.cpp
Selection/SelectionTracker.cpp
Selection/SelectionVisibilityServer.cpp
Selection/StandardSelectionRestorer.cpp
Shift/IShiftable.cpp
Shift/ShiftSet.cpp
Transaction/FinalizerDock.cpp
Transaction/Transaction.cpp
Transaction/TransactionImp.cpp
Undoer/PosUndoer.cpp
Undoer/Undoer.cpp
Undoer/UndoerFunctions.cpp
Undoer/UndoerParam.cpp
UndoerImp/PosUndoerGroup.cpp
UndoerImp/SequenceUndoer.cpp
UndoerImp/TransactionUndoer.cpp
View/ISelectionObserver.cpp
View/IView.cpp
View/IViewElement.cpp
View/SelectionObserverDock.cpp
View/VISelectable.cpp
Weight/Weight.cpp
This is only the list of files that are recompiled due to the implicit
imports in implementation files of the Core module. Of course, all explicit
importers of the Core module would need to be recompiled as well, which
are way more for our UML Editor.
Our Core module is just a small example for a module using partitions.
For large modules, those unneeded recompilations may make a difference.
Technically, they should be avoidable.
But it’s not just a problem with wasting CPU time for unneeded
recompilations. The code is also more difficult to understand, as it’s
not evident for readers of the code, where the implicitly imported
declarations are coming from. That affects also smaller modules like
our Core module. We have addressed that by explicitly (redundantly)
importing the required partitions. Those explicit imports can be
tested by temporarily commenting out the exports in the primary module
interface unit (Core/_Module.ixx) and then recompiling all files of
the Core module. The compiler will then error out if an explicit import
is missing. Those redundant explicit imports can also be used to search
where a specific partition is imported. This enables finding all effectively
needed dependencies.
The C++ language currently lacks a concise and easy to use alternative for explicitly expressing the minimally required dependencies on partitions.
(last edited 2026-04-21)