C++ Logo


Advanced search

Re: Questions about wording and design intention for header units and ideas

From: Gabriel Dos Reis <gdr_at_[hidden]>
Date: Fri, 19 May 2023 18:39:51 +0000
Whether a header is importable is really a reflection of use. What the standard is saying is that certain standard headers can be used in certain way, which is a constraint on implementation in certain way. For the ecosystem to require an in-source pragma will be counter to the spirit of the feature, and practically useless. Within a project with given set of configuration macros, I should be able to say “import <unistd.h>;” without the OS vendor having to put in a pragma.

A configuration file of some sort makes sense, and such configuration can capture dependency on the project.

-- Gaby

From: SG15 <sg15-bounces_at_[hidden]> On Behalf Of Tom Honermann via SG15
Sent: Thursday, May 18, 2023 12:19 PM
To: 许传奇(夜灯) <chuanqi.xcq_at_[hidden]>; Iain Sandoe via SG15 <sg15_at_[hidden]>
Cc: Tom Honermann <tom_at_honermann.net>
Subject: Re: [SG15] Questions about wording and design intention for header units and ideas

Hi, Chuanqi.

I agree with your interpretation of the standard. Since the standard is not concerned with build systems, implementation-defined was pretty much the only option for specifying which header files are importable (without introducing additional syntax).

I think these concerns should be addressed by SG15. An implementation dependent configuration file like you suggest is one way forward. Another would be for SG15 to specify a #pragma directive or magic comment (similar to the "-*- coding: <encoding name> -*-" comment that some editors recognize as an indication of source code character encoding; e.g. a "// importable-header" comment; I'm not suggesting this is a good idea).

Since most header files meet the importable header rules, an argument could be made for requiring an opt-out instead of (or in addition to) an opt-in.

The bottom line is, the information about which headers are intended to be importable has to come from somewhere and, as you indicate, if implementors don't rally around a common source for that information, they'll each make their own choices and scanning tools will have to grow features/options to cope with that.

I know people hate it, but in my opinion, implicitly built (and cached; using the importing TU's macro environment) BMIs are the way to go for header units. This matches what happens today for inclusion of header files. Yes, that means the same old ODR concerns that we've had forever with header files. That doesn't bother me. This avoids, I think, most of the difficulties that Daniel has been wresting with.


On 5/17/23 2:16 AM, 许传奇(夜灯) wrote:
Hi Experts,

    In a recent private meeting, we talked about the wording and the design intention for header units.
And the implementors get confused about how to implement header units again and we're wondering
if it is already specified in current wording clearly or what is the design intentions.

   First, the motivation example:

// a.cpp
import "foo.h";

// b.cpp
#define M 43
import "foo.h"

   The question is, for build systems, how can they know if they should use the same BMI for these
2 imports. Since **currently** the build systems don't have a **good** method to know whether a
macro is interesting to a specific file.

   Then we're looking for the wording to find solutions. (Tom suggested us to send this to CWG, but I guess
I found the concrete wording.) [module.import]p5 said (http://eel.is/c++draft/module.import#5):

> Given two such module-import-declarations:
> - if their header-names identify different headers or source files ([cpp.include]), they import distinct header units;
> - otherwise, if they appear in the same translation unit, they import the same header unit;
> - otherwise, it is unspecified whether they import the same header unit.

  So it looks like it is unspecified in the wording intentionally. Then we're curious about what's the proposed solution
at the beginning.

  BTW, [module.import]p5 also introduces the implementation-defined concept "importable header", which is confusing
to developers and users.


(The section is about my personal thought about header units. The section may be a little not closed to the topic)

I can roughly understand that the designer didn't want to bring too much limitations to the implementors.
(Or is it the reason that it is not good to insert module map like things into the formal wordings.)

But the consequence is that the C++ ecosystem is going to a more breaking state. For example, MSVC (or MSBuild?)
introduces header-units.json (https://learn.microsoft.com/en-us/cpp/build/reference/header-unit-json-reference?view=msvc-170).
And GCC has module map for named modules (I am not sure about gcc's state for header units). Clang has non-standard clang module
maps and doesn't have a solution for header units. It looks like things are not going right.

And I think a module map like thing is necessary for header units. For example, we can have header unit map to records the implementable
headers and the interesting macros. Maybe something like:

     "importable-headers": {
           "foo.h": ["Interesting Macro1", "Interesting Macro2", ...],
           "bar.h": [....]

Then it solves the two issues raised in the mail:
(1) We know which headers are importable: except STL headers, only the headers specified in the header unit map
are importable.
(2) We know whether or not we should reuse the same BMI for header units: we can reuse the BMI for the header units
for which the interesting macro state and value are the same.

I heard there was a decision to not make module map standard and I agree it is somewhat weird to have things like module map
in the current wordings. But given we're going to have C++ ecosystem standard, is it possible to have a standard header unit map
(or module map)?



Received on 2023-05-19 18:39:55