Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Commit 24bea9d

Browse files
committed
WIP: It works!
1 parent 7f39c94 commit 24bea9d

File tree

4 files changed

+77
-38
lines changed

4 files changed

+77
-38
lines changed

Cargo.lock

Lines changed: 35 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ categories = ["development-tools"]
1212

1313
build = "build.rs"
1414

15+
# Temporary override until/if https://github.com/rust-lang/cargo/pull/5830 lands
16+
[patch.'https://github.com/rust-lang/cargo']
17+
cargo = { git = "https://github.com/Xanewok/cargo", branch = "executor-compile-mode" }
18+
1519
[dependencies]
1620
cargo = { git = "https://github.com/rust-lang/cargo", rev = "af9e40c26b4ea2ebd6f31ee86ee61d5ac1c74eb0" }
1721
cargo_metadata = "0.5.2"

src/build/cargo.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ impl Executor for RlsExecutor {
333333
self.is_primary_crate(id)
334334
}
335335

336-
fn exec(&self, mut cargo_cmd: ProcessBuilder, id: &PackageId, target: &Target) -> CargoResult<()> {
336+
fn exec(&self, mut cargo_cmd: ProcessBuilder, id: &PackageId, target: &Target, mode: CompileMode) -> CargoResult<()> {
337337
// Use JSON output so that we can parse the rustc output.
338338
cargo_cmd.arg("--error-format=json");
339339
// Delete any stale data. We try and remove any json files with
@@ -461,7 +461,7 @@ impl Executor for RlsExecutor {
461461
// Cache executed command for the build plan
462462
{
463463
let mut cx = self.compilation_cx.lock().unwrap();
464-
cx.build_plan.cache_compiler_job(id, target, &cmd);
464+
cx.build_plan.cache_compiler_job(id, target, mode, &cmd);
465465
}
466466

467467
// Prepare modified cargo-generated args/envs for future rustc calls

src/build/plan.rs

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use std::sync::mpsc::Sender;
3333

3434
use crate::build::PackageArg;
3535
use cargo::core::{PackageId, Target, TargetKind};
36-
use cargo::core::compiler::{Context, Kind, Unit};
36+
use cargo::core::compiler::{CompileMode, Context, Kind, Unit};
3737
use cargo::core::profiles::Profile;
3838
use cargo::util::{CargoResult, ProcessBuilder};
3939
use cargo_metadata;
@@ -45,7 +45,9 @@ use crate::actions::progress::ProgressUpdate;
4545
use super::{BuildResult, Internals};
4646

4747
/// Main key type by which `Unit`s will be distinguished in the build plan.
48-
crate type UnitKey = (PackageId, TargetKind);
48+
/// In Target we're mostly interested in TargetKind (Lib, Bin, ...) and name
49+
/// (e.g. we can have 2 binary targets with different names).
50+
crate type UnitKey = (PackageId, Target, CompileMode);
4951

5052
/// Holds the information how exactly the build will be performed for a given
5153
/// workspace with given, specified features.
@@ -91,8 +93,8 @@ impl Plan {
9193
/// Cache a given compiler invocation in `ProcessBuilder` for a given
9294
/// `PackageId` and `TargetKind` in `Target`, to be used when processing
9395
/// cached build plan.
94-
crate fn cache_compiler_job(&mut self, id: &PackageId, target: &Target, cmd: &ProcessBuilder) {
95-
let pkg_key = (id.clone(), target.kind().clone());
96+
crate fn cache_compiler_job(&mut self, id: &PackageId, target: &Target, mode: CompileMode, cmd: &ProcessBuilder) {
97+
let pkg_key = (id.clone(), target.clone(), mode);
9698
self.compiler_jobs.insert(pkg_key, cmd.clone());
9799
}
98100

@@ -176,12 +178,12 @@ impl Plan {
176178

177179
let build_scripts: HashMap<&Path, UnitKey> = self.units
178180
.iter()
179-
.filter(|&(&(_, ref kind), _)| *kind == TargetKind::CustomBuild)
181+
.filter(|&(&(_, ref target, _), _)| *target.kind() == TargetKind::CustomBuild)
180182
.map(|(key, unit)| (unit.target.src_path(), key.clone()))
181183
.collect();
182184
let other_targets: HashMap<UnitKey, &Path> = self.units
183185
.iter()
184-
.filter(|&(&(_, ref kind), _)| *kind != TargetKind::CustomBuild)
186+
.filter(|&(&(_, ref target, _), _)| *target.kind() != TargetKind::CustomBuild)
185187
.map(|(key, unit)| {
186188
(
187189
key.clone(),
@@ -197,27 +199,32 @@ impl Plan {
197199
if let Some(unit) = build_scripts.get(modified) {
198200
result.insert(unit.clone());
199201
} else {
200-
// Not a build script, so we associate a dirty package with a
201-
// dirty file by finding longest (most specified) path prefix
202-
let unit = other_targets.iter().max_by_key(|&(_, src_dir)| {
203-
if !modified.starts_with(src_dir) {
204-
return 0;
205-
}
206-
modified
207-
.components()
208-
.zip(src_dir.components())
209-
.take_while(|&(a, b)| a == b)
202+
// Not a build script, so we associate a dirty file with a
203+
// package by finding longest (most specified) path prefix.
204+
let matching_prefix_components = |a: &Path, b: &Path| -> usize {
205+
assert!(a.is_absolute() && b.is_absolute());
206+
a.components().zip(b.components())
207+
.skip(1) // Skip RootDir
208+
.take_while(|&(x, y)| x == y)
210209
.count()
211-
});
212-
match unit {
213-
None => trace!(
214-
"Modified file {:?} doesn't correspond to any package!",
215-
modified.display()
216-
),
217-
Some(unit) => {
218-
result.insert(unit.0.clone());
219-
}
220210
};
211+
// Since a package can correspond to many units (e.g. compiled
212+
// as a regular binary or a test harness for unit tests), we
213+
// collect every unit having the longest path prefix.
214+
let max_matching_prefix = other_targets.values()
215+
.map(|src_dir| matching_prefix_components(modified, src_dir))
216+
.max().unwrap();
217+
218+
if max_matching_prefix == 0 {
219+
trace!("Modified file didn't correspond to any buildable unit!");
220+
} else {
221+
let dirty_units = other_targets.iter()
222+
.filter(|(_, src_dir)| max_matching_prefix ==
223+
matching_prefix_components(modified, src_dir)
224+
).map(|(unit, _)| unit);
225+
226+
result.extend(dirty_units.cloned());
227+
}
221228
}
222229
}
223230
result
@@ -344,7 +351,7 @@ impl Plan {
344351

345352
if dirties
346353
.iter()
347-
.any(|&(_, ref kind)| *kind == TargetKind::CustomBuild)
354+
.any(|&(_, ref target, _)| *target.kind() == TargetKind::CustomBuild)
348355
{
349356
WorkStatus::NeedsCargo(PackageArg::Packages(needed_packages))
350357
} else {
@@ -594,7 +601,7 @@ impl JobQueue {
594601
}
595602

596603
fn key_from_unit(unit: &Unit<'_>) -> UnitKey {
597-
(unit.pkg.package_id().clone(), unit.target.kind().clone())
604+
(unit.pkg.package_id().clone(), unit.target.clone(), unit.mode)
598605
}
599606

600607
macro_rules! print_dep_graph {
@@ -626,6 +633,7 @@ crate struct OwnedUnit {
626633
crate target: Target,
627634
crate profile: Profile,
628635
crate kind: Kind,
636+
crate mode: CompileMode,
629637
}
630638

631639
impl<'a> From<&'a Unit<'a>> for OwnedUnit {
@@ -635,6 +643,7 @@ impl<'a> From<&'a Unit<'a>> for OwnedUnit {
635643
target: unit.target.clone(),
636644
profile: unit.profile,
637645
kind: unit.kind,
646+
mode: unit.mode,
638647
}
639648
}
640649
}

0 commit comments

Comments
 (0)