@@ -78,12 +78,21 @@ constexpr std::string_view origin_name(Origin o) {
7878// reading `c-abi musl` is not left to work out which row `gnu` belongs to.
7979enum class EnvAxis { Unknown, CLibrary, ObjectAbi, ObjectFormat };
8080
81- // The noun for an axis , as it appears in the report. Empty for `Unknown`,
81+ // The noun for a segment , as it appears in the report. Empty for `Unknown`,
8282// because a report that cannot name the axis says nothing rather than guessing.
83- inline std::string_view env_axis_noun (EnvAxis a) {
83+ //
84+ // ⚠️ THE VALUE, NOT ONLY THE AXIS. `gnu` and `msvc` sit on the same axis and
85+ // select opposite ABIs, so a noun fixed per axis would print "the Itanium C++
86+ // ABI" for an MSVC build. Naming the ABI rather than the axis is deliberate:
87+ // `Itanium` and `MSVC` appear in no row of the report, so neither can be
88+ // mistaken for a layer the way "the C++ ABI" would be.
89+ inline std::string_view env_axis_noun (EnvAxis a, std::string_view segment = {}) {
8490 switch (a) {
8591 case EnvAxis::CLibrary: return " a C library" ;
86- case EnvAxis::ObjectAbi: return " the object ABI" ;
92+ case EnvAxis::ObjectAbi:
93+ if (segment == " gnu" ) return " the Itanium C++ ABI" ;
94+ if (segment == " msvc" ) return " the MSVC C++ ABI" ;
95+ return " the object ABI" ;
8796 case EnvAxis::ObjectFormat: return " the object format" ;
8897 case EnvAxis::Unknown: break ;
8998 }
@@ -751,11 +760,23 @@ inline std::string format_report(const TargetSide& ts, std::string_view targetNa
751760 // READER IS LOOKING AT IT.
752761 //
753762 // `x86_64-windows-gnu` above a line reading `c-abi musl` is not a
754- // contradiction: on Windows `gnu` names the object ABI, and the row it
755- // actually corresponds to is `c++-abi`. But the report contains no row
756- // called `gnu`, so a reader maps it to the nearest thing that looks like a
757- // C library name and concludes the build disagrees with itself. Measured
758- // twice, by the same reader, on two different days.
763+ // contradiction. Measured on the artefact of exactly that build:
764+ //
765+ // imports ntdll, KERNEL32, SHELL32 — no msvcrt, no ucrtbase
766+ // `_Z…` symbols 4507
767+ // `?…` symbols 0
768+ //
769+ // The first line is why `c-abi musl` is honest: none of MinGW's C runtime
770+ // is linked. The other two are what `gnu` actually selected — the Itanium
771+ // C++ ABI rather than Microsoft's.
772+ //
773+ // ⭐ AND IT CORRESPONDS TO NO ROW OF THIS REPORT, WHICH IS THE POINT. The
774+ // five layers record who SUPPLIES each layer; `gnu` names a convention the
775+ // OBJECTS FOLLOW, and several layers must agree on it. Pointing the reader
776+ // at `c++-abi libc++` would be a second wrong answer: libc++ is one
777+ // implementation of the standard library, libstdc++ is another, and both
778+ // sit on the Itanium ABI. The gloss therefore names the ABI itself, whose
779+ // name appears in no row and so cannot be mistaken for one.
759780 //
760781 // A warning would be wrong — it would fire on every legitimate MinGW build
761782 // and would say something false. A noun on the head line is not a
@@ -770,8 +791,9 @@ inline std::string format_report(const TargetSide& ts, std::string_view targetNa
770791 && !ts.requestedCAbi .empty ()
771792 && !ts.cAbi .absent () && ts.cAbi .fromGraph ()
772793 && ts.cAbi .interfaceName != ts.requestedCAbi ) {
773- head += std::format (" ({} names {}, not a C library)" ,
774- ts.requestedCAbi , env_axis_noun (ts.envAxis ));
794+ head += std::format (" ({} selects {}, not a C library)" ,
795+ ts.requestedCAbi ,
796+ env_axis_noun (ts.envAxis , ts.requestedCAbi ));
775797 }
776798 head += ' \n ' ;
777799
0 commit comments