Skip to content

Commit ae674a8

Browse files
Working patching MVP
Co-authored-by: Dan Johnson <[email protected]>
1 parent 848e4e7 commit ae674a8

File tree

4 files changed

+188
-108
lines changed

4 files changed

+188
-108
lines changed

crate_universe/src/context/crate_context.rs

+111-93
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//! Crate specific information embedded into [crate::context::Context] objects.
22
33
use std::collections::{BTreeMap, BTreeSet};
4-
use std::path::PathBuf;
4+
use std::path::{Path, PathBuf};
55

6-
use cargo_metadata::{Node, Package, PackageId};
6+
use cargo_metadata::{Node, Package, PackageId, Target};
77
use serde::{Deserialize, Serialize};
88

99
use crate::config::{CrateId, GenBinaries};
@@ -12,7 +12,9 @@ use crate::metadata::{
1212
};
1313
use crate::splicing::WorkspaceMetadata;
1414
use crate::utils::sanitize_module_name;
15-
use crate::utils::starlark::{Glob, SelectList, SelectMap, SelectStringDict, SelectStringList};
15+
use crate::utils::starlark::{
16+
Glob, GlobOrLabels, Label, SelectList, SelectMap, SelectStringDict, SelectStringList,
17+
};
1618

1719
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone)]
1820
pub struct CrateDependency {
@@ -43,8 +45,12 @@ pub struct TargetAttributes {
4345
/// The path to the crate's root source file, relative to the manifest.
4446
pub crate_root: Option<String>,
4547

46-
/// A glob pattern of all source files required by the target
47-
pub srcs: Glob,
48+
/// A glob pattern of all source files required by the target or a label
49+
/// pointing to a filegroup containing said glob (used for patching)
50+
pub srcs: GlobOrLabels,
51+
52+
/// A label for overriding compile_data, used for patching
53+
pub compile_data: Option<GlobOrLabels>,
4854
}
4955

5056
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone)]
@@ -656,95 +662,100 @@ impl CrateContext {
656662
.targets
657663
.iter()
658664
.flat_map(|target| {
665+
let attrs = get_attributes(target, package, workspace, package_root);
659666
target.kind.iter().filter_map(move |kind| {
660-
// Unfortunately, The package graph and resolve graph of cargo metadata have different representations
661-
// for the crate names (resolve graph sanitizes names to match module names) so to get the rest of this
662-
// content to align when rendering, the package target names are always sanitized.
663-
let crate_name = sanitize_module_name(&target.name);
664-
665-
// Locate the crate's root source file relative to the package root normalized for unix
666-
let crate_root = pathdiff::diff_paths(&target.src_path, package_root).map(
667-
// Normalize the path so that it always renders the same regardless of platform
668-
|root| root.to_string_lossy().replace('\\', "/"),
669-
);
670-
println!("{}", package.id);
671-
if package.id.repr.contains("(path+file://") {
672-
println!("");
673-
println!("{crate_name} {kind} {:?}", &crate_root);
674-
println!("src: {:?}", &target.src_path);
675-
println!("pkg: {:?}", package_root);
676-
println!("root: {:?}", &crate_root);
677-
println!("workspace: {:?}", workspace.workspace_prefix);
678-
let temp_components = std::env::temp_dir().components().count() + 1;
679-
println!("temp dir components to drop: {temp_components}");
680-
let real_root: PathBuf =
681-
package_root.components().skip(temp_components).collect();
682-
println!("ACTUAL FOR REAL ROOT: {}", real_root.to_string_lossy());
683-
println!("");
684-
}
685-
let crate_root = crate_root.map(|r| {
686-
if package.id.repr.contains("(path+file://") {
687-
let temp_components = std::env::temp_dir().components().count() + 1;
688-
package_root
689-
.components()
690-
.skip(temp_components)
691-
.collect::<PathBuf>()
692-
.join(r)
693-
.to_string_lossy()
694-
.to_string()
695-
} else {
696-
r
697-
}
698-
});
699-
700-
// Conditionally check to see if the dependencies is a build-script target
701-
if include_build_scripts && kind == "custom-build" {
702-
return Some(Rule::BuildScript(TargetAttributes {
703-
crate_name,
704-
crate_root,
705-
srcs: Glob::new_rust_srcs(),
706-
}));
707-
}
708-
709-
// Check to see if the dependencies is a proc-macro target
667+
let attrs = attrs.clone();
710668
if kind == "proc-macro" {
711-
return Some(Rule::ProcMacro(TargetAttributes {
712-
crate_name,
713-
crate_root,
714-
srcs: Glob::new_rust_srcs(),
715-
}));
716-
}
717-
718-
// Check to see if the dependencies is a library target
719-
if ["lib", "rlib"].contains(&kind.as_str()) {
720-
return Some(Rule::Library(TargetAttributes {
721-
crate_name,
722-
crate_root,
723-
srcs: Glob::new_rust_srcs(),
724-
}));
725-
}
726-
727-
// Check if the target kind is binary and is one of the ones included in gen_binaries
728-
if kind == "bin"
729-
&& match gen_binaries {
669+
Some(Rule::ProcMacro(attrs))
670+
} else if ["lib", "rlib"].contains(&kind.as_str()) {
671+
Some(Rule::Library(attrs))
672+
} else if include_build_scripts && kind == "custom-build" {
673+
let build_script_crate_root = attrs
674+
.crate_root
675+
.map(|s| s.replace(":crate_root", ":build_script_crate_root"));
676+
Some(Rule::BuildScript(TargetAttributes {
677+
crate_root: build_script_crate_root,
678+
..attrs
679+
}))
680+
} else if kind == "bin" {
681+
match gen_binaries {
730682
GenBinaries::All => true,
731683
GenBinaries::Some(set) => set.contains(&target.name),
732684
}
733-
{
734-
return Some(Rule::Binary(TargetAttributes {
735-
crate_name: target.name.clone(),
736-
crate_root,
737-
srcs: Glob::new_rust_srcs(),
738-
}));
685+
.then(|| {
686+
Rule::Binary(TargetAttributes {
687+
crate_name: target.name.clone(),
688+
..attrs
689+
})
690+
})
691+
} else {
692+
None
739693
}
740-
741-
None
742694
})
743695
})
744696
.collect()
745697
}
746698
}
747699

