diff options
Diffstat (limited to 'src/bootstrap/tool.rs')
-rw-r--r-- | src/bootstrap/tool.rs | 245 |
1 files changed, 67 insertions, 178 deletions
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index d1fd2e8c4..b3791efaf 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -1,4 +1,3 @@ -use std::collections::HashSet; use std::env; use std::fs; use std::path::PathBuf; @@ -12,6 +11,7 @@ use crate::toolstate::ToolState; use crate::util::{add_dylib_path, exe, t}; use crate::Compiler; use crate::Mode; +use crate::{gha, Kind}; #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub enum SourceType { @@ -33,41 +33,27 @@ struct ToolBuild { allow_features: &'static str, } -fn tooling_output( - mode: Mode, - tool: &str, - build_stage: u32, - host: &TargetSelection, - target: &TargetSelection, -) -> String { - match mode { - // depends on compiler stage, different to host compiler - Mode::ToolRustc => { - if host == target { - format!("Building tool {} (stage{} -> stage{})", tool, build_stage, build_stage + 1) - } else { - format!( - "Building tool {} (stage{}:{} -> stage{}:{})", - tool, - build_stage, - host, - build_stage + 1, - target - ) - } +impl Builder<'_> { + fn msg_tool( + &self, + mode: Mode, + tool: &str, + build_stage: u32, + host: &TargetSelection, + target: &TargetSelection, + ) -> Option<gha::Group> { + match mode { + // depends on compiler stage, different to host compiler + Mode::ToolRustc => self.msg_sysroot_tool( + Kind::Build, + build_stage, + format_args!("tool {tool}"), + *host, + *target, + ), + // doesn't depend on compiler, same as host compiler + _ => self.msg(Kind::Build, build_stage, format_args!("tool {tool}"), *host, *target), } - // doesn't depend on compiler, same as host compiler - Mode::ToolStd => { - if host == target { - format!("Building tool {} (stage{})", tool, build_stage) - } else { - format!( - "Building tool {} (stage{}:{} -> stage{}:{})", - tool, build_stage, host, build_stage, target - ) - } - } - _ => format!("Building tool {} (stage{})", tool, build_stage), } } @@ -112,143 +98,16 @@ impl Step for ToolBuild { if !self.allow_features.is_empty() { cargo.allow_features(self.allow_features); } - let msg = tooling_output( + let _guard = builder.msg_tool( self.mode, self.tool, self.compiler.stage, &self.compiler.host, &self.target, ); - builder.info(&msg); - let mut duplicates = Vec::new(); - let is_expected = compile::stream_cargo(builder, cargo, vec![], &mut |msg| { - // Only care about big things like the RLS/Cargo for now - match tool { - "rls" | "cargo" | "clippy-driver" | "miri" | "rustfmt" => {} - - _ => return, - } - let (id, features, filenames) = match msg { - compile::CargoMessage::CompilerArtifact { - package_id, - features, - filenames, - target: _, - } => (package_id, features, filenames), - _ => return, - }; - let features = features.iter().map(|s| s.to_string()).collect::<Vec<_>>(); - - for path in filenames { - let val = (tool, PathBuf::from(&*path), features.clone()); - // we're only interested in deduplicating rlibs for now - if val.1.extension().and_then(|s| s.to_str()) != Some("rlib") { - continue; - } - - // Don't worry about compiles that turn out to be host - // dependencies or build scripts. To skip these we look for - // anything that goes in `.../release/deps` but *doesn't* go in - // `$target/release/deps`. This ensure that outputs in - // `$target/release` are still considered candidates for - // deduplication. - if let Some(parent) = val.1.parent() { - if parent.ends_with("release/deps") { - let maybe_target = parent - .parent() - .and_then(|p| p.parent()) - .and_then(|p| p.file_name()) - .and_then(|p| p.to_str()) - .unwrap(); - if maybe_target != &*target.triple { - continue; - } - } - } - - // Record that we've built an artifact for `id`, and if one was - // already listed then we need to see if we reused the same - // artifact or produced a duplicate. - let mut artifacts = builder.tool_artifacts.borrow_mut(); - let prev_artifacts = artifacts.entry(target).or_default(); - let prev = match prev_artifacts.get(&*id) { - Some(prev) => prev, - None => { - prev_artifacts.insert(id.to_string(), val); - continue; - } - }; - if prev.1 == val.1 { - return; // same path, same artifact - } - // If the paths are different and one of them *isn't* inside of - // `release/deps`, then it means it's probably in - // `$target/release`, or it's some final artifact like - // `libcargo.rlib`. In these situations Cargo probably just - // copied it up from `$target/release/deps/libcargo-xxxx.rlib`, - // so if the features are equal we can just skip it. - let prev_no_hash = prev.1.parent().unwrap().ends_with("release/deps"); - let val_no_hash = val.1.parent().unwrap().ends_with("release/deps"); - if prev.2 == val.2 || !prev_no_hash || !val_no_hash { - return; - } - - // ... and otherwise this looks like we duplicated some sort of - // compilation, so record it to generate an error later. - duplicates.push((id.to_string(), val, prev.clone())); - } - }); - - if is_expected && !duplicates.is_empty() { - eprintln!( - "duplicate artifacts found when compiling a tool, this \ - typically means that something was recompiled because \ - a transitive dependency has different features activated \ - than in a previous build:\n" - ); - let (same, different): (Vec<_>, Vec<_>) = - duplicates.into_iter().partition(|(_, cur, prev)| cur.2 == prev.2); - if !same.is_empty() { - eprintln!( - "the following dependencies are duplicated although they \ - have the same features enabled:" - ); - for (id, cur, prev) in same { - eprintln!(" {}", id); - // same features - eprintln!(" `{}` ({:?})\n `{}` ({:?})", cur.0, cur.1, prev.0, prev.1); - } - } - if !different.is_empty() { - eprintln!("the following dependencies have different features:"); - for (id, cur, prev) in different { - eprintln!(" {}", id); - let cur_features: HashSet<_> = cur.2.into_iter().collect(); - let prev_features: HashSet<_> = prev.2.into_iter().collect(); - eprintln!( - " `{}` additionally enabled features {:?} at {:?}", - cur.0, - &cur_features - &prev_features, - cur.1 - ); - eprintln!( - " `{}` additionally enabled features {:?} at {:?}", - prev.0, - &prev_features - &cur_features, - prev.1 - ); - } - } - eprintln!(); - eprintln!( - "to fix this you will probably want to edit the local \ - src/tools/rustc-workspace-hack/Cargo.toml crate, as \ - that will update the dependency graph to ensure that \ - these crates all share the same feature set" - ); - panic!("tools should not compile multiple copies of the same crate"); - } + let mut cargo = Command::from(cargo); + let is_expected = builder.try_run(&mut cargo); builder.save_toolstate( tool, @@ -282,7 +141,7 @@ pub fn prepare_tool_cargo( mode: Mode, target: TargetSelection, command: &'static str, - path: &'static str, + path: &str, source_type: SourceType, extra_features: &[String], ) -> CargoCommand { @@ -299,7 +158,9 @@ pub fn prepare_tool_cargo( || path.ends_with("rustfmt") { cargo.env("LIBZ_SYS_STATIC", "1"); - features.push("rustc-workspace-hack/all-static".to_string()); + } + if path.ends_with("cargo") { + features.push("all-static".to_string()); } } @@ -319,6 +180,12 @@ pub fn prepare_tool_cargo( cargo.env("CFG_VERSION", builder.rust_version()); cargo.env("CFG_RELEASE_NUM", &builder.version); cargo.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel()); + if let Some(ref ver_date) = builder.rust_info().commit_date() { + cargo.env("CFG_VER_DATE", ver_date); + } + if let Some(ref ver_hash) = builder.rust_info().sha() { + cargo.env("CFG_VER_HASH", ver_hash); + } let info = GitInfo::new(builder.config.omit_git_hash, &dir); if let Some(sha) = info.sha() { @@ -434,6 +301,8 @@ bootstrap_tool!( CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata"; GenerateCopyright, "src/tools/generate-copyright", "generate-copyright"; SuggestTests, "src/tools/suggest-tests", "suggest-tests"; + GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys"; + RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = "test"; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] @@ -611,14 +480,13 @@ impl Step for Rustdoc { cargo.rustflag("--cfg=parallel_compiler"); } - let msg = tooling_output( + let _guard = builder.msg_tool( Mode::ToolRustc, "rustdoc", build_compiler.stage, &self.compiler.host, &target, ); - builder.info(&msg); builder.run(&mut cargo.into()); // Cargo adds a number of paths to the dylib search path on windows, which results in @@ -707,18 +575,18 @@ impl Step for Cargo { if self.target.contains("windows") { build_cred( "cargo-credential-wincred", - "src/tools/cargo/crates/credential/cargo-credential-wincred", + "src/tools/cargo/credential/cargo-credential-wincred", ); } if self.target.contains("apple-darwin") { build_cred( "cargo-credential-macos-keychain", - "src/tools/cargo/crates/credential/cargo-credential-macos-keychain", + "src/tools/cargo/credential/cargo-credential-macos-keychain", ); } build_cred( "cargo-credential-1password", - "src/tools/cargo/crates/credential/cargo-credential-1password", + "src/tools/cargo/credential/cargo-credential-1password", ); cargo_bin_path } @@ -867,6 +735,7 @@ macro_rules! tool_extended { stable = $stable:expr $(,tool_std = $tool_std:literal)? $(,allow_features = $allow_features:expr)? + $(,add_bins_to_sysroot = $add_bins_to_sysroot:expr)? ;)+) => { $( #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -909,7 +778,7 @@ macro_rules! tool_extended { #[allow(unused_mut)] fn run(mut $sel, $builder: &Builder<'_>) -> Option<PathBuf> { - $builder.ensure(ToolBuild { + let tool = $builder.ensure(ToolBuild { compiler: $sel.compiler, target: $sel.target, tool: $tool_name, @@ -919,7 +788,27 @@ macro_rules! tool_extended { is_optional_tool: true, source_type: SourceType::InTree, allow_features: concat!($($allow_features)*), - }) + })?; + + if (false $(|| !$add_bins_to_sysroot.is_empty())?) && $sel.compiler.stage > 0 { + let bindir = $builder.sysroot($sel.compiler).join("bin"); + t!(fs::create_dir_all(&bindir)); + + #[allow(unused_variables)] + let tools_out = $builder + .cargo_out($sel.compiler, Mode::ToolRustc, $sel.target); + + $(for add_bin in $add_bins_to_sysroot { + let bin_source = tools_out.join(exe(add_bin, $sel.target)); + let bin_destination = bindir.join(exe(add_bin, $sel.compiler.host)); + $builder.copy(&bin_source, &bin_destination); + })? + + let tool = bindir.join(exe($tool_name, $sel.compiler.host)); + Some(tool) + } else { + Some(tool) + } } } )+ @@ -933,15 +822,15 @@ macro_rules! tool_extended { tool_extended!((self, builder), Cargofmt, "src/tools/rustfmt", "cargo-fmt", stable=true; CargoClippy, "src/tools/clippy", "cargo-clippy", stable=true; - Clippy, "src/tools/clippy", "clippy-driver", stable=true; - Miri, "src/tools/miri", "miri", stable=false; - CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=true; + Clippy, "src/tools/clippy", "clippy-driver", stable=true, add_bins_to_sysroot = ["clippy-driver", "cargo-clippy"]; + Miri, "src/tools/miri", "miri", stable=false, add_bins_to_sysroot = ["miri"]; + CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=true, add_bins_to_sysroot = ["cargo-miri"]; // FIXME: tool_std is not quite right, we shouldn't allow nightly features. // But `builder.cargo` doesn't know how to handle ToolBootstrap in stages other than 0, // and this is close enough for now. Rls, "src/tools/rls", "rls", stable=true, tool_std=true; RustDemangler, "src/tools/rust-demangler", "rust-demangler", stable=false, tool_std=true; - Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true; + Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, add_bins_to_sysroot = ["rustfmt", "cargo-fmt"]; ); impl<'a> Builder<'a> { |