Skip to content

Commit b249c70

Browse files
committed
crate_universe: synthesize build-script edge at render time
A library/binary/proc-macro built from a crate with a build script depends on that crate's own build_script_build target. That edge was recorded as a self-referential entry in common_attrs.deps, which also feeds workspace_member_deps() and produced a spurious crate-hub alias for any workspace member that is a library with a build script (issue #4089). Stop recording the self-edge in common_attrs.deps (reserved for cross-crate deps) and instead synthesize the build_script_build edge during rendering from the presence of the build-script target. workspace_member_deps() then naturally excludes it with no filtering. Upstream issue: #4089
1 parent fb01b69 commit b249c70

3 files changed

Lines changed: 36 additions & 30 deletions

File tree

crate_universe/src/context.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,6 @@ mod test {
412412
.map(|dep| (&dep.id, context.has_duplicate_workspace_member_dep_by_alias(dep)))
413413
.collect::<Vec<_>>(),
414414
[
415-
(&CrateId::new("child".to_owned(), Version::new(0, 1, 0)), false),
416415
(&CrateId::new("tonic".to_owned(), Version::new(0, 4, 3)), false),
417416
(&CrateId::new("tonic-build".to_owned(), Version::new(0, 4, 2)), false),
418417
],

crate_universe/src/context/crate_context.rs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ impl CrateContext {
431431
.unwrap_or_default();
432432

433433
// Gather all "common" attributes
434-
let mut common_attrs = CommonAttributes {
434+
let common_attrs = CommonAttributes {
435435
crate_features,
436436
deps,
437437
deps_dev,
@@ -494,21 +494,7 @@ impl CrateContext {
494494
_ => None,
495495
});
496496

497-
let build_script_attrs = if let Some(target) = build_script_target {
498-
// Track the build script dependency
499-
common_attrs.deps.insert(
500-
CrateDependency {
501-
id: current_crate_id,
502-
target: target.crate_name.clone(),
503-
alias: None,
504-
local_path: match source_annotations.get(&annotation.node.id) {
505-
Some(SourceAnnotation::Path { path }) => Some(path.clone()),
506-
_ => None,
507-
},
508-
},
509-
None,
510-
);
511-
497+
let build_script_attrs = if build_script_target.is_some() {
512498
let build_deps = annotation.deps.build_deps.clone().map(new_crate_dep);
513499
let build_link_deps = annotation.deps.build_link_deps.clone().map(new_crate_dep);
514500
let build_proc_macro_deps = annotation

crate_universe/src/rendering.rs

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::sync::Arc;
1111
use anyhow::{bail, Context as AnyhowContext, Result};
1212
use itertools::Itertools;
1313

14-
use crate::config::{AliasRule, RenderConfig, VendorMode};
14+
use crate::config::{AliasRule, CrateId, RenderConfig, VendorMode};
1515
use crate::context::crate_context::{CrateContext, CrateDependency, Rule};
1616
use crate::context::{Context, TargetAttributes};
1717
use crate::metadata::SourceAnnotation;
@@ -680,13 +680,14 @@ impl Renderer {
680680
krate: &CrateContext,
681681
target: &TargetAttributes,
682682
) -> Result<RustProcMacro> {
683+
let mut deps = krate.common_attrs.deps.clone();
684+
if let Some(dep) = build_script_dep(krate) {
685+
deps.insert(dep, None);
686+
}
683687
Ok(RustProcMacro {
684688
name: target.crate_name.clone(),
685689
deps: SelectSet::new(
686-
self.make_deps(
687-
krate.common_attrs.deps.clone(),
688-
krate.common_attrs.extra_deps.clone(),
689-
),
690+
self.make_deps(deps, krate.common_attrs.extra_deps.clone()),
690691
platforms,
691692
),
692693
proc_macro_deps: SelectSet::new(
@@ -707,13 +708,14 @@ impl Renderer {
707708
krate: &CrateContext,
708709
target: &TargetAttributes,
709710
) -> Result<RustLibrary> {
711+
let mut deps = krate.common_attrs.deps.clone();
712+
if let Some(dep) = build_script_dep(krate) {
713+
deps.insert(dep, None);
714+
}
710715
Ok(RustLibrary {
711716
name: target.crate_name.clone(),
712717
deps: SelectSet::new(
713-
self.make_deps(
714-
krate.common_attrs.deps.clone(),
715-
krate.common_attrs.extra_deps.clone(),
716-
),
718+
self.make_deps(deps, krate.common_attrs.extra_deps.clone()),
717719
platforms,
718720
),
719721
proc_macro_deps: SelectSet::new(
@@ -742,10 +744,11 @@ impl Renderer {
742744
.iter()
743745
.any(|rule| matches!(rule, Rule::ProcMacro(_)));
744746

745-
let mut deps = self.make_deps(
746-
krate.common_attrs.deps.clone(),
747-
krate.common_attrs.extra_deps.clone(),
748-
);
747+
let mut crate_deps = krate.common_attrs.deps.clone();
748+
if let Some(dep) = build_script_dep(krate) {
749+
crate_deps.insert(dep, None);
750+
}
751+
let mut deps = self.make_deps(crate_deps, krate.common_attrs.extra_deps.clone());
749752
let mut proc_macro_deps = self.make_deps(
750753
krate.common_attrs.proc_macro_deps.clone(),
751754
krate.common_attrs.extra_proc_macro_deps.clone(),
@@ -1009,6 +1012,24 @@ fn render_build_file_template(template: &str, name: &str, version: &str) -> Resu
10091012
)
10101013
}
10111014

1015+
/// A crate depends on its own build script for the script's generated outputs.
1016+
/// Returns that `build_script_build` target as a dependency, if the crate has one.
1017+
fn build_script_dep(krate: &CrateContext) -> Option<CrateDependency> {
1018+
let target = krate.targets.iter().find_map(|t| match t {
1019+
Rule::BuildScript(attrs) => Some(attrs.crate_name.clone()),
1020+
_ => None,
1021+
})?;
1022+
Some(CrateDependency {
1023+
id: CrateId::new(krate.name.clone(), krate.version.clone()),
1024+
target,
1025+
alias: None,
1026+
local_path: match &krate.repository {
1027+
Some(SourceAnnotation::Path { path }) => Some(path.clone()),
1028+
_ => None,
1029+
},
1030+
})
1031+
}
1032+
10121033
fn make_data_with_exclude(
10131034
platforms: &Platforms,
10141035
include: BTreeSet<String>,

0 commit comments

Comments
 (0)