700+
fn get_attributes(
701+
target: &Target,
702+
package: &Package,
703+
workspace: &WorkspaceMetadata,
704+
package_root: &Path,
705+
) -> TargetAttributes {
706+
// Unfortunately, The package graph and resolve graph of cargo metadata have
707+
// different representations for the crate names (resolve graph sanitizes
708+
// names to match module names) so to get the rest of this content to align
709+
// when rendering, the package target names are always sanitized.
710+
let crate_name = sanitize_module_name(&target.name);
711+
712+
// Locate the crate's root source file relative to the package root normalized
713+
// for unix
714+
let crate_root = pathdiff::diff_paths(&target.src_path, package_root).map(
715+
// Normalize the path so that it always renders the same regardless of platform
716+
|root| root.to_string_lossy().replace('\\', "/"),
717+
);
718+
let local_patch = package.id.repr.contains("(path+file://");
719+
let temp_components = std::env::temp_dir().components().count() + 1;
720+
let real_root: PathBuf = package_root.components().skip(temp_components).collect();
721+
if !local_patch || real_root.as_os_str().is_empty() {
722+
TargetAttributes {
723+
crate_name,
724+
crate_root,
725+
srcs: Glob::new_rust_srcs().into(),
726+
compile_data: None,
727+
}
728+
} else {
729+
let root = real_root.display();
730+
let pkg = if let Some(workspace) = &workspace.workspace_prefix {
731+
format!("{workspace}/{}", root)
732+
} else {
733+
root.to_string()
734+
};
735+
// TODO: remove once added to help-docs
736+
println!("\nThere's a patch crate at '//{pkg}'.");
737+
println!("Make sure that '//{pkg}/BUILD.bazel' exposes the following filegroups:");
738+
println!("'crate_root', 'srcs', 'compile_data', and (if necessary) 'build_script'");
739+
let srcs = GlobOrLabels::Labels(vec![Label {
740+
repository: None,
741+
package: Some(pkg.clone()),
742+
target: "srcs".to_string(),
743+
}]);
744+
let compile_data = Some(GlobOrLabels::Labels(vec![Label {
745+
repository: None,
746+
package: Some(pkg.clone()),
747+
target: "compile_data".to_string(),
748+
}]));
749+
750+
TargetAttributes {
751+
crate_name,
752+
crate_root: Some(format!("//{pkg}:crate_root")),
753+
srcs,
754+
compile_data,
755+
}
756+
}
757+
}
758+
748759
#[cfg(test)]
749760
mod test {
750761
use super::*;
@@ -787,7 +798,8 @@ mod test {
787798
BTreeSet::from([Rule::Library(TargetAttributes {
788799
crate_name: "common".to_owned(),
789800
crate_root: Some("lib.rs".to_owned()),
790-
srcs: Glob::new_rust_srcs(),
801+
srcs: Glob::new_rust_srcs().into(),
802+
compile_data: None,
791803
})]),
792804
);
793805
}
@@ -819,7 +831,7 @@ mod test {
819831
let include_build_scripts = false;
820832
let context = CrateContext::new(
821833
crate_annotation,
822-
&annotations.metadata.packages,
834+
&annotations.metadata,
823835
&annotations.lockfile.crates,
824836
&pairred_extras,
825837
&annotations.features,
@@ -834,12 +846,14 @@ mod test {
834846
Rule::Library(TargetAttributes {
835847
crate_name: "common".to_owned(),
836848
crate_root: Some("lib.rs".to_owned()),
837-
srcs: Glob::new_rust_srcs(),
849+
srcs: Glob::new_rust_srcs().into(),
850+
compile_data: None,
838851
}),
839852
Rule::Binary(TargetAttributes {
840853
crate_name: "common-bin".to_owned(),
841854
crate_root: Some("main.rs".to_owned()),
842-
srcs: Glob::new_rust_srcs(),
855+
srcs: Glob::new_rust_srcs().into(),
856+
compile_data: None,
843857
}),
844858
]),
845859
);
@@ -882,7 +896,7 @@ mod test {
882896
let include_build_scripts = true;
883897
let context = CrateContext::new(
884898
crate_annotation,
885-
&annotations.metadata.packages,
899+
&annotations.metadata,
886900
&annotations.lockfile.crates,
887901
&annotations.pairred_extras,
888902
&annotations.features,
@@ -898,12 +912,14 @@ mod test {
898912
Rule::Library(TargetAttributes {
899913
crate_name: "openssl_sys".to_owned(),
900914
crate_root: Some("src/lib.rs".to_owned()),
901-
srcs: Glob::new_rust_srcs(),
915+
srcs: Glob::new_rust_srcs().into(),
916+
compile_data: None,
902917
}),
903918
Rule::BuildScript(TargetAttributes {
904919
crate_name: "build_script_main".to_owned(),
905920
crate_root: Some("build/main.rs".to_owned()),
906-
srcs: Glob::new_rust_srcs(),
921+
srcs: Glob::new_rust_srcs().into(),
922+
compile_data: None,
907923
})
908924
]),
909925
);
@@ -927,7 +943,7 @@ mod test {
927943
let include_build_scripts = false;
928944
let context = CrateContext::new(
929945
crate_annotation,
930-
&annotations.metadata.packages,
946+
&annotations.metadata,
931947
&annotations.lockfile.crates,
932948
&annotations.pairred_extras,
933949
&annotations.features,
@@ -942,7 +958,8 @@ mod test {
942958
BTreeSet::from([Rule::Library(TargetAttributes {
943959
crate_name: "openssl_sys".to_owned(),
944960
crate_root: Some("src/lib.rs".to_owned()),
945-
srcs: Glob::new_rust_srcs(),
961+
srcs: Glob::new_rust_srcs().into(),
962+
compile_data: None,
946963
})]),
947964
);
948965
}
@@ -962,7 +979,7 @@ mod test {
962979
let include_build_scripts = false;
963980
let context = CrateContext::new(
964981
crate_annotation,
965-
&annotations.metadata.packages,
982+
&annotations.metadata,
966983
&annotations.lockfile.crates,
967984
&annotations.pairred_extras,
968985
&annotations.features,
@@ -977,7 +994,8 @@ mod test {
977994
BTreeSet::from([Rule::Library(TargetAttributes {
978995
crate_name: "sysinfo".to_owned(),
979996
crate_root: Some("src/lib.rs".to_owned()),
980-
srcs: Glob::new_rust_srcs(),
997+
srcs: Glob::new_rust_srcs().into(),
998+
compile_data: None,
981999
})]),
9821000
);
9831001
}

crate_universe/src/rendering.rs

+24-11
Original file line numberDiff line numberDiff line change
@@ -328,11 +328,17 @@ impl Renderer {
328328
build_script_env: attrs
329329
.map_or_else(SelectDict::default, |attrs| attrs.build_script_env.clone())
330330
.remap_configurations(platforms),
331-
compile_data: make_data(
332-
platforms,
333-
&empty_set,
334-
attrs.map_or(&empty_list, |attrs| &attrs.compile_data),
335-
),
331+
compile_data: {
332+
let mut data = make_data(
333+
platforms,
334+
&empty_set,
335+
attrs.map_or(&empty_list, |attrs| &attrs.compile_data),
336+
);
337+
if let Some(cd) = &target.compile_data {
338+
data.glob = cd.clone();
339+
}
340+
data
341+
},
336342
crate_features: SelectList::from(&krate.common_attrs.crate_features)
337343
.map_configuration_names(|triple| {
338344
render_platform_constraint_label(&self.config.platforms_template, &triple)
@@ -479,11 +485,17 @@ impl Renderer {
479485
target: &TargetAttributes,
480486
) -> Result<CommonAttrs> {
481487
Ok(CommonAttrs {
482-
compile_data: make_data(
483-
platforms,
484-
&krate.common_attrs.compile_data_glob,
485-
&krate.common_attrs.compile_data,
486-
),
488+
compile_data: {
489+
let mut data = make_data(
490+
platforms,
491+
&krate.common_attrs.compile_data_glob,
492+
&krate.common_attrs.compile_data,
493+
);
494+
if let Some(cd) = &target.compile_data {
495+
data.glob = cd.clone();
496+
}
497+
data
498+
},
487499
crate_features: SelectList::from(&krate.common_attrs.crate_features)
488500
.map_configuration_names(|triple| {
489501
render_platform_constraint_label(&self.config.platforms_template, &triple)
@@ -719,7 +731,8 @@ fn make_data(platforms: &Platforms, glob: &BTreeSet<String>, select: &SelectList
719731
.iter()
720732
.map(|&glob| glob.to_owned())
721733
.collect(),
722-
},
734+
}
735+
.into(),
723736
select: select.clone().remap_configurations(platforms),
724737
}
725738
}

crate_universe/src/utils/starlark.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ pub struct CargoBuildScript {
122122
serialize_with = "SelectList::serialize_starlark"
123123
)]
124124
pub rustc_flags: SelectList<WithOriginalConfigurations<String>>,
125-
pub srcs: Glob,
125+
pub srcs: GlobOrLabels,
126126
#[serde(skip_serializing_if = "Set::is_empty")]
127127
pub tags: Set<String>,
128128
#[serde(
@@ -232,14 +232,14 @@ pub struct CommonAttrs {
232232
pub rustc_env_files: SelectList<WithOriginalConfigurations<String>>,
233233
#[serde(skip_serializing_if = "Vec::is_empty")]
234234
pub rustc_flags: Vec<String>,
235-
pub srcs: Glob,
235+
pub srcs: GlobOrLabels,
236236
#[serde(skip_serializing_if = "Set::is_empty")]
237237
pub tags: Set<String>,
238238
pub version: String,
239239
}
240240

241241
pub struct Data {
242-
pub glob: Glob,
242+
pub glob: GlobOrLabels,
243243
pub select: SelectList<WithOriginalConfigurations<String>>,
244244
}
245245

0 commit comments

Comments
 (0)