Skip to main content

Crate rucc_sysroot

Crate rucc_sysroot 

Source
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.

§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 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;

Modules§

argv
The linker command line, as a function of the target and the sysroot and nothing else.
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.

Structs§

TargetTuple
Everything about a target that changes the bytes the compiler emits.