|
28 | 28 | // freestanding posix / arch-default the same one token, `-D__unix__`, for the |
29 | 29 | // same reason: nothing here defines it either |
30 | 30 | // Windows posix / arch-default Cygwin-flavoured: `--target=x86_64-pc-cygwin`, |
31 | | -// `__CYGWIN__`/`__CYGWIN32__` STAY DEFINED (see |
32 | | -// the note below the table — this is a design |
33 | | -// revision, not the original §3.3 text) |
| 31 | +// plus `-U__CYGWIN__ -U__CYGWIN32__` (see |
| 32 | +// the note below the table — measurement |
| 33 | +// returned this to the original §3.3 text) |
34 | 34 | // * builtins = iso turn off the platform-C-library idioms the |
35 | 35 | // code generator assumes (§3.2.1) — Apple's |
36 | 36 | // `memset_pattern16` is the one measured case |
|
70 | 70 | // identity links exactly like one compiled under the MinGW one. Only the |
71 | 71 | // preprocessor saw a different environment; the linker never has to know. |
72 | 72 | // |
73 | | -// `__CYGWIN__`/`__CYGWIN32__` ARE NOT REMOVED, AND THE FIRST VERSION OF THIS |
74 | | -// MODULE GOT THAT WRONG. §3.3's original text called for `-U__CYGWIN__ |
75 | | -// -U__CYGWIN32__` on the reasoning that a real Cygwin userland is not in the |
76 | | -// graph. A first reading of the openkal-musl spike's libunwind build failure |
77 | | -// blamed a missing `__CYGWIN__` branch in libunwind itself; reading the |
78 | | -// vendored source shows that is wrong — upstream libunwind has no such |
79 | | -// branch, so defining it there would have changed nothing (the actual break |
80 | | -// was a downstream package selecting on `_WIN32` and is being fixed there). |
81 | | -// The reason to keep them defined is narrower and still real: third-party |
82 | | -// portable code that has to know the OBJECT FORMAT — as opposed to which C |
83 | | -// environment or which platform API — has no name for "PE format with a |
84 | | -// POSIX-presenting C environment" other than `__CYGWIN__`, and such code |
85 | | -// cannot be patched the way this ecosystem's own packages can. The cost is |
86 | | -// symmetric: a library that reaches for `__CYGWIN__` may also reach for a |
87 | | -// real Cygwin interface (`sys/cygwin.h`, `cygwin_conv_path`) that does not |
88 | | -// exist here. This is a TRADE-OFF for the 30-member measurement to settle — |
89 | | -// if defining it produces more new failures than it fixes, the answer flips |
90 | | -// — not a fact this module is asserting as closed. |
| 73 | +// `__CYGWIN__`/`__CYGWIN32__` ARE REMOVED, AND THIS MODULE HAS HELD BOTH |
| 74 | +// ANSWERS. The first version removed them; a second kept them, on the |
| 75 | +// argument that third-party code needing to know the OBJECT FORMAT has no |
| 76 | +// other name for "PE format with a POSIX-presenting C environment". That |
| 77 | +// version wrote the condition for changing its mind: a trade-off "for the |
| 78 | +// 30-member measurement to settle — if defining it produces more new |
| 79 | +// failures than it fixes, the answer flips". |
| 80 | +// |
| 81 | +// The measurement settled it (2026-09-20, 60 member-target combinations). |
| 82 | +// Keeping them cost four members, each stopping at `#include <windows.h>` |
| 83 | +// reached through `#if defined(_WIN32) || defined(__CYGWIN__)`; none failed |
| 84 | +// for want of the macro. Four against zero, so the answer flipped. |
| 85 | +// |
| 86 | +// What the second version got wrong is worth keeping, because it is not |
| 87 | +// specific to this macro. The name was borrowed to mean "the object format |
| 88 | +// is PE". Upstream uses it to mean "Win32 is available" — mimalloc says so in |
| 89 | +// the guard itself, and sqlite3 puts it in the `SQLITE_OS_WIN` detection set. |
| 90 | +// A BORROWED NAME MEANS WHAT THE LENDER'S HISTORY MADE IT MEAN, not what the |
| 91 | +// borrower intended. The object-format question therefore keeps no macro at |
| 92 | +// all: a package asks `cfg(os = "windows")`. If some day a third party can |
| 93 | +// only ask it in the preprocessor, mcpp defines a name of its own. |
91 | 94 | export module mcpp.toolchain.cenv; |
92 | 95 |
|
93 | 96 | import std; |
@@ -286,16 +289,38 @@ inline std::expected<Realisation, std::string> realise( |
286 | 289 | "on x86_64 only; this arch has no verified " |
287 | 290 | "substitute triple"); |
288 | 291 | // `--target=x86_64-pc-cygwin`, on the COMPILE line only (module |
289 | | - // header above). `__CYGWIN__`/`__CYGWIN32__` are LEFT AS THE |
290 | | - // TRIPLE SUBSTITUTION DEFINES THEM — not undefined (see the |
291 | | - // module header's note: portable third-party code that needs to |
292 | | - // know the object format has no other name for "PE format, |
293 | | - // POSIX-presenting environment", and this is a trade-off for the |
294 | | - // 30-member measurement, not a settled fact). |
| 292 | + // header above), AND `__CYGWIN__`/`__CYGWIN32__` UNDEFINED ON TOP |
| 293 | + // OF IT. The triple is what suppresses `_WIN32`, gives `__unix__` |
| 294 | + // and gives LP64; the two `-U` tokens remove the one thing the |
| 295 | + // triple carries that this environment cannot honour. |
| 296 | + // |
| 297 | + // THE MEASUREMENT THIS WAS LEFT TO HAS SETTLED IT (2026-09-20, 60 |
| 298 | + // member-target combinations on the published graph). Defining |
| 299 | + // them cost four members --- archive, sqlite3, mimalloc, c-ares |
| 300 | + // --- each stopping at `#include <windows.h>` reached through a |
| 301 | + // guard of the shape `#if defined(_WIN32) || defined(__CYGWIN__)`. |
| 302 | + // Nothing in the same run failed for want of the macro. The |
| 303 | + // module header's condition was "if defining it produces more new |
| 304 | + // failures than it fixes, the answer flips": four against zero. |
| 305 | + // |
| 306 | + // Upstream says plainly what it means by the name. mimalloc: |
| 307 | + // `// we use windows locks on cygwin, but otherwise treat it at |
| 308 | + // unix`. sqlite3 lists it in the `SQLITE_OS_WIN` detection set and |
| 309 | + // then includes `windows.h`. The name asserts WIN32 IS AVAILABLE, |
| 310 | + // not "the object format is PE" --- a borrowed name means what the |
| 311 | + // lender's history made it mean, whatever we intended by it. |
| 312 | + // |
| 313 | + // The object-format question keeps no macro. A package asks |
| 314 | + // `cfg(os = "windows")`, which needs none. Should measurement ever |
| 315 | + // show third-party code that can only ask it in the preprocessor, |
| 316 | + // the answer is a name mcpp defines itself, not one it borrows. |
295 | 317 | r.tokens.push_back("--target=x86_64-pc-cygwin"); |
| 318 | + r.tokens.push_back("-U__CYGWIN__"); |
| 319 | + r.tokens.push_back("-U__CYGWIN32__"); |
296 | 320 | r.expectDefined.push_back("__unix__"); |
297 | | - r.expectDefined.push_back("__CYGWIN__"); |
298 | 321 | r.expectUndefined.push_back("_WIN32"); |
| 322 | + r.expectUndefined.push_back("__CYGWIN__"); |
| 323 | + r.expectUndefined.push_back("__CYGWIN32__"); |
299 | 324 | cygwinIdentity = true; |
300 | 325 | } else if (decl.presents == CAbiPresents::Windows) { |
301 | 326 | // Already the base triple's own identity — nothing to add. |
|
0 commit comments