Expand description
One header, merged across every release that has it.
Design: spec/cross-compile/08-sysroots.md section 8.3. The shape of the answer is Zig’s
generic-glibc, which is one tree with the per-version differences written inside the files as
conditionals on __GLIBC_MINOR__, and the technique for deriving one rather than maintaining it
by hand is ziglang/universal-headers, which document 01.2 records as the state of the art and
as unfinished.
§What a merge is allowed to do
Write text that every release shipped, and conditionals around the text that only some of them
shipped. That is all. It never edits a declaration, never reflows anything and never invents a
line, with one exception that is not an exception so much as a requirement: glibc’s own
definition of __GLIBC_MINOR__ has to go, because the compiler is what defines it in a merged
tree, and what replaces it is a check that somebody did.
§The two ways cutting a file up can break it
A conditional put in the wrong place turns a working header into one that does not compile, or worse into one that compiles differently, so both ways are checked rather than avoided by being careful.
The first is a piece that cannot be split, which is a macro or a directive continued with a
backslash, or a line whose trailing comment closes further down. norm::pieces is what makes
that impossible: the smallest thing the merge can put a conditional between is a logical line.
The second is a piece that is part of the file’s own conditional. A region that contains an
#endif whose #if is above it, or an #else belonging to an #if above it, cannot be wrapped
in an #if of ours: our #endif would close theirs, or their #else would become ours.
The answer to the second one is to make the region bigger until it holds the whole of whatever it
was reaching into, and the region says which way to grow rather than being searched for. A branch
that closes an #if from above needs the text above it, a branch that leaves an #if of its own
open needs the text below it, and growing stops as soon as no branch reaches out. Growing
upward takes back a region already decided, which is the one place a decision here is
reconsidered. A file where the region grows to the whole file is one copy per release, which is
how this started and is still the answer for a file whose releases disagree about where their own
conditionals are.
§Why it reads its own output back
Because the only statement worth making about a merged tree is that it is the releases it was merged from, and the way to say that is to take it apart again. Every file, for every release that has it, is evaluated at that release’s version and held against what that release shipped. A merge that cannot reproduce its inputs is a bug in this file, and the check runs before the tree is written rather than in a test over a fixture, because the fixture that matters is glibc.
Structs§
- Merged
- One merged header.
Enums§
- Kind
- What the merge had to do to one file.
Constants§
- GUARD
- What replaces glibc’s own definition of the version macro.
Functions§
- one
- Merges one header.
textshas one entry per release,Nonewhere that release does not have it.