rucc_sysroot/lib.rs
1//! Where a target's headers and link inputs live, which directories are searched for them, and in
2//! what order they reach the linker.
3//!
4//! Design: `spec/cross-compile/08-sysroots.md`, and section 8.5 for the rule this crate exists to
5//! enforce.
6//!
7//! # The claim this crate is responsible for
8//!
9//! `spec/cross-compile/02-the-goal.md` claim 5 is byte identical output from different hosts for
10//! the same target. It holds only because the search path rules make the libc header directory a
11//! function of the target rather than of the machine, and that function is here.
12//!
13//! So every answer in this crate is derived from a [`TargetTuple`] and from paths the caller
14//! supplies. Nothing reads an environment variable, nothing looks at `std::env::consts`, and
15//! nothing touches the filesystem. A host directory can only enter through
16//! [`Options::host_include`], which [`include_paths`] uses exactly once and only when the target
17//! is the host, and that is checkable by reading one function.
18//!
19//! # What is in here
20//!
21//! [`Sysroot`] is the directory layout for one target: where its headers go, where its link inputs
22//! go, and where the record of what they are goes. Its root is a function of a cache directory and
23//! the tuple, which is what makes the tuple a cache key.
24//!
25//! [`include_paths`] is section 8.5 as an ordered list, with each entry saying which of the four
26//! steps put it there. [`LinkLine`] is the start files, the libraries and the end files for a musl
27//! link, in the order a linker needs them.
28//!
29//! [`Manifest`] is what a produced sysroot carries: every input with where it came from, its hash
30//! and its licence. Two sysroots for the same target built on two hosts have the same manifest, and
31//! comparing manifests is how that gets checked without comparing several thousand files.
32//!
33//! # What is not in here
34//!
35//! Nothing fetches. Downloading musl, verifying it and unpacking it is
36//! `spec/cross-compile/13-distribution.md`, and it needs a cache, a provenance record and a network
37//! policy that this crate deliberately has no opinion about. What this crate settles is where the
38//! result goes and how it is searched, which is the part that has to be decided before anything is
39//! worth downloading.
40//!
41//! ```
42//! use rucc_sysroot::{Sysroot, LinkLine, LinkMode};
43//! use rucc_tuple::TargetTuple;
44//! use std::path::Path;
45//!
46//! let target: TargetTuple = "aarch64-linux-musl".parse().unwrap();
47//! let sysroot = Sysroot::in_cache(Path::new("/cache"), target);
48//!
49//! // The cache key is the canonical spelling, so two hosts asking for the same target ask for
50//! // the same directory.
51//! assert_eq!(sysroot.cache_key(), "aarch64-linux-musl");
52//! assert_eq!(sysroot.root(), Path::new("/cache/sysroots/aarch64-linux-musl"));
53//!
54//! // A static link needs three start files, and `crtn.o` goes after the libraries rather than
55//! // with the other two.
56//! let line = LinkLine::musl(&sysroot, LinkMode::Static);
57//! assert_eq!(line.start.last().unwrap().file_name().unwrap(), "crti.o");
58//! assert_eq!(line.end.first().unwrap().file_name().unwrap(), "crtn.o");
59//! assert!(line.flags.iter().any(|flag| flag == "-static"));
60//! ```
61
62#![doc(html_root_url = "https://docs.rs/rucc-sysroot/0.9.0")]
63// Every public item here is read by somebody bringing up a target, and an undocumented one is a
64// question they have to answer by reading the body.
65#![deny(missing_docs)]
66
67pub mod layout;
68pub mod link;
69pub mod manifest;
70pub mod search;
71
72pub use layout::Sysroot;
73pub use link::{LinkLine, LinkMode};
74pub use manifest::{Input, Licence, Manifest, ManifestError};
75pub use search::{Entry, Options, Origin, include_paths};
76
77#[doc(inline)]
78pub use rucc_tuple::TargetTuple;