Date: Wed, 14 Jan 2026 11:45:24 +0800
> IIUC the issue is that if you have a TU that implements the interface of a particular partition, and only needs to import that partition, removing the partition name creates an interface dependency on the entire module, resulting in unnecessary rebuilding if a different interface partition changes.
Yeah, correctly.
> Alternatively, you could interpret this situation as a sign that you're putting too much in a single module; if the interface of the partition is so independent, perhaps it should be a separate module, e.g. mylib.net <http://mylib.net > instead of mylib:net.
I don’t think we should limit the number of partitions in a single module. It seems odd… e.g. within different modules, it is hard to have forward declarations.
> Chuanqi proposes to handle this by giving the implementation unit its own dummy partition name, and then wants a way to suppress BMI generation for that dummy partition. But this seems a bit like piling kludge on kludge to work around the lack of a way in the standard to specify an implementation unit for a specific partition.
Agreed generally except I don’t think it is a kludge (sorry if I misunderstand the word ‘kludge’, I looked up it in the dictionary). As I feel it is natural to do so… according to the wording of the spec, the so called implementation partition unit are implementation unit actually.
[module.unit]p2
> A module interface unit <http://eel.is/c++draft/module.unit#def:module_interface_unit > is a module unit whose module-declaration <http://eel.is/c++draft/module.unit#nt:module-declaration > starts with export-keyword <http://eel.is/c++draft/lex.pptoken#nt:export-keyword >; any other module unit is a module implementation unit <http://eel.is/c++draft/module.unit#def:module_implementation_unit >. <http://eel.is/c++draft/module.unit#2.sentence-1 >
And it looks like the spec lacks a term for the “module implementation unit” we’re talking now. The spec uses a sentense to describe it:
[module.unit]p8:
> A module-declaration <http://eel.is/c++draft/module.unit#nt:module-declaration > that contains neither an export-keyword <http://eel.is/c++draft/lex.pptoken#nt:export-keyword > nor a module-partition <http://eel.is/c++draft/module.unit#nt:module-partition > implicitly imports the primary module interface unit of the module as if by a module-import-declaration <http://eel.is/c++draft/module.import#nt:module-import-declaration >. <http://eel.is/c++draft/module.unit#8.sentence-1 >
Or maybe we can ask some guiding questions to make the discussion clea:
(1) Is it a problem now? (Change any interface unit will force the recompilation for all module implmentation units which are not a partition).
(2) If the answer to (1) is yes, is it a standard defect? If not, it shoudl be a defect of the build system.
(3) If the answert to (2) is yes, is it a wording defect or a design defect?
Thanks,
Chuanqi
------------------------------------------------------------------
From:core <core_at_[hidden]>
Send Time:Wed, Jan 14, 2026, 11:29
To:SG15<sg15_at_[hidden]>
CC:Jason Merrill<jason_at_[hidden]>; core<core_at_[hidden]>; Chuanqi Xu<chuanqi.xcq_at_[hidden]>
Subject:Re: [isocpp-core] [isocpp-sg15] [modules] wordings to allow build system to not always emit BMI for implementation partition units
On Wed, Jan 14, 2026 at 10:09 AM Chuanqi Xu via SG15 <sg15_at_[hidden] <mailto:sg15_at_[hidden] >> wrote:
> IMO, if you have a non-exported partition that you don't want exported,
remove the partition name. It can (must) then be listed outside of a
`CXX_MODULES` file set and won't make a BMI (whatever the costs may be).
The standard already has a mechanism to do the "part of a module, but
not making a BMI". Why do we need another subflavor of translation unit?
IIUC the issue is that if you have a TU that implements the interface of a particular partition, and only needs to import that partition, removing the partition name creates an interface dependency on the entire module, resulting in unnecessary rebuilding if a different interface partition changes.
Chuanqi proposes to handle this by giving the implementation unit its own dummy partition name, and then wants a way to suppress BMI generation for that dummy partition. But this seems a bit like piling kludge on kludge to work around the lack of a way in the standard to specify an implementation unit for a specific partition.
Alternatively, you could interpret this situation as a sign that you're putting too much in a single module; if the interface of the partition is so independent, perhaps it should be a separate module, e.g. mylib.net <http://mylib.net > instead of mylib:net.
This is the problem. It then requires the users to pay for the additional cost for generating BMIs. In some degree, it violates the zero-abstraction rule.
I can understand that CMake didn’t optimize this due to human resources or what ever reasons. But I think we need to be on the same page that we should allow it.
> Sure, if the build system can determine that an importable module unit isn't ever actually imported, then it can optimize away building the BMI.
This seems like an "as-if" issue, unobservable by a conforming program. The standard doesn't say anything about build system artifacts.
OTOH, BMI generation seems like a small overhead as a side effect of compilation, so it's unclear to me why avoiding it is a high priority.
Thanks for clarification. I don’t think it is a high priority. But I do think it is a problem of CMake’s implementation. And a cmake dev says the root cause is the spec wording. That’s why I sent this.
Thanks,
Chuanqi
------------------------------------------------------------------
From:core <core_at_[hidden] <mailto:core_at_lists.isocpp.org >>
Send Time:Wed, Jan 14, 2026, 03:03
To:Chuanqi Xu<chuanqi.xcq_at_[hidden] <mailto:chuanqi.xcq_at_[hidden] >>
CC:Ben Boeckel<ben.boeckel_at_[hidden] <mailto:ben.boeckel_at_[hidden] >>; core<core_at_[hidden] <mailto:core_at_[hidden] >>; SG15<sg15_at_[hidden] <mailto:sg15_at_[hidden] >>; Jens Maurer<jens.maurer_at_[hidden] <mailto:jens.maurer_at_[hidden] >>
Subject:Re: [isocpp-core] [modules] wordings to allow build system to not always emit BMI for implementation partition units
On Tue, Jan 13, 2026 at 11:19:32 +0800, Chuanqi Xu wrote:
> As the author of CMake modules and who said the current wording has a
> bug/defect, would you like to comment to explain why do you think the
> current wording has a bug/defect for it?
> CC Jens as the chair of CWG.
This was not me (I am `mathstuf` on Reddit). It is, however, a fellow
Kitwarean. He's not available right away, so I am speaking for myself
here based on what he wrote.
From Chuanqi's blog post:
> However, in practice, there is a small issue for CMake users with this
> approach. Currently, CMake requires all module implementation
> partition units to be listed in CXX_MODULES_FILES, which causes CMake
> to generate a BMI for each of them. This is a waste of time. In our
> example, network.cpp, common.cpp, and util.cpp are designed not to be
> imported by any other unit, a fact that the programmer can guarantee
> and intends.
From linked Reddit reply:
> As discussed upstream, this is a standard bug and there's unlikely to
> be any movement on it unless something changes in the standard.
>
> The standard has no way to advertise a "non-exporting" partition unit.
> It is assumed all partition units export, thus all partition units
> must generate a BMI. Notably, clang makes the same assumption whenever
> it sees a .cppm extension.
>
> The MSVC behavior (absent /internalPartition) is simply broken and
> non-conforming
IMO, if you have a non-exported partition that you don't want exported,
remove the partition name. It can (must) then be listed outside of a
`CXX_MODULES` file set and won't make a BMI (whatever the costs may be).
The standard already has a mechanism to do the "part of a module, but
not making a BMI". Why do we need another subflavor of translation unit?
From Chuanqi's Reddit reply:
> For build system, my confusion part is, in bazel, it works fine if we
> put the module unit in the `srcs` field instead of the
> `module_interface` field. Given the support of modules in bazel
> generally follows cmake, I don't understand why cmake can't make the
> same behavior.
CMake sees that the scanner says "makes a BMI named X", compares against
its notes that it isn't expecting a BMI and assumes user error.
--Ben
_______________________________________________
Core mailing list
Core_at_[hidden] <mailto:Core_at_lists.isocpp.org >
Subscription: https://lists.isocpp.org/mailman/listinfo.cgi/core <https://lists.isocpp.org/mailman/listinfo.cgi/core >
Link to this post: http://lists.isocpp.org/core/2026/01/19209.php <http://lists.isocpp.org/core/2026/01/19209.php >
_______________________________________________
SG15 mailing list
SG15_at_[hidden] <mailto:SG15_at_[hidden] >
https://lists.isocpp.org/mailman/listinfo.cgi/sg15 <https://lists.isocpp.org/mailman/listinfo.cgi/sg15 >
Yeah, correctly.
> Alternatively, you could interpret this situation as a sign that you're putting too much in a single module; if the interface of the partition is so independent, perhaps it should be a separate module, e.g. mylib.net <http://mylib.net > instead of mylib:net.
I don’t think we should limit the number of partitions in a single module. It seems odd… e.g. within different modules, it is hard to have forward declarations.
> Chuanqi proposes to handle this by giving the implementation unit its own dummy partition name, and then wants a way to suppress BMI generation for that dummy partition. But this seems a bit like piling kludge on kludge to work around the lack of a way in the standard to specify an implementation unit for a specific partition.
Agreed generally except I don’t think it is a kludge (sorry if I misunderstand the word ‘kludge’, I looked up it in the dictionary). As I feel it is natural to do so… according to the wording of the spec, the so called implementation partition unit are implementation unit actually.
[module.unit]p2
> A module interface unit <http://eel.is/c++draft/module.unit#def:module_interface_unit > is a module unit whose module-declaration <http://eel.is/c++draft/module.unit#nt:module-declaration > starts with export-keyword <http://eel.is/c++draft/lex.pptoken#nt:export-keyword >; any other module unit is a module implementation unit <http://eel.is/c++draft/module.unit#def:module_implementation_unit >. <http://eel.is/c++draft/module.unit#2.sentence-1 >
And it looks like the spec lacks a term for the “module implementation unit” we’re talking now. The spec uses a sentense to describe it:
[module.unit]p8:
> A module-declaration <http://eel.is/c++draft/module.unit#nt:module-declaration > that contains neither an export-keyword <http://eel.is/c++draft/lex.pptoken#nt:export-keyword > nor a module-partition <http://eel.is/c++draft/module.unit#nt:module-partition > implicitly imports the primary module interface unit of the module as if by a module-import-declaration <http://eel.is/c++draft/module.import#nt:module-import-declaration >. <http://eel.is/c++draft/module.unit#8.sentence-1 >
Or maybe we can ask some guiding questions to make the discussion clea:
(1) Is it a problem now? (Change any interface unit will force the recompilation for all module implmentation units which are not a partition).
(2) If the answer to (1) is yes, is it a standard defect? If not, it shoudl be a defect of the build system.
(3) If the answert to (2) is yes, is it a wording defect or a design defect?
Thanks,
Chuanqi
------------------------------------------------------------------
From:core <core_at_[hidden]>
Send Time:Wed, Jan 14, 2026, 11:29
To:SG15<sg15_at_[hidden]>
CC:Jason Merrill<jason_at_[hidden]>; core<core_at_[hidden]>; Chuanqi Xu<chuanqi.xcq_at_[hidden]>
Subject:Re: [isocpp-core] [isocpp-sg15] [modules] wordings to allow build system to not always emit BMI for implementation partition units
On Wed, Jan 14, 2026 at 10:09 AM Chuanqi Xu via SG15 <sg15_at_[hidden] <mailto:sg15_at_[hidden] >> wrote:
> IMO, if you have a non-exported partition that you don't want exported,
remove the partition name. It can (must) then be listed outside of a
`CXX_MODULES` file set and won't make a BMI (whatever the costs may be).
The standard already has a mechanism to do the "part of a module, but
not making a BMI". Why do we need another subflavor of translation unit?
IIUC the issue is that if you have a TU that implements the interface of a particular partition, and only needs to import that partition, removing the partition name creates an interface dependency on the entire module, resulting in unnecessary rebuilding if a different interface partition changes.
Chuanqi proposes to handle this by giving the implementation unit its own dummy partition name, and then wants a way to suppress BMI generation for that dummy partition. But this seems a bit like piling kludge on kludge to work around the lack of a way in the standard to specify an implementation unit for a specific partition.
Alternatively, you could interpret this situation as a sign that you're putting too much in a single module; if the interface of the partition is so independent, perhaps it should be a separate module, e.g. mylib.net <http://mylib.net > instead of mylib:net.
This is the problem. It then requires the users to pay for the additional cost for generating BMIs. In some degree, it violates the zero-abstraction rule.
I can understand that CMake didn’t optimize this due to human resources or what ever reasons. But I think we need to be on the same page that we should allow it.
> Sure, if the build system can determine that an importable module unit isn't ever actually imported, then it can optimize away building the BMI.
This seems like an "as-if" issue, unobservable by a conforming program. The standard doesn't say anything about build system artifacts.
OTOH, BMI generation seems like a small overhead as a side effect of compilation, so it's unclear to me why avoiding it is a high priority.
Thanks for clarification. I don’t think it is a high priority. But I do think it is a problem of CMake’s implementation. And a cmake dev says the root cause is the spec wording. That’s why I sent this.
Thanks,
Chuanqi
------------------------------------------------------------------
From:core <core_at_[hidden] <mailto:core_at_lists.isocpp.org >>
Send Time:Wed, Jan 14, 2026, 03:03
To:Chuanqi Xu<chuanqi.xcq_at_[hidden] <mailto:chuanqi.xcq_at_[hidden] >>
CC:Ben Boeckel<ben.boeckel_at_[hidden] <mailto:ben.boeckel_at_[hidden] >>; core<core_at_[hidden] <mailto:core_at_[hidden] >>; SG15<sg15_at_[hidden] <mailto:sg15_at_[hidden] >>; Jens Maurer<jens.maurer_at_[hidden] <mailto:jens.maurer_at_[hidden] >>
Subject:Re: [isocpp-core] [modules] wordings to allow build system to not always emit BMI for implementation partition units
On Tue, Jan 13, 2026 at 11:19:32 +0800, Chuanqi Xu wrote:
> As the author of CMake modules and who said the current wording has a
> bug/defect, would you like to comment to explain why do you think the
> current wording has a bug/defect for it?
> CC Jens as the chair of CWG.
This was not me (I am `mathstuf` on Reddit). It is, however, a fellow
Kitwarean. He's not available right away, so I am speaking for myself
here based on what he wrote.
From Chuanqi's blog post:
> However, in practice, there is a small issue for CMake users with this
> approach. Currently, CMake requires all module implementation
> partition units to be listed in CXX_MODULES_FILES, which causes CMake
> to generate a BMI for each of them. This is a waste of time. In our
> example, network.cpp, common.cpp, and util.cpp are designed not to be
> imported by any other unit, a fact that the programmer can guarantee
> and intends.
From linked Reddit reply:
> As discussed upstream, this is a standard bug and there's unlikely to
> be any movement on it unless something changes in the standard.
>
> The standard has no way to advertise a "non-exporting" partition unit.
> It is assumed all partition units export, thus all partition units
> must generate a BMI. Notably, clang makes the same assumption whenever
> it sees a .cppm extension.
>
> The MSVC behavior (absent /internalPartition) is simply broken and
> non-conforming
IMO, if you have a non-exported partition that you don't want exported,
remove the partition name. It can (must) then be listed outside of a
`CXX_MODULES` file set and won't make a BMI (whatever the costs may be).
The standard already has a mechanism to do the "part of a module, but
not making a BMI". Why do we need another subflavor of translation unit?
From Chuanqi's Reddit reply:
> For build system, my confusion part is, in bazel, it works fine if we
> put the module unit in the `srcs` field instead of the
> `module_interface` field. Given the support of modules in bazel
> generally follows cmake, I don't understand why cmake can't make the
> same behavior.
CMake sees that the scanner says "makes a BMI named X", compares against
its notes that it isn't expecting a BMI and assumes user error.
--Ben
_______________________________________________
Core mailing list
Core_at_[hidden] <mailto:Core_at_lists.isocpp.org >
Subscription: https://lists.isocpp.org/mailman/listinfo.cgi/core <https://lists.isocpp.org/mailman/listinfo.cgi/core >
Link to this post: http://lists.isocpp.org/core/2026/01/19209.php <http://lists.isocpp.org/core/2026/01/19209.php >
_______________________________________________
SG15 mailing list
SG15_at_[hidden] <mailto:SG15_at_[hidden] >
https://lists.isocpp.org/mailman/listinfo.cgi/sg15 <https://lists.isocpp.org/mailman/listinfo.cgi/sg15 >
Received on 2026-01-14 03:45:31
