Skip to content

Refactor build-manifest to minimize the number of changes needed to add a new component #102565

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Nov 9, 2022
32 changes: 19 additions & 13 deletions src/tools/build-manifest/README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
# build-manifest

This tool generates the manifests uploaded to static.rust-lang.org and used by
rustup. The tool is invoked by the bootstrap tool.
This tool generates the manifests uploaded to static.rust-lang.org and used by rustup.
You can see a full list of all manifests at <https://static.rust-lang.org/manifests.txt>.
This listing is updated by <https://github.com/rust-lang/generate-manifest-list> every 7 days.

This gets called by `promote-release` <https://github.com/rust-lang/promote-release> via `x.py dist hash-and-sign`.

## Adding a new component

1. Add a new `Step` to `dist.rs`. This should usually be named after the filename of the uploaded tarball. See https://github.com/rust-lang/rust/pull/101799/files#diff-2c56335faa24486df09ba392d8900c57e2fac4633e1f7038469bcf9ed3feb871 for an example.
a. If appropriate, call `tarball.is_preview(true)` for the component.
2. Add a new `PkgType` to build-manifest. Fix all the compile errors as appropriate.

## Testing changes locally

In order to test the changes locally you need to have a valid dist directory
available locally. If you don't want to build all the compiler, you can easily
create one from the nightly artifacts with:

```
#!/bin/bash
for cmpn in rust rustc rust-std rust-docs cargo; do
wget https://static.rust-lang.org/dist/${cmpn}-nightly-x86_64-unknown-linux-gnu.tar.gz
```sh
for component in rust rustc rust-std rust-docs cargo; do
wget -P build/dist https://static.rust-lang.org/dist/${component}-nightly-x86_64-unknown-linux-gnu.tar.gz
done
```

Then, you can generate the manifest and all the packages from `path/to/dist` to
`path/to/output` with:
Then, you can generate the manifest and all the packages from `build/dist` to
`build/manifest` with:

```sh
mkdir -p build/manifest
cargo +nightly run --release -p build-manifest build/dist build/manifest 1970-01-01 http://example.com nightly
```
$ cargo +nightly run path/to/dist path/to/output 1970-01-01 http://example.com CHANNEL
```

Remember to replace `CHANNEL` with the channel you produced dist artifacts of
and `VERSION` with the current Rust version.
212 changes: 92 additions & 120 deletions src/tools/build-manifest/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
//! Build a dist manifest, hash and sign everything.
//! This gets called by `promote-release`
//! (https://github.com/rust-lang/rust-central-station/tree/master/promote-release)
//! via `x.py dist hash-and-sign`; the cmdline arguments are set up
//! by rustbuild (in `src/bootstrap/dist.rs`).
#![doc = include_str!("../README.md")]

