Skip to main content

Module layout

Module layout 

Source
Expand description

The directory layout of one target’s sysroot, and the cache key that names it.

Design: spec/cross-compile/08-sysroots.md sections 8.2 and 8.3.

§Why the directories are split the way they are

Section 8.3 is about a multiplication. Headers are naively arch x os x libc x libc-version trees, which for glibc alone is eight architectures times six versions and several hundred megabytes, and spec/cross-compile/13-distribution.md has a size budget that number destroys.

The fix is two splits that turn the product into a sum. The per version differences go inside the files as #if __GLIBC_MINOR__ >= n, so one tree serves every version. The per architecture differences stay in directories, because they are whole files rather than lines, but only for the small part of a libc that has any: bits/ and a handful of others. Everything else is one copy.

That is why a sysroot here has two include directories rather than one. Sysroot::arch_include holds the files that differ by architecture and is searched first, and Sysroot::generic_include holds the copy that every architecture shares.

A Linux target searches four directories and not two, because the kernel’s headers are a second pair with the same split and a different owner. They are Kernel, their root is the cache rather than a sysroot, and the order is the libc’s two and then the kernel’s two, which is the order zig cc -E -v prints for a glibc target. linux/ and asm/ are nine megabytes of files that are the same for every target, so one tree is shared and only asm/ is copied per architecture.

§Why the root is a function of the tuple

spec/cross-compile/02-the-goal.md claim 5 asks for byte identical output from different hosts. A sysroot that lands in a directory named after the host, or after the day it was built, or after a hash of an absolute path, breaks that before anything is compiled. So the root is the cache directory the caller chose plus the canonical spelling of the tuple, and nothing else.

The canonical spelling is the key rather than a hash of it because it is already unique, it is already a legal directory name, and a cache a person can read is a cache a person can debug. It carries the whole ten field model, so x86_64-linux-gnu and x86_64-linux-gnu.2.28 are different directories, which is the point of env_version being in the tuple at all.

It is not the hash of the contents either, which is what spec/cross-compile/13-distribution.md section 13.2 asked for until tamnd/rucc#1021 settled it. A name cannot carry one: this function is what the producer calls to find out where to write files it has not written yet, so there are no contents to hash when the question is asked. The hash lives in the record instead, which is crate::Manifest::digest, and the one thing the name has to be is the same on two hosts.

Structs§

GlibcSkew
A glibc release the bundled tree cannot serve, and the release the tree is.
Kernel
The kernel’s own headers, which are not the libc’s and are shared by every target that can read them.
Sysroot
One target’s sysroot: where its headers are, where its link inputs are, and where the record of what they are is.

Constants§

BUNDLED_GLIBC
The glibc our bundled header tree is derived from.

Functions§

bundled_glibc_minor
The __GLIBC_MINOR__ a target gets when it is compiled against the bundled glibc tree.
can_be_bundled
Whether we can produce a sysroot for this target without the user fetching anything.