Skip to content

Commit 21a5efb

Browse files
committed
Fix links vars showing up for testing packages
If a package is tested and the library for the package wasn't built (e.g. only tested or it wasn't present) then the `links` env vars from dependencies weren't showing up to the build script by accident. This was an accidental regression from #8969. The intention of #8969 was to exclude connections to build scripts connected via dev-dependencies, but it only applied a heuristic because the unit graph doesn't retain information about dev-dependencies. The fix here is to instead actually retain information about dev-dependencies which is only used for constructing the unit graph and connecting build script executions to one another. Closes #9063
1 parent 89dcb2a commit 21a5efb

File tree

2 files changed

+97
-18
lines changed

2 files changed

+97
-18
lines changed

src/cargo/core/compiler/unit_dependencies.rs

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ struct State<'a, 'cfg> {
4747
target_data: &'a RustcTargetData,
4848
profiles: &'a Profiles,
4949
interner: &'a UnitInterner,
50+
51+
/// A set of edges in `unit_dependencies` where (a, b) means that the
52+
/// dependency from a to b was added purely because it was a dev-dependency.
53+
/// This is used during `connect_run_custom_build_deps`.
54+
dev_dependency_edges: HashSet<(Unit, Unit)>,
5055
}
5156

5257
pub fn build_unit_dependencies<'a, 'cfg>(
@@ -86,6 +91,7 @@ pub fn build_unit_dependencies<'a, 'cfg>(
8691
target_data,
8792
profiles,
8893
interner,
94+
dev_dependency_edges: HashSet::new(),
8995
};
9096

9197
let std_unit_deps = calc_deps_of_std(&mut state, std_roots)?;
@@ -98,7 +104,7 @@ pub fn build_unit_dependencies<'a, 'cfg>(
98104
attach_std_deps(&mut state, std_roots, std_unit_deps);
99105
}
100106

101-
connect_run_custom_build_deps(&mut state.unit_dependencies);
107+
connect_run_custom_build_deps(&mut state);
102108

103109
// Dependencies are used in tons of places throughout the backend, many of
104110
// which affect the determinism of the build itself. As a result be sure
@@ -258,7 +264,8 @@ fn compute_deps(
258264
});
259265