mod checksum;
mod manifest;
Expand Down Expand Up @@ -184,7 +180,7 @@ static PKG_INSTALLERS: &[&str] = &["x86_64-apple-darwin", "aarch64-apple-darwin"

static MINGW: &[&str] = &["i686-pc-windows-gnu", "x86_64-pc-windows-gnu"];

static NIGHTLY_ONLY_COMPONENTS: &[&str] = &["miri-preview", "rust-docs-json-preview"];
static NIGHTLY_ONLY_COMPONENTS: &[PkgType] = &[PkgType::Miri, PkgType::JsonDocs];

macro_rules! t {
($e:expr) => {
Expand Down Expand Up @@ -287,28 +283,9 @@ impl Builder {
}

fn add_packages_to(&mut self, manifest: &mut Manifest) {
macro_rules! package {
($name:expr, $targets:expr) => {
self.package($name, &mut manifest.pkg, $targets, &[])
};
for pkg in PkgType::all() {
self.package(pkg, &mut manifest.pkg);
}
package!("rustc", HOSTS);
package!("rustc-dev", HOSTS);
package!("reproducible-artifacts", HOSTS);
package!("rustc-docs", HOSTS);
package!("cargo", HOSTS);
package!("rust-mingw", MINGW);
package!("rust-std", TARGETS);
self.package("rust-docs", &mut manifest.pkg, HOSTS, DOCS_FALLBACK);
self.package("rust-docs-json-preview", &mut manifest.pkg, HOSTS, DOCS_FALLBACK);
package!("rust-src", &["*"]);
package!("rls-preview", HOSTS);
package!("rust-analyzer-preview", HOSTS);
package!("clippy-preview", HOSTS);
package!("miri-preview", HOSTS);
package!("rustfmt-preview", HOSTS);
package!("rust-analysis", TARGETS);
package!("llvm-tools-preview", TARGETS);
}

fn add_artifacts_to(&mut self, manifest: &mut Manifest) {
Expand All @@ -333,44 +310,28 @@ impl Builder {
}

fn add_profiles_to(&mut self, manifest: &mut Manifest) {
let mut profile = |name, pkgs| self.profile(name, &mut manifest.profiles, pkgs);
profile("minimal", &["rustc", "cargo", "rust-std", "rust-mingw"]);
profile(
"default",
&[
"rustc",
"cargo",
"rust-std",
"rust-mingw",
"rust-docs",
"rustfmt-preview",
"clippy-preview",
],
);
profile(
"complete",
&[
"rustc",
"cargo",
"rust-std",
"rust-mingw",
"rust-docs",
"rustfmt-preview",
"clippy-preview",
"rls-preview",
"rust-analyzer-preview",
"rust-src",
"llvm-tools-preview",
"rust-analysis",
"miri-preview",
],
);
use PkgType::*;

let mut profile = |name, pkgs: &_| self.profile(name, &mut manifest.profiles, pkgs);

// Use a Vec here to make sure we don't exclude any components in an earlier profile.
let minimal = vec![Rustc, Cargo, RustStd, RustMingw];
profile("minimal", &minimal);

let mut default = minimal;
default.extend([HtmlDocs, Rustfmt, Clippy]);
profile("default", &default);

// NOTE: this profile is effectively deprecated; do not add new components to it.
let mut complete = default;
complete.extend([Rls, RustAnalyzer, RustSrc, LlvmTools, RustAnalysis, Miri]);
profile("complete", &complete);

// The compiler libraries are not stable for end users, and they're also huge, so we only
// `rustc-dev` for nightly users, and only in the "complete" profile. It's still possible
// for users to install the additional component manually, if needed.
if self.versions.channel() == "nightly" {
self.extend_profile("complete", &mut manifest.profiles, &["rustc-dev"]);
self.extend_profile("complete", &mut manifest.profiles, &[RustcDev]);
// Do not include the rustc-docs component for now, as it causes
// conflicts with the rust-docs component when installed. See
// #75833.
Expand All @@ -382,12 +343,11 @@ impl Builder {
let mut rename = |from: &str, to: &str| {
manifest.renames.insert(from.to_owned(), Rename { to: to.to_owned() })
};
rename("rls", "rls-preview");
rename("rustfmt", "rustfmt-preview");
rename("clippy", "clippy-preview");
rename("miri", "miri-preview");
rename("rust-docs-json", "rust-docs-json-preview");
rename("rust-analyzer", "rust-analyzer-preview");
for pkg in PkgType::all() {
if pkg.is_preview() {
rename(pkg.tarball_component_name(), &pkg.manifest_component_name());
}
}
}

fn rust_package(&mut self, manifest: &Manifest) -> Package {
Expand Down Expand Up @@ -419,42 +379,52 @@ impl Builder {
let mut components = Vec::new();
let mut extensions = Vec::new();

let host_component = |pkg| Component::from_str(pkg, host);

// rustc/rust-std/cargo/docs are all required,
// and so is rust-mingw if it's available for the target.
components.extend(vec![
host_component("rustc"),
host_component("rust-std"),
host_component("cargo"),
host_component("rust-docs"),
]);
if host.contains("pc-windows-gnu") {
components.push(host_component("rust-mingw"));
}
let host_component = |pkg: &_| Component::from_pkg(pkg, host);

// Tools are always present in the manifest,
// but might be marked as unavailable if they weren't built.
extensions.extend(vec![
host_component("clippy-preview"),
host_component("miri-preview"),
host_component("rls-preview"),
host_component("rust-analyzer-preview"),
host_component("rustfmt-preview"),
host_component("llvm-tools-preview"),
host_component("rust-analysis"),
host_component("rust-docs-json-preview"),
]);

extensions.extend(
TARGETS
.iter()
.filter(|&&target| target != host)
.map(|target| Component::from_str("rust-std", target)),
);
extensions.extend(HOSTS.iter().map(|target| Component::from_str("rustc-dev", target)));
extensions.extend(HOSTS.iter().map(|target| Component::from_str("rustc-docs", target)));
extensions.push(Component::from_str("rust-src", "*"));
for pkg in PkgType::all() {
match pkg {
// rustc/rust-std/cargo/docs are all required
PkgType::Rustc | PkgType::Cargo | PkgType::HtmlDocs => {
components.push(host_component(pkg));
}
PkgType::RustStd => {
components.push(host_component(pkg));
extensions.extend(
TARGETS
.iter()
.filter(|&&target| target != host)
.map(|target| Component::from_pkg(pkg, target)),
);
}
// so is rust-mingw if it's available for the target
PkgType::RustMingw => {
if host.contains("pc-windows-gnu") {
components.push(host_component(pkg));
}
}
// Tools are always present in the manifest,
// but might be marked as unavailable if they weren't built.
PkgType::Clippy
| PkgType::Miri
| PkgType::Rls
| PkgType::RustAnalyzer
| PkgType::Rustfmt
| PkgType::LlvmTools
| PkgType::RustAnalysis
| PkgType::JsonDocs => {
extensions.push(host_component(pkg));
}
PkgType::RustcDev | PkgType::RustcDocs => {
extensions.extend(HOSTS.iter().map(|target| Component::from_pkg(pkg, target)));
}
PkgType::RustSrc => {
extensions.push(Component::from_pkg(pkg, "*"));
}
PkgType::Rust => {}
// NOTE: this is intentional, these artifacts aren't intended to be used with rustup
PkgType::ReproducibleArtifacts => {}
}
}

// If the components/extensions don't actually exist for this
// particular host/target combination then nix it entirely from our
Expand All @@ -481,43 +451,44 @@ impl Builder {
&mut self,
profile_name: &str,
dst: &mut BTreeMap<String, Vec<String>>,
pkgs: &[&str],
pkgs: &[PkgType],
) {
dst.insert(profile_name.to_owned(), pkgs.iter().map(|s| (*s).to_owned()).collect());
dst.insert(
profile_name.to_owned(),
pkgs.iter().map(|s| s.manifest_component_name()).collect(),
);
}

fn extend_profile(
&mut self,
profile_name: &str,
dst: &mut BTreeMap<String, Vec<String>>,
pkgs: &[&str],
pkgs: &[PkgType],
) {
dst.get_mut(profile_name)
.expect("existing profile")
.extend(pkgs.iter().map(|s| (*s).to_owned()));
.extend(pkgs.iter().map(|s| s.manifest_component_name()));
}

fn package(
&mut self,
pkgname: &str,
dst: &mut BTreeMap<String, Package>,
targets: &[&str],
fallback: &[(&str, &str)],
) {
let version_info = self
.versions
.version(&PkgType::from_component(pkgname))
.expect("failed to load package version");
fn package(&mut self, pkg: &PkgType, dst: &mut BTreeMap<String, Package>) {
if *pkg == PkgType::Rust {
// This is handled specially by `rust_package` later.
// Order is important, so don't call `rust_package` here.
return;
}

let fallback = if pkg.use_docs_fallback() { DOCS_FALLBACK } else { &[] };
let version_info = self.versions.version(&pkg).expect("failed to load package version");
let mut is_present = version_info.present;

// Never ship nightly-only components for other trains.
if self.versions.channel() != "nightly" && NIGHTLY_ONLY_COMPONENTS.contains(&pkgname) {
if self.versions.channel() != "nightly" && NIGHTLY_ONLY_COMPONENTS.contains(&pkg) {
is_present = false; // Pretend the component is entirely missing.
}

macro_rules! tarball_name {
($target_name:expr) => {
self.versions.tarball_name(&PkgType::from_component(pkgname), $target_name).unwrap()
self.versions.tarball_name(pkg, $target_name).unwrap()
};
}
let mut target_from_compressed_tar = |target_name| {
Expand Down Expand Up @@ -546,7 +517,8 @@ impl Builder {
Target::unavailable()
};

let targets = targets
let targets = pkg
.targets()
.iter()
.map(|name| {
let target = if is_present {
Expand All @@ -561,7 +533,7 @@ impl Builder {
.collect();

dst.insert(
pkgname.to_string(),
pkg.manifest_component_name(),
Package {
version: version_info.version.unwrap_or_default(),
git_commit_hash: version_info.git_commit,
Expand Down
5 changes: 3 additions & 2 deletions src/tools/build-manifest/src/manifest.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::versions::PkgType;
use crate::Builder;
use serde::{Serialize, Serializer};
use std::collections::BTreeMap;
Expand Down Expand Up @@ -116,8 +117,8 @@ pub(crate) struct Component {
}

impl Component {
pub(crate) fn from_str(pkg: &str, target: &str) -> Self {
Self { pkg: pkg.to_string(), target: target.to_string() }
pub(crate) fn from_pkg(pkg: &PkgType, target: &str) -> Self {
Self { pkg: pkg.manifest_component_name(), target: target.to_string() }
}
}

Expand Down
Loading