pub struct Sysroot { /* private fields */ }Expand description
One target’s sysroot: where its headers are, where its link inputs are, and where the record of what they are is.
Constructed rather than discovered. Nothing here checks that any of these directories exists, because the caller that is about to produce a sysroot needs the same answer as the caller that is about to read one, and a constructor that failed for an absent directory would give the first one nothing to create.
Implementations§
Source§impl Sysroot
impl Sysroot
Sourcepub fn in_cache(cache: &Path, target: TargetTuple) -> Self
pub fn in_cache(cache: &Path, target: TargetTuple) -> Self
The sysroot for this target inside this cache directory.
The path is <cache>/sysroots/<canonical tuple>. Two hosts running this with the same
cache directory and the same target get the same path, which is what makes the tuple a
cache key and is the reason spec/cross-compile/03-target-model.md section 3.2 admits a
field only when it changes how a call is made or a struct is laid out.
Sourcepub fn at(root: PathBuf, target: TargetTuple) -> Self
pub fn at(root: PathBuf, target: TargetTuple) -> Self
A sysroot rooted at a directory the user named, with --sysroot or -isysroot.
The layout below the root is the same, so a user who assembled a tree the way we lay one
out is served by every other method here. A user who did not is served by
Options::sysroot, which replaces step 3 of section 8.5
wholesale rather than assuming a shape.
Sourcepub const fn target(&self) -> TargetTuple
pub const fn target(&self) -> TargetTuple
The target this sysroot is for.
Sourcepub fn cache_key(&self) -> String
pub fn cache_key(&self) -> String
The cache key, which is the canonical spelling of the tuple.
The whole tuple and not a summary of it. A key that dropped env_version would serve a
sysroot built against glibc 2.28 to a target that pinned 2.34, and the failure would be a
missing symbol at link time on one machine and not on another.
Sourcepub fn arch_include(&self) -> PathBuf
pub fn arch_include(&self) -> PathBuf
The headers that differ by architecture, which are searched before the generic ones.
Section 8.3’s second split. For musl this is bits/, which is a few dozen small files
against a few hundred shared ones, so the copy per architecture is cheap and the
alternative of one whole tree per architecture is not.
Sourcepub fn generic_include(&self) -> PathBuf
pub fn generic_include(&self) -> PathBuf
The headers every architecture shares, which is almost all of them.
Sourcepub fn includes(&self) -> Vec<PathBuf>
pub fn includes(&self) -> Vec<PathBuf>
The libc’s include directories, in search order, most specific first.
Two rather than four. A Linux target also needs the kernel’s own headers, which are
Kernel and are not under this root, because they are the same files for every target
that shares an architecture and carrying a copy of them per tuple is nine megabytes times
the size of the table.
Sourcepub fn lib(&self) -> PathBuf
pub fn lib(&self) -> PathBuf
The link inputs: the start files, the libc archive or its generated stubs, and the compiler’s own runtime for this target.
Sourcepub fn manifest_path(&self) -> PathBuf
pub fn manifest_path(&self) -> PathBuf
The manifest naming every input with its source, its hash and its licence.
A file rather than a directory, and at the top rather than beside the libraries, because the thing a person does with it is read it first.
Sourcepub fn header_arch(&self) -> &'static str
pub fn header_arch(&self) -> &'static str
The name the target’s libc gives to its per architecture header directory.
Not the architecture component of the canonical tuple, which carries a baseline the headers
do not care about: armv7a-linux-musleabihf and armv5te-linux-musleabi read the same
arm directory, because a header does not know which instructions the chip has. 32-bit x86
is i386 in musl’s source tree whatever the tuple spells it.
§Why the libc is part of the answer
The two libcs do not split their headers at the same place, and the name has to follow the libc rather than a scheme of ours, because the producer installs what the libc’s own build system installs and the compiler has to look where that put it.
musl splits per architecture and per ABI, which is what arch/ in its source tree is, so
x86_64, i386 and x32 are three directories. glibc splits per architecture family and
handles the rest inside the files: one x86 directory serves i386, x86-64 and x32, and 22
of the 31 files in its bits/ branch on __x86_64__, __ILP32__ or __WORDSIZE to do it,
starting with bits/wordsize.h. Checked against Zig 0.16, which ships twelve glibc
directories named after families and seventeen musl directories named after architectures.
§The rule this is here to enforce
An ILP32 ABI on a 64-bit architecture cannot read the LP64 headers. Every type that carries
a pointer or a long is a different size, and x86_64-linux-gnux32 is the row that proves
it. For musl that is a separate directory, which is what the suffix below is. For glibc it
is a branch inside glibc’s own files, so the directory is shared and the thing that checks
it is section 8.4’s structural equivalence corpus rather than a path.