260266
let mut ret = Vec::new();
261-
for (id, _) in filtered_deps {
267+
let mut dev_deps = Vec::new();
268+
for (id, deps) in filtered_deps {
262269
let pkg = state.get(id);
263270
let lib = match pkg.targets().iter().find(|t| t.is_lib()) {
264271
Some(t) => t,
@@ -267,6 +274,7 @@ fn compute_deps(
267274
let mode = check_or_build_mode(unit.mode, lib);
268275
let dep_unit_for = unit_for.with_dependency(unit, lib);
269276

277+
let start = ret.len();
270278
if state.config.cli_unstable().dual_proc_macros && lib.proc_macro() && !unit.kind.is_host()
271279
{
272280
let unit_dep = new_unit_dep(state, unit, pkg, lib, dep_unit_for, unit.kind, mode)?;
@@ -286,7 +294,18 @@ fn compute_deps(
286294
)?;
287295
ret.push(unit_dep);
288296
}
297+
298+
// If the unit added was a dev-dependency unit, then record that in the
299+
// dev-dependencies array. We'll add this to
300+
// `state.dev_dependency_edges` at the end and process it later in
301+
// `connect_run_custom_build_deps`.
302+
if deps.iter().all(|d| !d.is_transitive()) {
303+
for dep in ret[start..].iter() {
304+
dev_deps.push((unit.clone(), dep.unit.clone()));
305+
}
306+
}
289307
}
308+
state.dev_dependency_edges.extend(dev_deps);
290309

291310
// If this target is a build script, then what we've collected so far is
292311
// all we need. If this isn't a build script, then it depends on the
@@ -617,26 +636,18 @@ fn new_unit_dep_with_profile(
617636
///
618637
/// Here we take the entire `deps` map and add more dependencies from execution
619638
/// of one build script to execution of another build script.
620-
fn connect_run_custom_build_deps(unit_dependencies: &mut UnitGraph) {
639+
fn connect_run_custom_build_deps(state: &mut State<'_, '_>) {
621640
let mut new_deps = Vec::new();
622641

623642
{
643+
let state = &*state;
624644
// First up build a reverse dependency map. This is a mapping of all
625645
// `RunCustomBuild` known steps to the unit which depends on them. For
626646
// example a library might depend on a build script, so this map will
627647
// have the build script as the key and the library would be in the
628648
// value's set.
629-
//
630-
// Note that as an important part here we're skipping "test" units. Test
631-
// units depend on the execution of a build script, but
632-
// links-dependencies only propagate through `[dependencies]`, nothing
633-
// else. We don't want to pull in a links-dependency through a
634-
// dev-dependency since that could create a cycle.
635649
let mut reverse_deps_map = HashMap::new();
636-
for (unit, deps) in unit_dependencies.iter() {
637-
if unit.mode.is_any_test() {
638-
continue;
639-
}
650+
for (unit, deps) in state.unit_dependencies.iter() {
640651
for dep in deps {
641652
if dep.unit.mode == CompileMode::RunCustomBuild {
642653
reverse_deps_map
@@ -656,7 +667,8 @@ fn connect_run_custom_build_deps(unit_dependencies: &mut UnitGraph) {
656667
// `links`, then we depend on that package's build script! Here we use
657668
// `dep_build_script` to manufacture an appropriate build script unit to
658669
// depend on.
659-
for unit in unit_dependencies
670+
for unit in state
671+
.unit_dependencies
660672
.keys()
661673
.filter(|k| k.mode == CompileMode::RunCustomBuild)
662674
{
@@ -670,16 +682,34 @@ fn connect_run_custom_build_deps(unit_dependencies: &mut UnitGraph) {
670682
let to_add = reverse_deps
671683
.iter()
672684
// Get all sibling dependencies of `unit`
673-
.flat_map(|reverse_dep| unit_dependencies[reverse_dep].iter())
685+
.flat_map(|reverse_dep| {
686+
state.unit_dependencies[reverse_dep]
687+
.iter()
688+
.map(move |a| (reverse_dep, a))
689+
})
674690
// Only deps with `links`.
675-
.filter(|other| {
691+
.filter(|(_parent, other)| {
676692
other.unit.pkg != unit.pkg
677693
&& other.unit.target.is_linkable()
678694
&& other.unit.pkg.manifest().links().is_some()
679695
})
696+
// Skip dependencies induced via dev-dependencies since
697+
// connections between `links` and build scripts only happens
698+
// via normal dependencies. Otherwise since dev-dependencies can
699+
// be cyclic we could have cyclic build-script executions.
700+
.filter_map(move |(parent, other)| {
701+
if state
702+
.dev_dependency_edges
703+
.contains(&((*parent).clone(), other.unit.clone()))
704+
{
705+
None
706+
} else {
707+
Some(other)
708+
}
709+
})
680710
// Get the RunCustomBuild for other lib.
681711
.filter_map(|other| {
682-
unit_dependencies[&other.unit]
712+
state.unit_dependencies[&other.unit]
683713
.iter()
684714
.find(|other_dep| other_dep.unit.mode == CompileMode::RunCustomBuild)
685715
.cloned()
@@ -695,7 +725,11 @@ fn connect_run_custom_build_deps(unit_dependencies: &mut UnitGraph) {
695725

696726
// And finally, add in all the missing dependencies!
697727
for (unit, new_deps) in new_deps {
698-
unit_dependencies.get_mut(&unit).unwrap().extend(new_deps);
728+
state
729+
.unit_dependencies
730+
.get_mut(&unit)
731+
.unwrap()
732+
.extend(new_deps);
699733
}
700734
}
701735

tests/testsuite/build_script.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4158,3 +4158,48 @@ fn rerun_if_directory() {
41584158
dirty();
41594159
fresh();
41604160
}
4161+
4162+
#[cargo_test]
4163+
fn test_with_dep_metadata() {
4164+
let p = project()
4165+
.file(
4166+
"Cargo.toml",
4167+
r#"
4168+
[package]
4169+
name = "foo"
4170+
version = "0.1.0"
4171+
4172+
[dependencies]
4173+
bar = { path = 'bar' }
4174+
"#,
4175+
)
4176+
.file("src/lib.rs", "")
4177+
.file(
4178+
"build.rs",
4179+
r#"
4180+
fn main() {
4181+
assert_eq!(std::env::var("DEP_BAR_FOO").unwrap(), "bar");
4182+
}
4183+
"#,
4184+
)
4185+
.file(
4186+
"bar/Cargo.toml",
4187+
r#"
4188+
[package]
4189+
name = "bar"
4190+
version = "0.1.0"
4191+
links = 'bar'
4192+
"#,
4193+
)
4194+
.file("bar/src/lib.rs", "")
4195+
.file(
4196+
"bar/build.rs",
4197+
r#"
4198+
fn main() {
4199+
println!("cargo:foo=bar");
4200+
}
4201+
"#,
4202+
)
4203+
.build();
4204+
p.cargo("test --lib").run();
4205+
}

0 commit comments

Comments
 (0)