Expand description
Where a target’s headers and link inputs live, which directories are searched for them, and in what order they reach the linker.
Design: spec/cross-compile/08-sysroots.md, and section 8.5 for the rule this crate exists to
enforce.
§The claim this crate is responsible for
spec/cross-compile/02-the-goal.md claim 5 is byte identical output from different hosts for
the same target. It holds only because the search path rules make the libc header directory a
function of the target rather than of the machine, and that function is here.
So every answer in this crate is derived from a TargetTuple and from paths the caller
supplies. Nothing reads an environment variable, nothing looks at std::env::consts, and
nothing touches the filesystem. A host directory can only enter through
Options::host_include, which include_paths uses exactly once and only when the target
is the host, and that is checkable by reading one function.
§What is in here
Sysroot is the directory layout for one target: where its headers go, where its link inputs
go, and where the record of what they are goes. Its root is a function of a cache directory and
the tuple, which is what makes the tuple a cache key.
Kernel is the other half of a Linux target’s headers. linux/ and asm/ are the system
call interface rather than the C library, 31 of glibc’s installed headers and 3 of musl’s
include one of them, and they are the same files for every target that shares an architecture.
So they sit in the cache rather than in a sysroot and a Linux target searches four directories.
bundled_glibc_minor is the version half of the same tree. One tree serves every glibc
release, with the differences inside the files as #if __GLIBC_MINOR__ >= n, so the release is
what the target supplies and the compiler defines the macro. It answers None for every libc
that has no such macro and an error for a release newer than the tree, which is the one direction
that cannot be approximated.
include_paths is section 8.5 as an ordered list, with each entry saying which of the four
steps put it there. LinkLine is the start files, the libraries and the end files, in the
order a linker needs them, for either libc.
argv is spec/cross-compile/11-linking.md section 11.3: the whole linker command line as a
function of the target, the sysroot and what the user asked for. It is the same division as the
one above, one level up. LinkLine is what has to be linked, which is a fact about the target,
and argv is how that is spelled for a linker, which is a fact about the linker. Section 11.3
asks for a golden file per target and tests/link-lines is it, one file per target, regenerated
by cargo xtask link-lines and checked in CI.
Manifest is what a produced sysroot carries: every input with where it came from, its hash
and its licence. Two sysroots for the same target built on two hosts have the same manifest, and
comparing manifests is how that gets checked without comparing several thousand files.
Manifest::digest is the same comparison in one line, which is what the cache layout of
spec/cross-compile/13-distribution.md section 13.2 wanted a hash in a directory’s name for.
sha256 is how that digest is computed, and it is public because the digest is not the only
thing that needs it. An artifact a downloader just wrote is checked against the hash pinned in
the release before anything is unpacked, and the files that come out of it are checked against
the manifest inside it, which is section 13.8’s division of a fetch into the transport and the
part that decides whether the result is correct.
artifact is what a release pins: one sysroot artifact per target, by URL and by hash. It is
here rather than beside the fetch that uses it because the generator of the file below cannot
depend on the driver, and because a pin is a fact about a sysroot.
distribution is that table and Wall and the target table written out as one file, which is
what spec/cross-compile/13-distribution.md section 13.5 asks to ship beside the binary: for
every target, whether the sysroot for it is in the archive, is a download this release pins, is
behind a licence wall, or is ours to ship and not published yet.
Wall is section 13.4’s two licence walls as data. Apple’s SDK and Microsoft’s are the two
things in section 8.2’s table that are not ours to ship, so for those targets there is no bundled
tree, no artifact a release can pin, and a message that names the licence and the lawful ways to
get one instead of a message about a tree that has not been built yet.
§What is not in here
Nothing fetches. Downloading musl, verifying it and unpacking it is
spec/cross-compile/13-distribution.md, and the network policy it needs is that document’s
section 13.8: the bytes are moved by a downloader the machine already has, and the hash check,
the manifest and the rename into place are ours. None of those three is in this crate either.
What this crate settles is where the result goes and how it is searched, which is the part that
has to be decided before anything is worth downloading.
use rucc_sysroot::{Sysroot, LinkLine, LinkMode, argv};
use rucc_tuple::TargetTuple;
use std::path::Path;
let target: TargetTuple = "aarch64-linux-musl".parse().unwrap();
let sysroot = Sysroot::in_cache(Path::new("/cache"), target);
// The cache key is the canonical spelling, so two hosts asking for the same target ask for
// the same directory.
assert_eq!(sysroot.cache_key(), "aarch64-linux-musl");
assert_eq!(sysroot.root(), Path::new("/cache/sysroots/aarch64-linux-musl"));
// A static link needs three start files, and `crtn.o` goes after the libraries rather than
// with the other two.
let line = LinkLine::musl(&sysroot, LinkMode::Static);
assert_eq!(line.start.last().unwrap().file_name().unwrap(), "crti.o");
assert_eq!(line.end.first().unwrap().file_name().unwrap(), "crtn.o");
// And the whole linker command line, which names nothing on this machine.
let options = argv::Invocation { mode: LinkMode::Static, ..Default::default() };
let line = argv::argv(target, &sysroot, &options).unwrap();
assert!(line.contains(&"-static".to_owned()));
assert!(line.contains(&"-m".to_owned()) && line.contains(&"aarch64linux".to_owned()));Re-exports§
pub use argv::Invocation;pub use argv::Item;pub use argv::Unsupported;pub use artifact::PINNED;pub use artifact::Pinned;pub use artifact::pinned_for;pub use artifact::pinned_targets;pub use distribution::Arrival;pub use layout::BUNDLED_GLIBC;pub use layout::GlibcSkew;pub use layout::Kernel;pub use layout::Sysroot;pub use layout::bundled_glibc_minor;pub use link::Libc;pub use link::LinkLine;pub use link::LinkMode;pub use link::libc;pub use manifest::Input;pub use manifest::Licence;pub use manifest::Manifest;pub use manifest::ManifestError;pub use manifest::Provenance;pub use search::Entry;pub use search::Options;pub use search::Origin;pub use search::include_paths;pub use wall::Wall;
Modules§
- argv
- The linker command line, as a function of the target and the sysroot and nothing else.
- artifact
- What this release pins: one sysroot artifact per target, by URL and by hash.
- distribution
- What a release brings onto a machine, per target, as one file an auditor can read.
- layout
- The directory layout of one target’s sysroot, and the cache key that names it.
- link
- The start files, the libraries and the loader for one target’s link.
- manifest
- What a produced sysroot carries: every input, where it came from, its hash and its licence.
- search
- The header search path, as section 8.5 states it.
- sha256
- sha256, as published in FIPS 180-4.
- wall
- The two targets whose system headers are somebody else’s to license.
Structs§
- Target
Tuple - Everything about a target that changes the bytes the compiler emits.