C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Revising #pragma once

From: Gašper Ažman <gasper.azman_at_[hidden]>
Date: Fri, 30 Aug 2024 11:52:50 +0100
Well:
- 3p libraries each have their own thing, of course, but they have an
interest in keeping it reasonable and deconflicted and I bother them if
their include guards aren't unique
- 1p, we have a modified bloomberg-style scheme (thanks Lakos) where we do
INCLUDED_{company}_{full_path_to_header} where the paths are globally
unique, and I have a linter that autofixes it so if you do #pragma once it
just gets replaced, and if you copy-paste it somewhere else you get a fixit.

This solved A LOT of build breakages, and was a prerequisite for getting
cloud builds working at all.

So, yeah, I will strongly oppose any standardization of #pragma once on a
"same file" basis; C++ is more and more a "large systems" language, because
small projects can choose Rust and be fine. #once INCLUDE_GUARD_SLUG solves
all the annoyance of 3-lines for one feature and doesn't have same-file
issues.

On Fri, Aug 30, 2024 at 11:47 AM Tiago Freire <tmiguelf_at_[hidden]> wrote:

> And what does "aware of the global namespacing" mean in practice?
>
> ------------------------------
> *From:* Gašper Ažman <gasper.azman_at_[hidden]>
> *Sent:* Friday, August 30, 2024 12:22:14 PM
> *To:* Tiago Freire <tmiguelf_at_[hidden]>
> *Cc:* std-proposals_at_[hidden] <std-proposals_at_[hidden]>
> *Subject:* Re: [std-proposals] Revising #pragma once
>
> Because my linter is aware of the global namespacing of libraries and can
> fix stuff *before they get into the source control structure*. My build
> tools have to deal with build outputs, not sources. Substantially different
> thing.
>
> On Fri, Aug 30, 2024 at 11:20 AM Tiago Freire <tmiguelf_at_[hidden]>
> wrote:
>
>> > This is why we have linters. At least that's a problem I can fix and
>> diagnose; I can't fix #pragma once.
>>
>>
>>
>> If your linter could figure that out, why your compiler wouldn’t?
>>
>>
>>
>> *From:* Gašper Ažman <gasper.azman_at_[hidden]>
>> *Sent:* Friday, August 30, 2024 12:16 PM
>> *To:* Tiago Freire <tmiguelf_at_[hidden]>
>> *Cc:* std-proposals_at_[hidden]
>> *Subject:* Re: [std-proposals] Revising #pragma once
>>
>>
>>
>> This is why we have linters. At least that's a problem I can fix and
>> diagnose; I can't fix #pragma once.
>>
>>
>>
>> On Fri, Aug 30, 2024 at 11:13 AM Tiago Freire <tmiguelf_at_[hidden]>
>> wrote:
>>
>> How do you ensure that your “INCLUDE_GUARD_STRING_YOU_CANNOT_OMIT” is
>> unique across different libraries?
>>
>> Given standard practice, if the headers the same name, they are very
>> likely going to have the same “INCLUDE_GUARD_STRING_YOU_CANNOT_OMIT”. And
>> we are back to the same problem you just describe.
>>
>>
>>
>> Now multiply this by, “I renamed the file and forget to change it”, “I
>> copy pasted a template header file and forgot to change the
>> INCLUDE_GUARD_STRING_YOU_CANNOT_OMIT, and wasn’t caught in review because
>> nobody looks at that”.
>>
>>
>> You know what they do not have? The same filepath.
>>
>> If I don’t have to write it, I don’t have to worry about these problems.
>>
>>
>>
>>
>>
>> *From:* Gašper Ažman <gasper.azman_at_[hidden]>
>> *Sent:* Friday, August 30, 2024 12:06 PM
>> *To:* std-proposals_at_[hidden]
>> *Cc:* Tiago Freire <tmiguelf_at_[hidden]>
>> *Subject:* Re: [std-proposals] Revising #pragma once
>>
>>
>>
>> Simple as in #once INCLUDE_GUARD_STRING_YOU_CANNOT_OMIT?
>>
>>
>>
>> On Fri, Aug 30, 2024 at 11:04 AM Tiago Freire via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>>
>> I agree, bit-wise comparison is not the way to go, that’s why no compiler
>> does this.
>>
>> There’s no need to over-engineer this. Keep it simple.
>>
>>
>>
>>
>>
>> *From:* Std-Proposals <std-proposals-bounces_at_[hidden]> *On
>> Behalf Of *Gašper Ažman via Std-Proposals
>> *Sent:* Friday, August 30, 2024 11:51 AM
>> *To:* marcinjaczewski86_at_[hidden]
>> *Cc:* Gašper Ažman <gasper.azman_at_[hidden]>;
>> std-proposals_at_[hidden]; Tom Honermann <tom_at_[hidden]>
>> *Subject:* Re: [std-proposals] Revising #pragma once
>>
>>
>>
>> If you knew up-front you wouldn't do it :).
>>
>>
>>
>> This happens though. There are people who generate code - whole include
>> trees - and for plugins they end up looking very very similar or identical.
>> And then as the build engineer my users complain that "their build doesn't
>> work on the cloud build environment" and I have to somehow *find their bug*.
>>
>>
>>
>> Think about it. How the hell do you diagnose this silent noninclusion?
>>
>>
>>
>> On Fri, Aug 30, 2024 at 9:30 AM Marcin Jaczewski <
>> marcinjaczewski86_at_[hidden]> wrote:
>>
>> pt., 30 sie 2024 o 01:20 Gašper Ažman via Std-Proposals
>> <std-proposals_at_[hidden]> napisał(a):
>> >
>> > Darlings,
>> >
>> > byte-identical is just plain incorrect. Consider.
>> >
>> > [library1/public.hpp]
>> > #pragma once
>> > #include "utils.hpp"
>> >
>> > [library1/utils.hpp]
>> > class lib1 {};
>> >
>> > library2/public.hpp
>> > #pragma once
>> > #include "utils.hpp"
>> >
>> > [library2/utils.hpp]
>> > class lib2 {};
>> >
>> > [main.cpp]
>> > #include "library1/public.hpp"
>> > #include "library2/public.hpp" # boom, library2/utils.hpp does not get
>> included
>> >
>> > same-contents also means same-relative-include-trees. Congratulations.
>> >
>>
>> Question is do you know upfront that files are problematic?
>> Then we could do something like this:
>> a) we only consider normalized paths
>> b) use have option to add path mappings that are used in path comparison
>>
>> Like:
>>
>> We have folders `libs/fooV1` and `libs/fooV2`. Both folders are symlinks
>> but by default when compiler load `libs/fooV1/bar.h` and
>> `libs/fooV2/bar.h`
>> the compiler considers them as separate files even when they are the same
>> file.
>> Now we add compiler flag `-PI libs/fooV1:libs/fooV2` (similar to `-I`)
>> and now
>> when compiler load `libs/fooV1/foo.h` he consider it as if he load
>> `libs/fooV2/bar.h` and thus next loading of `libs/fooV2/bar.h` will be
>> blocked.
>>
>> And this should be ver dumb process it could be cases when
>> `libs/fooV1/bar.h`
>> and `libs/fooV2/bar.h` are unrelated but if you make specific maping it
>> will
>> override even diffrnet files. This could be useful to hacking some broken
>> includes like:
>>
>> ```
>> -PI hack/foo/bar.h:libs/fooV2/bar.h
>> ```
>>
>> and we can in our files do:
>>
>> ```
>> #include "hack/foo/bar.h"
>> #include "libs/fooV2/foo.h" // it will ignore `#include "bar.h"`
>> ```
>>
>> Could mechnism like this work on your build system?
>>
>> > On Fri, Aug 30, 2024 at 12:15 AM Jeremy Rifkin via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>> >>
>> >> > In this very thread there are examples showing why taking only the
>> content into account doesn't work but it was brushed off as "that can be
>> fixed".
>> >>
>> >> I'm sorry you feel I have brushed any presented examples off. I have
>> >> found them all immensely helpful for consideration. It's hard for me
>> >> to imagine times when you'd want the same include-guarded content
>> >> included twice, however I found the example of a "main header"
>> >> compelling. The example of a header that only defines macros you undef
>> >> is also not impractical.
>> >>
>> >> However, there are also compelling examples for filesystem identity.
>> >> Mainly the multiple mount point issue.
>> >>
>> >> I think both can be reasonable, however, I have been trying to
>> >> understand the most probable failure modes. While I originally
>> >> proposed a content-based definition, I do think a filesystem-based
>> >> definition is closer to current semantics and expectations.
>> >>
>> >> Jeremy
>> >>
>> >> On Thu, Aug 29, 2024 at 5:24 PM Breno Guimarães via Std-Proposals
>> >> <std-proposals_at_[hidden]> wrote:
>> >> >
>> >> > To add to that, the whole idea is to standardize standard practice.
>> If the first thing you do is to change spec to something else, then you're
>> not standardizing standard practice, you are adding a new feature that
>> inconveniently clashes with an existing one.
>> >> >
>> >> > In this very thread there are examples showing why taking only the
>> content into account doesn't work but it was brushed off as "that can be
>> fixed".
>> >> >
>> >> > None of this make sense to me.
>> >> >
>> >> >
>> >> > Em qui., 29 de ago. de 2024 18:59, Tiago Freire via Std-Proposals <
>> std-proposals_at_[hidden]> escreveu:
>> >> >>
>> >> >> Again, hashing content... totally unnecessary.
>> >> >>
>> >> >> There's no need to identify "same content" which as far as I can
>> see can be defeated by modifications that don't change the interpretation,
>> like spaces, which although not technically a violation of "same content"
>> it clearly defeats the intent.
>> >> >>
>> >> >> An include summons a resource, a pragma once bars that resources
>> from bey re-summonable. That's it. File paths should be more than enough.
>> >> >>
>> >> >> I'm unconvinced that the "bad cases" are not just a product of bad
>> build architecture, if done properly a compiler should never be presented
>> with multiple alternatives of the same file. And putting such requirements
>> on compilers puts an unnecessary burden on developers to support a scenario
>> that it is that is arguably bad practice.
>> >> >>
>> >> >> The argument is "prgma once" is supported everywhere it is good, we
>> should make it official in the standard, effectively no change to a
>> compiler should occur as a consequence.
>> >> >> If a change needs to occur, then in fact "your version" of what you
>> mean by "pragma once" is actually "not supported" by all the major
>> compilers.
>> >> >>
>> >> >> Current compiler support of "pragma once" and it's usage on cross
>> platform projects have a particular way of dealing with dependencies in
>> mind. That workflow works. It's pointless to have this discussion if you
>> don't understand that flow, and you shouldn't tailor the tool to a workflow
>> that doesn't exist to the detriment of all.
>> >> >>
>> >> >>
>> >> >> ________________________________
>> >> >> From: Std-Proposals <std-proposals-bounces_at_[hidden]> on
>> behalf of Jeremy Rifkin via Std-Proposals <std-proposals_at_[hidden]
>> >
>> >> >> Sent: Thursday, August 29, 2024 9:56:18 PM
>> >> >> To: Tom Honermann <tom_at_[hidden]>
>> >> >> Cc: Jeremy Rifkin <rifkin.jer_at_[hidden]>;
>> std-proposals_at_[hidden] <std-proposals_at_[hidden]>
>> >> >> Subject: Re: [std-proposals] Revising #pragma once
>> >> >>
>> >> >> Performance should be fine if using a content definition. An
>> implementation can do inode/path checks against files it already knows of,
>> as a fast path. The first time a file is #included it’s just a hash+table
>> lookup to decide whether to continue.
>> >> >>
>> >> >> Regarding the filesystem definition vs content definition question,
>> while I think a content-based definition is robust I can see there is FUD
>> about it and also an argument about current practice being a
>> filesystem-based definition. It may just be best to approach this as
>> filesystem uniqueness to the implementation’s ability, with a requirement
>> that symbolic links/hard links are handled. This doesn’t cover the case of
>> multiple mount points, but we’ve discussed that that’s impossible with
>> #pragma once without using contents instead.
>> >> >>
>> >> >> Jeremy
>> >> >>
>> >> >> On Thu, Aug 29, 2024 at 13:06 Tom Honermann <tom_at_[hidden]>
>> wrote:
>> >> >>>
>> >> >>> On 8/28/24 12:32 AM, Jeremy Rifkin via Std-Proposals wrote:
>> >> >>>
>> >> >>> Another question is whether the comparison should be post
>> translation
>> >> >>> phase 1.
>> >> >>>
>> >> >>> I gave this some thought while drafting the proposal. I think it
>> comes
>> >> >>> down to whether the intent is single inclusion of files or single
>> >> >>> inclusion of contents.
>> >> >>>
>> >> >>> Indeed. The proposal currently favors the "same contents" approach
>> and offers the following wording.
>> >> >>>
>> >> >>> A preprocessing directive of the form
>> >> >>> # pragma once new-line
>> >> >>> shall cause no subsequent #include directives to perform
>> replacement for a file with text contents identical to this file.
>> >> >>>
>> >> >>> The wording will have to define what it means for contents to be
>> identical. Options include:
>> >> >>>
>> >> >>> The files must be byte-for-byte identical. This makes source file
>> encoding observable (which I would be strongly against).
>> >> >>> The files must encode the same character sequence post translation
>> phase 1. This makes comparisons potentially expensive.
>> >> >>>
>> >> >>> Note that the "same contents" approach obligates an implementation
>> to consider every previously encountered file for every #include directive.
>> An inode based optimization can help to determine if a file was previously
>> encountered based on identity, but it doesn't help to reduce the costs when
>> a file that was not previously seen is encountered.
>> >> >>>
>> >> >>>
>> >> >>> Tom.
>> >> >>>
>> >> >>> Jeremy
>> >> >>>
>> >> >>> On Tue, Aug 27, 2024 at 3:39 PM Tom Honermann via Std-Proposals
>> >> >>> <std-proposals_at_[hidden]> wrote:
>> >> >>>
>> >> >>> On 8/27/24 4:10 PM, Thiago Macieira via Std-Proposals wrote:
>> >> >>>
>> >> >>> On Tuesday 27 August 2024 12:35:17 GMT-7 Andrey Semashev via
>> Std-Proposals
>> >> >>> wrote:
>> >> >>>
>> >> >>> The fact that gcc took the approach to compare file contents I
>> consider
>> >> >>> a poor choice, and not an argument to standardize this
>> implementation.
>> >> >>>
>> >> >>> Another question is whether a byte comparison of two files of the
>> same size is
>> >> >>> expensive for compilers.
>> >> >>>
>> >> >>> #once ID doesn't need to compare the entire file.
>> >> >>>
>> >> >>> Another question is whether the comparison should be post
>> translation
>> >> >>> phase 1. In other words, whether differently encoded source files
>> that
>> >> >>> decode to the same sequence of code points are considered the same
>> file
>> >> >>> (e.g., a Windows-1252 version and a UTF-8 version). Standard C++
>> does
>> >> >>> not currently allow source file encoding to be observable but a
>> #pragma
>> >> >>> once implementation that only compares bytes would make such
>> differences
>> >> >>> observable.
>> >> >>>
>> >> >>> Tom.
>> >> >>>
>> >> >>> --
>> >> >>> Std-Proposals mailing list
>> >> >>> Std-Proposals_at_[hidden]
>> >> >>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>> >> >>
>> >> >>
>> >> >> --
>> >> >> Std-Proposals mailing list
>> >> >> Std-Proposals_at_[hidden]
>> >> >> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>> >> >
>> >> > --
>> >> > Std-Proposals mailing list
>> >> > Std-Proposals_at_[hidden]
>> >> > https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>> >> --
>> >> Std-Proposals mailing list
>> >> Std-Proposals_at_[hidden]
>> >> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>> >
>> > --
>> > Std-Proposals mailing list
>> > Std-Proposals_at_[hidden]
>> > https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>>
>

Received on 2024-08-30 10:53:05