Skip to content

Commit

Permalink
Filter out crates that depend on build scripts, and crates that depen…
Browse files Browse the repository at this point in the history
…d on other uncachable crates
  • Loading branch information
dpaoliello committed Sep 13, 2023
1 parent 9561c72 commit e8cf2b3
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 10 deletions.
47 changes: 38 additions & 9 deletions src/cargo/core/compiler/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ pub trait Cache: Send + Sync {
package_id: &PackageId,
fingerprint: &Fingerprint,
target_kind: &TargetKind,
all_deps: &[(PackageId, TargetKind)],
outputs: &[OutputFile],
) -> CargoResult<bool>;
fn put(
&self,
package_id: &PackageId,
fingerprint: &Fingerprint,
target_kind: &TargetKind,
all_deps: &[(PackageId, TargetKind)],
outputs: &[OutputFile],
) -> CargoResult<()>;
}
Expand Down Expand Up @@ -111,12 +113,29 @@ struct CacheMetadata {
}

impl LocalCache {
fn is_cachable(package_id: &PackageId) -> bool {
fn is_cachable(package_id: &PackageId, all_deps: Option<&[(PackageId, TargetKind)]>) -> bool {
if !package_id.source_id().is_remote_registry() {
tracing::debug!("'{package_id:?}' is uncachable: unsupported registry");
tracing::debug!("'{package_id}' is uncachable: unsupported registry");
return false;
}

if let Some(all_deps) = all_deps {
if all_deps
.iter()
.any(|(_, tk)| matches!(tk, TargetKind::CustomBuild))
{
tracing::debug!("'{package_id}' is uncachable: depends on build script");
}

if !all_deps
.iter()
.all(|(p, _)| LocalCache::is_cachable(p, None))
{
tracing::debug!("'{package_id}' is uncachable: dependency is uncachable");
return false;
}
}

true
}
}
Expand All @@ -127,9 +146,10 @@ impl Cache for LocalCache {
package_id: &PackageId,
fingerprint: &Fingerprint,
target_kind: &TargetKind,
all_deps: &[(PackageId, TargetKind)],
outputs: &[OutputFile],
) -> CargoResult<bool> {
if !LocalCache::is_cachable(package_id) {
if !LocalCache::is_cachable(package_id, Some(all_deps)) {
return Ok(false);
}

Expand All @@ -148,9 +168,15 @@ impl Cache for LocalCache {
// TODO Try to hardlink, fallback to copy (reflink is only supported for ReFS).
// TODO What if the file already exists? Skip or overwrite?
if cacache::copy_hash_sync(&self.cache_directory, sri, &output.path).is_ok() {
tracing::debug!("GET: Found '{output:?}' for '{package_id:?}' (as {target_kind:?}) in cache, copying to target dir");
tracing::debug!(
"GET: Found {flavor:?} for '{package_id}' (as {target_kind:?}) in cache, copying to target dir",
flavor=output.flavor
);
} else {
tracing::debug!("GET: Did not find '{output:?}' for '{package_id:?}' (as {target_kind:?}) in cache");
tracing::debug!(
"GET: Did not find {flavor:?} for '{package_id}' (as {target_kind:?}) in cache",
flavor=output.flavor
);
all_found = false;
}
}
Expand All @@ -163,9 +189,10 @@ impl Cache for LocalCache {
package_id: &PackageId,
fingerprint: &Fingerprint,
target_kind: &TargetKind,
all_deps: &[(PackageId, TargetKind)],
outputs: &[OutputFile],
) -> CargoResult<()> {
if !LocalCache::is_cachable(package_id) {
if !LocalCache::is_cachable(package_id, Some(all_deps)) {
return Ok(());
}

Expand All @@ -179,8 +206,9 @@ impl Cache for LocalCache {
for output in outputs {
// Entry exists and has data, nothing to do.
tracing::debug!(
"PUT: Found '{output:?}' for '{package_id:?}' (as {target_kind:?}) in cache, skipping update"
);
"PUT: Found {flavor:?} for '{package_id}' (as {target_kind:?}) in cache, skipping update",
flavor=output.flavor
);
}
}
_ => {}
Expand All @@ -192,7 +220,8 @@ impl Cache for LocalCache {

for output in outputs {
tracing::debug!(
"PUT: Adding '{output:?}' for '{package_id:?}' (as {target_kind:?}) to cache"
"PUT: Adding {flavor:?} for '{package_id}' (as {target_kind:?}) to cache",
flavor=output.flavor
);
let mut writer = cacache::WriteOpts::new().open_hash_sync(&self.cache_directory)?;
io::copy(
Expand Down
15 changes: 15 additions & 0 deletions src/cargo/core/compiler/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,21 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
&self.bcx.unit_graph[unit]
}

/// all direct and indirect dependencies for the given unit.
pub fn all_unit_deps(&self, unit: &Unit) -> Vec<UnitDep> {
fn add_deps(context: &Context<'_, '_>, unit: &Unit, deps: &mut HashSet<UnitDep>) {
for dep in context.unit_deps(unit) {
if deps.insert(dep.clone()) {
add_deps(context, &dep.unit, deps);
}
}
}

let mut deps = HashSet::new();
add_deps(self, unit, &mut deps);
deps.into_iter().collect::<_>()
}

/// Returns the RunCustomBuild Unit associated with the given Unit.
///
/// If the package does not have a build script, this returns None.
Expand Down
13 changes: 12 additions & 1 deletion src/cargo/core/compiler/fingerprint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,9 +538,14 @@ fn cache_artifact(
let cache = cx.artifact_cache.clone();
let package_id = unit.pkg.package_id();
let target_kind = unit.target.kind().clone();
let all_deps = cx
.all_unit_deps(&unit)
.iter()
.map(|ud| (ud.unit.pkg.package_id(), ud.unit.target.kind().clone()))
.collect::<Vec<_>>();

Ok(Work::new(move |_state| {
if let Err(err) = cache.put(&package_id, &fingerprint, &target_kind, &outputs) {
if let Err(err) = cache.put(&package_id, &fingerprint, &target_kind, &all_deps, &outputs) {
tracing::warn!("failed to PUT {package_id} in cache: {err}")
}
Ok(())
Expand Down Expand Up @@ -1368,10 +1373,16 @@ fn calculate(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Arc<Fingerpri
calculate_normal(cx, unit)?
};

let all_deps = cx
.all_unit_deps(&unit)
.iter()
.map(|ud| (ud.unit.pkg.package_id(), ud.unit.target.kind().clone()))
.collect::<Vec<_>>();
let use_cache = match cx.artifact_cache.get(
&unit.pkg.package_id(),
&fingerprint,
unit.target.kind(),
&all_deps,
&cx.outputs(unit)?,
) {
Ok(val) => val,
Expand Down

0 comments on commit e8cf2b3

Please sign in to comment.