chore: remove `rustc-workspace-hack`

Co-authored-by: Scott Schafer <schaferjscott@gmail.com>
Co-authored-by: Eric Huss <eric@huss.org>
This commit is contained in:
Weihang Lo 2023-03-13 17:46:38 +00:00
parent 1cfaa3431e
commit befa5c98c9
No known key found for this signature in database
GPG Key ID: D7DBF189825E82E7
8 changed files with 4 additions and 191 deletions

View File

@ -2773,7 +2773,6 @@ dependencies = [
name = "rls" name = "rls"
version = "2.0.0" version = "2.0.0"
dependencies = [ dependencies = [
"rustc-workspace-hack",
"serde", "serde",
"serde_json", "serde_json",
] ]
@ -2885,11 +2884,8 @@ dependencies = [
[[package]] [[package]]
name = "rustc-workspace-hack" name = "rustc-workspace-hack"
version = "1.0.0" version = "1.0.0"
dependencies = [ source = "registry+https://github.com/rust-lang/crates.io-index"
"libc", checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb"
"regex",
"serde_json",
]
[[package]] [[package]]
name = "rustc_abi" name = "rustc_abi"

View File

@ -100,10 +100,6 @@ miniz_oxide.debug = 0
object.debug = 0 object.debug = 0
[patch.crates-io] [patch.crates-io]
# See comments in `src/tools/rustc-workspace-hack/README.md` for what's going on
# here
rustc-workspace-hack = { path = 'src/tools/rustc-workspace-hack' }
# See comments in `library/rustc-std-workspace-core/README.md` for what's going on # See comments in `library/rustc-std-workspace-core/README.md` for what's going on
# here # here
rustc-std-workspace-core = { path = 'library/rustc-std-workspace-core' } rustc-std-workspace-core = { path = 'library/rustc-std-workspace-core' }

View File

@ -238,8 +238,6 @@ pub struct Build {
ci_env: CiEnv, ci_env: CiEnv,
delayed_failures: RefCell<Vec<String>>, delayed_failures: RefCell<Vec<String>>,
prerelease_version: Cell<Option<u32>>, prerelease_version: Cell<Option<u32>>,
tool_artifacts:
RefCell<HashMap<TargetSelection, HashMap<String, (&'static str, PathBuf, Vec<String>)>>>,
#[cfg(feature = "build-metrics")] #[cfg(feature = "build-metrics")]
metrics: metrics::BuildMetrics, metrics: metrics::BuildMetrics,
@ -458,7 +456,6 @@ impl Build {
ci_env: CiEnv::current(), ci_env: CiEnv::current(),
delayed_failures: RefCell::new(Vec::new()), delayed_failures: RefCell::new(Vec::new()),
prerelease_version: Cell::new(None), prerelease_version: Cell::new(None),
tool_artifacts: Default::default(),
#[cfg(feature = "build-metrics")] #[cfg(feature = "build-metrics")]
metrics: metrics::BuildMetrics::init(), metrics: metrics::BuildMetrics::init(),

View File

@ -1,4 +1,3 @@
use std::collections::HashSet;
use std::env; use std::env;
use std::fs; use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
@ -120,136 +119,10 @@ impl Step for ToolBuild {
&self.target, &self.target,
); );
builder.info(&msg); builder.info(&msg);
let mut duplicates = Vec::new(); let is_expected = compile::stream_cargo(builder, cargo, vec![], &mut |_msg| {
let is_expected = compile::stream_cargo(builder, cargo, vec![], &mut |msg| { return;
// Only care about big things like the RLS/Cargo for now
match tool {
"rls" | "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");
}
builder.save_toolstate( builder.save_toolstate(
tool, tool,
if is_expected { ToolState::TestFail } else { ToolState::BuildFail }, if is_expected { ToolState::TestFail } else { ToolState::BuildFail },

View File

@ -7,7 +7,3 @@ license = "Apache-2.0/MIT"
[dependencies] [dependencies]
serde = { version = "1.0.143", features = ["derive"] } serde = { version = "1.0.143", features = ["derive"] }
serde_json = "1.0.83" serde_json = "1.0.83"
# A noop dependency that changes in the Rust repository, it's a bit of a hack.
# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
# for more information.
rustc-workspace-hack = "1.0.0"

View File

@ -1,19 +0,0 @@
[package]
name = "rustc-workspace-hack"
version = "1.0.0"
license = 'MIT OR Apache-2.0'
description = """
Hack for the compiler's own build system
"""
edition = "2021"
[lib]
path = "lib.rs"
# For documentation about what this is and why in the world these dependencies
# are appearing, see `README.md`.
[dependencies]
libc = { version = "0.2", features = ["extra_traits"] }
serde_json = { version = "1.0.31", features = ["unbounded_depth"] }
# Ensure default features of regex, which are disabled in some scenarios.
regex = { version = "1.5.6" }

View File

@ -1,25 +0,0 @@
# `rustc-workspace-hack`
This crate is a bit of a hack to make workspaces in rustc work a bit better.
The rationale for this existence is a bit subtle, but the general idea is that
we want commands like `./x.py build src/tools/{clippy,cargo}` to share as
many dependencies as possible.
Each invocation is a different invocation of Cargo, however. Each time Cargo
runs a build it will re-resolve the dependency graph, notably selecting
different features sometimes for each build.
For example, let's say there's a very deep dependency like `winapi` in each of
these builds. For Cargo, `winapi` has 33 features enabled. In Clippy, however,
`winapi` has 22 features enabled. This means that building Cargo and then the
Clippy will actually build winapi twice, which in turn will build duplicates
of everything that depends on `winapi`. This is bad!
The goal of this crate is to solve this problem and ensure that the resolved
dependency graph for all of these tools is the same in the various subsets of
each tool, notably enabling the same features of transitive dependencies.
All tools vendored here depend on the `rustc-workspace-hack` crate on crates.io.
When on crates.io this crate is an empty crate that is just a noop. We override
it, however, in this workspace to this crate here, which means we can control
crates in the dependency graph for each of these tools.

View File

@ -1 +0,0 @@
// intentionally left blank