diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 0003e2b36d..8367e9a5b2 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -79,6 +79,7 @@ crate_universe_vendor_example_targets: &crate_universe_vendor_example_targets - "//vendor_external:crates_vendor" - "//vendor_local_manifests:crates_vendor" - "//vendor_local_pkgs:crates_vendor" + - "//vendor_local_patching:crates_vendor" - "//vendor_remote_manifests:crates_vendor" - "//vendor_remote_pkgs:crates_vendor" - "@rules_rust//tools/rust_analyzer:gen_rust_project" diff --git a/crate_universe/Cargo.toml b/crate_universe/Cargo.toml index 22475453b4..c46c26e3e8 100644 --- a/crate_universe/Cargo.toml +++ b/crate_universe/Cargo.toml @@ -21,6 +21,7 @@ exclude = [ "test_data/metadata/multi_kind_proc_macro_dep", "test_data/metadata/nested_build_dependencies", "test_data/metadata/no_deps", + "test_data/metadata/path_patching", "test_data/metadata/resolver_2_deps", "test_data/metadata/target_cfg_features", "test_data/metadata/target_features", diff --git a/crate_universe/extensions.bzl b/crate_universe/extensions.bzl index 6f50f0f04f..df046106f8 100644 --- a/crate_universe/extensions.bzl +++ b/crate_universe/extensions.bzl @@ -713,9 +713,9 @@ def _generate_hub_and_spokes( version = version.replace("+", "-"), ) - build_file_content = module_ctx.read(crates_dir.get_child("BUILD.%s-%s.bazel" % (name, version))) if "Http" in repo: # Replicates functionality in repo_http.j2. + build_file_content = module_ctx.read(crates_dir.get_child("BUILD.%s-%s.bazel" % (name, version))) repo = repo["Http"] http_archive( name = crate_repo_name, @@ -731,6 +731,7 @@ def _generate_hub_and_spokes( ) elif "Git" in repo: # Replicates functionality in repo_git.j2 + build_file_content = module_ctx.read(crates_dir.get_child("BUILD.%s-%s.bazel" % (name, version))) repo = repo["Git"] kwargs = {} for k, v in repo["commitish"].items(): diff --git a/crate_universe/src/api/lockfile.rs b/crate_universe/src/api/lockfile.rs index 0cbf017419..f32f7bf94c 100644 --- a/crate_universe/src/api/lockfile.rs +++ b/crate_universe/src/api/lockfile.rs @@ -176,6 +176,7 @@ mod test { }, target: String::from("anyhow"), alias: None, + source_annotation: None, }, CrateDependency { id: CrateId { @@ -184,6 +185,7 @@ mod test { }, target: String::from("reqwest"), alias: None, + source_annotation: None, }, ], ); diff --git a/crate_universe/src/cli/generate.rs b/crate_universe/src/cli/generate.rs index 88a422516c..1769683fc0 100644 --- a/crate_universe/src/cli/generate.rs +++ b/crate_universe/src/cli/generate.rs @@ -158,11 +158,22 @@ pub fn generate(opt: GenerateOptions) -> Result<()> { }; // Load Metadata and Lockfile - let (cargo_metadata, cargo_lockfile) = load_metadata(metadata_path)?; + let lockfile_path = metadata_path + .parent() + .expect("metadata files should always have parents") + .join("Cargo.lock"); + if !lockfile_path.exists() { + bail!( + "The metadata file at {} is not next to a `Cargo.lock` file.", + metadata_path.display() + ) + } + let (cargo_metadata, cargo_lockfile) = load_metadata(metadata_path, &lockfile_path)?; // Annotate metadata let annotations = Annotations::new( cargo_metadata, + &Some(lockfile_path), cargo_lockfile.clone(), config.clone(), &opt.nonhermetic_root_bazel_workspace_dir, diff --git a/crate_universe/src/cli/vendor.rs b/crate_universe/src/cli/vendor.rs index ec5dab83ff..ce480658fd 100644 --- a/crate_universe/src/cli/vendor.rs +++ b/crate_universe/src/cli/vendor.rs @@ -249,6 +249,7 @@ pub fn vendor(opt: VendorOptions) -> anyhow::Result<()> { // Annotate metadata let annotations = Annotations::new( cargo_metadata, + &opt.cargo_lockfile, cargo_lockfile.clone(), config.clone(), &opt.nonhermetic_root_bazel_workspace_dir, diff --git a/crate_universe/src/context.rs b/crate_universe/src/context.rs index 54568b6447..4c4f76cb9b 100644 --- a/crate_universe/src/context.rs +++ b/crate_universe/src/context.rs @@ -269,6 +269,7 @@ mod test { fn mock_context_common() -> Context { let annotations = Annotations::new( crate::test::metadata::common(), + &None, crate::test::lockfile::common(), Config::default(), Utf8Path::new("/tmp/bazelworkspace"), @@ -281,6 +282,7 @@ mod test { fn mock_context_aliases() -> Context { let annotations = Annotations::new( crate::test::metadata::alias(), + &None, crate::test::lockfile::alias(), Config::default(), Utf8Path::new("/tmp/bazelworkspace"), @@ -293,6 +295,7 @@ mod test { fn mock_context_workspace_build_scripts_deps() -> Context { let annotations = Annotations::new( crate::test::metadata::workspace_build_scripts_deps(), + &None, crate::test::lockfile::workspace_build_scripts_deps(), Config { generate_build_scripts: true, diff --git a/crate_universe/src/context/crate_context.rs b/crate_universe/src/context/crate_context.rs index 6271e9d87c..aeedd3941a 100644 --- a/crate_universe/src/context/crate_context.rs +++ b/crate_universe/src/context/crate_context.rs @@ -25,6 +25,10 @@ pub struct CrateDependency { /// Some dependencies are assigned aliases. This is tracked here #[serde(default, skip_serializing_if = "Option::is_none")] pub alias: Option, + + /// Where to acquire the source of this dependency. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub(crate) source_annotation: Option, } #[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone)] @@ -378,6 +382,7 @@ impl CrateContext { id: CrateId::new(pkg.name.clone(), pkg.version.clone()), target, alias: dep.alias, + source_annotation: Some(source_annotations[&dep.package_id].clone()), } }; @@ -475,6 +480,7 @@ impl CrateContext { id: current_crate_id, target: target.crate_name.clone(), alias: None, + source_annotation: source_annotations.get(&annotation.node.id).cloned(), }, None, ); @@ -874,6 +880,7 @@ mod test { fn common_annotations() -> Annotations { Annotations::new( crate::test::metadata::common(), + &None, crate::test::lockfile::common(), crate::config::Config::default(), Utf8Path::new("/tmp/bazelworkspace"), @@ -978,6 +985,7 @@ mod test { fn build_script_annotations() -> Annotations { Annotations::new( crate::test::metadata::build_scripts(), + &None, crate::test::lockfile::build_scripts(), crate::config::Config::default(), Utf8Path::new("/tmp/bazelworkspace"), @@ -988,6 +996,7 @@ mod test { fn crate_type_annotations() -> Annotations { Annotations::new( crate::test::metadata::crate_types(), + &None, crate::test::lockfile::crate_types(), crate::config::Config::default(), Utf8Path::new("/tmp/bazelworkspace"), @@ -1292,6 +1301,7 @@ mod test { fn absolute_paths_for_srcs_are_errors() { let annotations = Annotations::new( crate::test::metadata::abspath(), + &None, crate::test::lockfile::abspath(), crate::config::Config::default(), Utf8Path::new("/tmp/bazelworkspace"), diff --git a/crate_universe/src/context/platforms.rs b/crate_universe/src/context/platforms.rs index 3a1656b1be..6897e733c8 100644 --- a/crate_universe/src/context/platforms.rs +++ b/crate_universe/src/context/platforms.rs @@ -135,6 +135,7 @@ mod test { id: CrateId::new("mock_crate_b".to_owned(), VERSION_ZERO_ONE_ZERO), target: "mock_crate_b".to_owned(), alias: None, + source_annotation: None, }, None, ); @@ -193,6 +194,7 @@ mod test { id: CrateId::new("mock_crate_b".to_owned(), VERSION_ZERO_ONE_ZERO), target: "mock_crate_b".to_owned(), alias: None, + source_annotation: None, }, Some(configuration), ); @@ -279,6 +281,7 @@ mod test { id: CrateId::new("mock_crate_b".to_owned(), VERSION_ZERO_ONE_ZERO), target: "mock_crate_b".to_owned(), alias: None, + source_annotation: None, }, Some(configuration.clone()), ); @@ -345,6 +348,7 @@ mod test { id: CrateId::new("mock_crate_b".to_owned(), VERSION_ZERO_ONE_ZERO), target: "mock_crate_b".to_owned(), alias: None, + source_annotation: None, }, Some(configuration.clone()), ); diff --git a/crate_universe/src/metadata.rs b/crate_universe/src/metadata.rs index dce766f667..7cb24b839c 100644 --- a/crate_universe/src/metadata.rs +++ b/crate_universe/src/metadata.rs @@ -353,26 +353,15 @@ pub(crate) fn write_metadata(path: &Path, metadata: &cargo_metadata::Metadata) - /// A helper function for deserializing Cargo metadata and lockfiles pub(crate) fn load_metadata( metadata_path: &Path, + lockfile_path: &Path, ) -> Result<(cargo_metadata::Metadata, cargo_lock::Lockfile)> { - // Locate the Cargo.lock file related to the metadata file. - let lockfile_path = metadata_path - .parent() - .expect("metadata files should always have parents") - .join("Cargo.lock"); - if !lockfile_path.exists() { - bail!( - "The metadata file at {} is not next to a `Cargo.lock` file.", - metadata_path.display() - ) - } - let content = fs::read_to_string(metadata_path) .with_context(|| format!("Failed to load Cargo Metadata: {}", metadata_path.display()))?; let metadata = serde_json::from_str(&content).context("Unable to deserialize Cargo metadata")?; - let lockfile = cargo_lock::Lockfile::load(&lockfile_path) + let lockfile = cargo_lock::Lockfile::load(lockfile_path) .with_context(|| format!("Failed to load lockfile: {}", lockfile_path.display()))?; Ok((metadata, lockfile)) diff --git a/crate_universe/src/metadata/metadata_annotation.rs b/crate_universe/src/metadata/metadata_annotation.rs index 7dffb42f29..b386d9b6f9 100644 --- a/crate_universe/src/metadata/metadata_annotation.rs +++ b/crate_universe/src/metadata/metadata_annotation.rs @@ -3,7 +3,7 @@ use std::collections::{BTreeMap, BTreeSet}; use std::path::PathBuf; -use anyhow::{bail, Result}; +use anyhow::{bail, Context, Result}; use camino::{Utf8Path, Utf8PathBuf}; use cargo_metadata::{Node, Package, PackageId}; use hex::ToHex; @@ -164,6 +164,7 @@ pub(crate) enum SourceAnnotation { patches: Option>, }, Path { + /// Local path to crate's source, relative to Bazel workspace root. path: Utf8PathBuf, }, } @@ -181,6 +182,7 @@ pub(crate) struct LockfileAnnotation { impl LockfileAnnotation { pub(crate) fn new( + lockfile_path: &Option, lockfile: CargoLockfile, metadata: &CargoMetadata, nonhermetic_root_bazel_workspace_dir: &Utf8Path, @@ -205,6 +207,7 @@ impl LockfileAnnotation { Self::collect_source_annotations( node, metadata, + lockfile_path, &lockfile, &workspace_metadata, nonhermetic_root_bazel_workspace_dir, @@ -225,6 +228,7 @@ impl LockfileAnnotation { fn collect_source_annotations( node: &Node, metadata: &CargoMetadata, + lockfile_path: &Option, lockfile: &CargoLockfile, workspace_metadata: &WorkspaceMetadata, nonhermetic_root_bazel_workspace_dir: &Utf8Path, @@ -265,14 +269,36 @@ impl LockfileAnnotation { .strip_prefix(&metadata.workspace_root) { Ok(suffix) => { - // Replace path within our temporary cargo workspace we ran `cargo metadata`` in with path within the actual Bazel workspace. + // Replace path within our temporary cargo workspace we ran `cargo metadata` in with path within the actual Bazel workspace. // This replacement allows in-repo patches sections to work as intended using local_crate_mirror. - let mut new_path = - nonhermetic_root_bazel_workspace_dir.to_owned(); - if let Some(prefix) = - workspace_metadata.workspace_prefix.as_ref() - { - new_path.push(prefix); + let mut new_path = Utf8PathBuf::new(); + if let Some(path) = lockfile_path { + // If a lockfile path is provided, figure out the path of + // its parent directory (relative to Bazel workspace root), + // since `suffix` is relative to it in the actual Bazel + // workspace. + let p = Utf8Path::from_path( + path.parent() + .context("unexpected empty lockfile path")?, + ) + .context("unxpected non-Unicode lockfile path")?; + if p.starts_with(nonhermetic_root_bazel_workspace_dir) { + // If path in lockfile is under Bazel root, strip Bazel + // root to get the actual path. + let relative_lockfile_path = p.strip_prefix(nonhermetic_root_bazel_workspace_dir) + .context("unexpected lockfile path not under root Bazel workspace")?; + new_path.push(relative_lockfile_path); + } else { + // If path in lockfile is not under Bazel root, we are + // likely in a temporary directory, so rebase to Bazel + // root. + new_path.push(nonhermetic_root_bazel_workspace_dir); + if let Some(prefix) = + workspace_metadata.workspace_prefix.as_ref() + { + new_path.push(prefix); + } + } } new_path.push(suffix); new_path @@ -422,11 +448,13 @@ pub(crate) struct Annotations { impl Annotations { pub(crate) fn new( cargo_metadata: CargoMetadata, + cargo_lockfile_path: &Option, cargo_lockfile: CargoLockfile, config: Config, nonhermetic_root_bazel_workspace_dir: &Utf8Path, ) -> Result { let lockfile_annotation = LockfileAnnotation::new( + cargo_lockfile_path, cargo_lockfile, &cargo_metadata, nonhermetic_root_bazel_workspace_dir, @@ -560,6 +588,7 @@ mod test { #[test] fn annotate_lockfile_with_aliases() { LockfileAnnotation::new( + &None, test::lockfile::alias(), &test::metadata::alias(), Utf8Path::new("/tmp/bazelworkspace"), @@ -575,6 +604,7 @@ mod test { #[test] fn annotate_lockfile_with_build_scripts() { LockfileAnnotation::new( + &None, test::lockfile::build_scripts(), &test::metadata::build_scripts(), Utf8Path::new("/tmp/bazelworkspace"), @@ -585,6 +615,7 @@ mod test { #[test] fn annotate_lockfile_with_no_deps() { LockfileAnnotation::new( + &None, test::lockfile::no_deps(), &test::metadata::no_deps(), Utf8Path::new("/tmp/bazelworkspace"), @@ -595,6 +626,7 @@ mod test { #[test] fn detects_strip_prefix_for_git_repo() { let crates = LockfileAnnotation::new( + &None, test::lockfile::git_repos(), &test::metadata::git_repos(), Utf8Path::new("/tmp/bazelworkspace"), @@ -622,6 +654,7 @@ mod test { #[test] fn resolves_commit_from_branches_and_tags() { let crates = LockfileAnnotation::new( + &None, test::lockfile::git_repos(), &test::metadata::git_repos(), Utf8Path::new("/tmp/bazelworkspace"), @@ -645,6 +678,27 @@ mod test { ); } + #[test] + fn detects_local_path_patching() { + let crates = LockfileAnnotation::new( + &None, + test::lockfile::path_patching(), + &test::metadata::path_patching(), + Utf8Path::new("/tmp/bazelworkspace"), + ) + .unwrap() + .crates; + + // We can't reliably construct the PackageId because it'll contain local absolute paths, + // so compare the entire container, which should only have one element anyways. + assert_eq!( + crates.into_values().collect::>(), + [SourceAnnotation::Path { + path: "child_a".into() + }] + ); + } + #[test] fn detect_unused_annotation() { // Create a config with some random annotation @@ -656,6 +710,7 @@ mod test { let result = Annotations::new( test::metadata::no_deps(), + &None, test::lockfile::no_deps(), config, Utf8Path::new("/tmp/bazelworkspace"), @@ -694,6 +749,7 @@ mod test { // crate author in package metadata. let combined_annotations = Annotations::new( test::metadata::has_package_metadata(), + &None, test::lockfile::has_package_metadata(), config, Utf8Path::new("/tmp/bazelworkspace"), diff --git a/crate_universe/src/rendering.rs b/crate_universe/src/rendering.rs index f4ea032015..93f219b8e7 100644 --- a/crate_universe/src/rendering.rs +++ b/crate_universe/src/rendering.rs @@ -14,6 +14,7 @@ use itertools::Itertools; use crate::config::{AliasRule, RenderConfig, VendorMode}; use crate::context::crate_context::{CrateContext, CrateDependency, Rule}; use crate::context::{Context, TargetAttributes}; +use crate::metadata::SourceAnnotation; use crate::rendering::template_engine::TemplateEngine; use crate::select::Select; use crate::splicing::default_splicing_package_crate_id; @@ -343,7 +344,10 @@ impl Renderer { Err(e) => bail!(e), }; - let filename = Renderer::label_to_path(&label); + let filename = match &context.crates[id].repository { + Some(SourceAnnotation::Path { path }) => path.join("BUILD.bazel").into(), + _ => Renderer::label_to_path(&label), + }; let content = self.render_one_build_file(engine, platforms, &context.crates[id])?; Ok((filename, content)) }) @@ -819,8 +823,11 @@ impl Renderer { extra_deps: Select>, ) -> Select> { Select::merge( - deps.map(|dep| { - self.crate_label(&dep.id.name, &dep.id.version.to_string(), &dep.target) + deps.map(|dep| match dep.source_annotation { + Some(SourceAnnotation::Path { path }) => { + Label::from_str(&format!("//{}:{}", path, &dep.target)).unwrap() + } + _ => self.crate_label(&dep.id.name, &dep.id.version.to_string(), &dep.target), }), extra_deps, ) @@ -1380,6 +1387,7 @@ mod test { }; let annotations = Annotations::new( test::metadata::alias(), + &None, test::lockfile::alias(), config, Utf8Path::new("/tmp/bazelworkspace"), @@ -1592,6 +1600,7 @@ mod test { let annotations = Annotations::new( metadata, + &None, lockfile, config.clone(), Utf8Path::new("/tmp/bazelworkspace"), @@ -1980,6 +1989,7 @@ mod test { // this is identical to what we have in the `name` attribute // which creates conflict in `render_module_build_file` alias: Some("mock_crate".into()), + source_annotation: None, }])), ..Default::default() }, diff --git a/crate_universe/src/test.rs b/crate_universe/src/test.rs index 50b4d951c2..e8bc5822a0 100644 --- a/crate_universe/src/test.rs +++ b/crate_universe/src/test.rs @@ -109,6 +109,14 @@ pub(crate) mod metadata { .unwrap() } + pub(crate) fn path_patching() -> cargo_metadata::Metadata { + serde_json::from_str(include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/test_data/metadata/path_patching/metadata.json" + ))) + .unwrap() + } + pub(crate) fn optional_deps_disabled() -> cargo_metadata::Metadata { serde_json::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), @@ -249,6 +257,14 @@ pub(crate) mod lockfile { .unwrap() } + pub(crate) fn path_patching() -> cargo_lock::Lockfile { + cargo_lock::Lockfile::from_str(include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/test_data/metadata/path_patching/Cargo.lock" + ))) + .unwrap() + } + pub(crate) fn common() -> cargo_lock::Lockfile { cargo_lock::Lockfile::from_str(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), diff --git a/crate_universe/src/utils.rs b/crate_universe/src/utils.rs index 041b8f5655..7d35660c51 100644 --- a/crate_universe/src/utils.rs +++ b/crate_universe/src/utils.rs @@ -23,7 +23,7 @@ pub(crate) fn sanitize_repository_name(name: &str) -> String { /// Vendored crates are generated by cargo itself in `src/metadata.rs` in the /// `VendorGenerator::generate()` method. This means that the semver metadata will -/// always contain a (+) symbol, which is not compatible with bazel's labels. +/// always contain a (+) symbol, which is not compatible with bazel's labels. /// This function will rename the cargo vendor generated file paths to be compatible with bazel /// labels by simply replacing the (+) with a (-). If this file is called by any other cli mod, /// it just simply joins the out dir to the path diff --git a/crate_universe/test_data/metadata/path_patching/Cargo.lock b/crate_universe/test_data/metadata/path_patching/Cargo.lock new file mode 100644 index 0000000000..31d6831d77 --- /dev/null +++ b/crate_universe/test_data/metadata/path_patching/Cargo.lock @@ -0,0 +1,14 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "child_a" +version = "1.4.2" + +[[package]] +name = "path_patching" +version = "0.1.0" +dependencies = [ + "child_a", +] diff --git a/crate_universe/test_data/metadata/path_patching/Cargo.toml b/crate_universe/test_data/metadata/path_patching/Cargo.toml new file mode 100644 index 0000000000..5f8a8c22a9 --- /dev/null +++ b/crate_universe/test_data/metadata/path_patching/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "path_patching" +version = "0.1.0" +edition = "2018" + +# Required to satisfy cargo but no `lib.rs` is expected to +# exist within test data. +[lib] +path = "lib.rs" + +[dependencies] +child_a = "1.4.2" + +[patch.crates-io] +child_a = { path = "child_a" } diff --git a/crate_universe/test_data/metadata/path_patching/child_a/Cargo.toml b/crate_universe/test_data/metadata/path_patching/child_a/Cargo.toml new file mode 100644 index 0000000000..dbd79b1536 --- /dev/null +++ b/crate_universe/test_data/metadata/path_patching/child_a/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "child_a" +version = "1.4.2" +edition = "2018" + +# Required to satisfy cargo but no `lib.rs` is expected to +# exist within test data. +[lib] +path = "lib.rs" + +[dependencies] diff --git a/crate_universe/test_data/metadata/path_patching/metadata.json b/crate_universe/test_data/metadata/path_patching/metadata.json new file mode 100644 index 0000000000..e8b0311c61 --- /dev/null +++ b/crate_universe/test_data/metadata/path_patching/metadata.json @@ -0,0 +1,126 @@ +{ + "packages": [ + { + "name": "child_a", + "version": "1.4.2", + "id": "path+file:///usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching/child_a#1.4.2", + "license": null, + "license_file": null, + "description": null, + "source": null, + "dependencies": [], + "targets": [ + { + "kind": ["lib"], + "crate_types": ["lib"], + "name": "child_a", + "src_path": "/usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching/child_a/lib.rs", + "edition": "2018", + "doc": true, + "doctest": true, + "test": true + } + ], + "features": {}, + "manifest_path": "/usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching/child_a/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "path_patching", + "version": "0.1.0", + "id": "path+file:///usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching#0.1.0", + "license": null, + "license_file": null, + "description": null, + "source": null, + "dependencies": [ + { + "name": "child_a", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "req": "^1.4.2", + "kind": null, + "rename": null, + "optional": false, + "uses_default_features": true, + "features": [], + "target": null, + "registry": null + } + ], + "targets": [ + { + "kind": ["lib"], + "crate_types": ["lib"], + "name": "path_patching", + "src_path": "/usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching/lib.rs", + "edition": "2018", + "doc": true, + "doctest": true, + "test": true + } + ], + "features": {}, + "manifest_path": "/usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + } + ], + "workspace_members": [ + "path+file:///usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching#0.1.0" + ], + "workspace_default_members": [ + "path+file:///usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching#0.1.0" + ], + "resolve": { + "nodes": [ + { + "id": "path+file:///usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching/child_a#1.4.2", + "dependencies": [], + "deps": [], + "features": [] + }, + { + "id": "path+file:///usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching#0.1.0", + "dependencies": [ + "path+file:///usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching/child_a#1.4.2" + ], + "deps": [ + { + "name": "child_a", + "pkg": "path+file:///usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching/child_a#1.4.2", + "dep_kinds": [{ "kind": null, "target": null }] + } + ], + "features": [] + } + ], + "root": "path+file:///usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching#0.1.0" + }, + "target_directory": "/usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching/target", + "version": 1, + "workspace_root": "/usr/local/google/home/jayzhuang/fuchsia/third_party/bazel_rules_rust/crate_universe/test_data/metadata/path_patching", + "metadata": null +} diff --git a/examples/crate_universe/DEVELOPMENT.md b/examples/crate_universe/DEVELOPMENT.md index f5e24b1746..d24f651e78 100644 --- a/examples/crate_universe/DEVELOPMENT.md +++ b/examples/crate_universe/DEVELOPMENT.md @@ -9,6 +9,7 @@ bazel commands: ```shell bazel run //vendor_external:crates_vendor bazel run //vendor_local_manifests:crates_vendor +bazel run //vendor_local_patching:crates_vendor bazel run //vendor_local_pkgs:crates_vendor bazel run //vendor_remote_manifests:crates_vendor bazel run //vendor_remote_pkgs:crates_vendor diff --git a/examples/crate_universe/vendor_local_patching/.gitignore b/examples/crate_universe/vendor_local_patching/.gitignore new file mode 100644 index 0000000000..190f3d14e2 --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/.gitignore @@ -0,0 +1,3 @@ +# Ignore everything but the `BUILD` files within the vendored directories +vendor/*/* +!vendor/*/BUILD.bazel diff --git a/examples/crate_universe/vendor_local_patching/BUILD.bazel b/examples/crate_universe/vendor_local_patching/BUILD.bazel new file mode 100644 index 0000000000..96b3e6e263 --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_rust//crate_universe:defs.bzl", "crates_vendor") +load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_test") + +crates_vendor( + name = "crates_vendor", + cargo_lockfile = ":Cargo.lock", + manifests = [":Cargo.toml"], + mode = "local", + # No wasi support + supported_platform_triples = [ + "x86_64-unknown-linux-gnu", + "aarch64-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-fuchsia", + "aarch64-unknown-fuchsia", + ], + vendor_path = "vendor", +) + +rust_binary( + name = "bin", + srcs = ["src/main.rs"], + edition = "2021", + deps = ["//vendor_local_patching/vendor:rand"], +) + +rust_test( + name = "test", + crate = ":bin", +) diff --git a/examples/crate_universe/vendor_local_patching/Cargo.lock b/examples/crate_universe/vendor_local_patching/Cargo.lock new file mode 100644 index 0000000000..e107144607 --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/Cargo.lock @@ -0,0 +1,70 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getrandom" +version = "0.2.15" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "libc" +version = "0.2.141" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" + +[[package]] +name = "my_third_party" +version = "0.1.0" +dependencies = [ + "rand", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[patch.unused]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" + diff --git a/examples/crate_universe/vendor_local_patching/Cargo.toml b/examples/crate_universe/vendor_local_patching/Cargo.toml new file mode 100644 index 0000000000..41b011bc84 --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "my_third_party" +version = "0.1.0" + +[dependencies] +rand = "0.8.5" + +[patch.crates-io] +# We need to make sure that forked_getrandom/BUILD.bazel exposes the correct +# filegroups so that the generated BUILD file in the vendor dir can point to them. +getrandom = { path = "forked/getrandom" } + +# Since we know this crate is never used, we don't have to bother creating a BUILD +# file for our empty stub crate we're using to patch it out +wasi = { path = "empty/wasi" } diff --git a/examples/crate_universe/vendor_local_patching/README.md b/examples/crate_universe/vendor_local_patching/README.md new file mode 100644 index 0000000000..69dd7ba784 --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/README.md @@ -0,0 +1,19 @@ +# Local vendoring with patches + +This demonstrates patching out crates when using the "local" vendor mode. The +example crate just depends on `rand`, and we patch out two of the transitive deps: + +- `getrandom` is forked. In `forked_getrandom/BUILD.bazel` the necessary +filegroups are exposed so that the generated BUILD file at +`vendor/getrandom-0.2.8/BUILD.bazel` can use them. +- `wasi` is "empty-patched" because it's not actually used in the build. When +using local vendoring, `crate_universe` runs `cargo vendor` which isn't aware +of which target-triples you're using. The `wasi` crate is only used by `rand` +when you're actually targeting `wasi` (which we're not), so we +patch it out with a stub crate to avoid downloading and vendoring the source +of the that crate. This can be helpful to avoid vendoring large crates or +ones with conflicting licenses that aren't used in your build graph. + +The result of our `getrandom` patch is that the binary is always given the +same value for seeding its RNG. Therefore we can test that `rand::random` +returns the same value to check that the patching behavior is working correctly. diff --git a/examples/crate_universe/vendor_local_patching/empty/wasi/Cargo.toml b/examples/crate_universe/vendor_local_patching/empty/wasi/Cargo.toml new file mode 100644 index 0000000000..f77ae02a6c --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/empty/wasi/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" diff --git a/examples/crate_universe/vendor_local_patching/empty/wasi/src/lib.rs b/examples/crate_universe/vendor_local_patching/empty/wasi/src/lib.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/crate_universe/vendor_local_patching/forked/getrandom/BUILD.bazel b/examples/crate_universe/vendor_local_patching/forked/getrandom/BUILD.bazel new file mode 100644 index 0000000000..2068f9019b --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/forked/getrandom/BUILD.bazel @@ -0,0 +1,119 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//vendor_local_patching:crates_vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_build_script") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +rust_library( + name = "getrandom", + srcs = glob( + include = ["**/*.rs"], + allow_empty = False, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "std", + ], + crate_root = "src/lib.rs", + edition = "2018", + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=getrandom", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "0.2.15", + deps = [ + "//vendor_local_patching/forked/getrandom:build_script_build", + "//vendor_local_patching/vendor/cfg-if-1.0.0:cfg_if", + ], +) + +cargo_build_script( + name = "_bs", + srcs = glob( + include = ["**/*.rs"], + allow_empty = False, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + "**/*.rs", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "std", + ], + crate_name = "build_script_build", + crate_root = "build.rs", + data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + edition = "2018", + pkg_name = "getrandom", + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=getrandom", + "manual", + "noclippy", + "norustfmt", + ], + version = "0.2.15", + visibility = ["//visibility:private"], +) + +alias( + name = "build_script_build", + actual = ":_bs", + tags = ["manual"], +) diff --git a/examples/crate_universe/vendor_local_patching/forked/getrandom/Cargo.toml b/examples/crate_universe/vendor_local_patching/forked/getrandom/Cargo.toml new file mode 100644 index 0000000000..fd91b640eb --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/forked/getrandom/Cargo.toml @@ -0,0 +1,35 @@ +[package] +edition = "2018" +name = "getrandom" +version = "0.2.15" +authors = ["The Rand Project Developers"] +exclude = [".*"] +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A small cross-platform library for retrieving random data from system source" +documentation = "https://docs.rs/getrandom" +readme = "README.md" +categories = ["os", "no-std"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-random/getrandom" + +[lib] +name = "getrandom" +path = "src/lib.rs" + +[dependencies.cfg-if] +version = "1" + +[dependencies.compiler_builtins] +version = "0.1" +optional = true + +[dependencies.core] +version = "1.0" +optional = true +package = "rustc-std-workspace-core" + +[features] +std = [] diff --git a/examples/crate_universe/vendor_local_patching/forked/getrandom/build.rs b/examples/crate_universe/vendor_local_patching/forked/getrandom/build.rs new file mode 100644 index 0000000000..71d7ac7976 --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/forked/getrandom/build.rs @@ -0,0 +1,4 @@ +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rustc-env=RANDOM_NUMBER=4"); +} diff --git a/examples/crate_universe/vendor_local_patching/forked/getrandom/src/lib.rs b/examples/crate_universe/vendor_local_patching/forked/getrandom/src/lib.rs new file mode 100644 index 0000000000..1a6816069c --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/forked/getrandom/src/lib.rs @@ -0,0 +1,23 @@ +use std::{fmt, num::NonZeroU32}; + +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub struct Error(NonZeroU32); +impl std::error::Error for Error {} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Error({})", self.0.get()) + } +} + +pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> { + if dest.is_empty() { + return Ok(()); + } + let num = env!("RANDOM_NUMBER").parse().unwrap(); + for n in dest { + *n = num; // chosen by fair dice roll. + // guaranteed to be random. + } + Ok(()) +} diff --git a/examples/crate_universe/vendor_local_patching/src/main.rs b/examples/crate_universe/vendor_local_patching/src/main.rs new file mode 100644 index 0000000000..464196c200 --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/src/main.rs @@ -0,0 +1,11 @@ +fn main() { + println!("\"random\" number: {}", rand::random::()); +} + +#[cfg(test)] +mod tests { + #[test] + fn not_actually_random() { + assert_eq!(rand::random::(), 34253218); + } +} diff --git a/examples/crate_universe/vendor_local_patching/vendor/BUILD.bazel b/examples/crate_universe/vendor_local_patching/vendor/BUILD.bazel new file mode 100644 index 0000000000..0f00adcc0a --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/vendor/BUILD.bazel @@ -0,0 +1,43 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//vendor_local_patching:crates_vendor +############################################################################### + +package(default_visibility = ["//visibility:public"]) + +exports_files( + [ + "cargo-bazel.json", + "defs.bzl", + ] + glob( + include = ["*.bazel"], + allow_empty = True, + ), +) + +filegroup( + name = "srcs", + srcs = glob( + include = [ + "*.bazel", + "*.bzl", + ], + allow_empty = True, + ), +) + +# Workspace Member Dependencies +alias( + name = "rand-0.8.5", + actual = "//vendor_local_patching/vendor/rand-0.8.5:rand", + tags = ["manual"], +) + +alias( + name = "rand", + actual = "//vendor_local_patching/vendor/rand-0.8.5:rand", + tags = ["manual"], +) diff --git a/examples/crate_universe/vendor_local_patching/vendor/alias_rules.bzl b/examples/crate_universe/vendor_local_patching/vendor/alias_rules.bzl new file mode 100644 index 0000000000..14b04c1272 --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/vendor/alias_rules.bzl @@ -0,0 +1,47 @@ +"""Alias that transitions its target to `compilation_mode=opt`. Use `transition_alias="opt"` to enable.""" + +load("@rules_cc//cc:defs.bzl", "CcInfo") +load("@rules_rust//rust:rust_common.bzl", "COMMON_PROVIDERS") + +def _transition_alias_impl(ctx): + # `ctx.attr.actual` is a list of 1 item due to the transition + providers = [ctx.attr.actual[0][provider] for provider in COMMON_PROVIDERS] + if CcInfo in ctx.attr.actual[0]: + providers.append(ctx.attr.actual[0][CcInfo]) + return providers + +def _change_compilation_mode(compilation_mode): + def _change_compilation_mode_impl(_settings, _attr): + return { + "//command_line_option:compilation_mode": compilation_mode, + } + + return transition( + implementation = _change_compilation_mode_impl, + inputs = [], + outputs = [ + "//command_line_option:compilation_mode", + ], + ) + +def _transition_alias_rule(compilation_mode): + return rule( + implementation = _transition_alias_impl, + provides = COMMON_PROVIDERS, + attrs = { + "actual": attr.label( + mandatory = True, + doc = "`rust_library()` target to transition to `compilation_mode=opt`.", + providers = COMMON_PROVIDERS, + cfg = _change_compilation_mode(compilation_mode), + ), + "_allowlist_function_transition": attr.label( + default = "@bazel_tools//tools/allowlists/function_transition_allowlist", + ), + }, + doc = "Transitions a Rust library crate to the `compilation_mode=opt`.", + ) + +transition_alias_dbg = _transition_alias_rule("dbg") +transition_alias_fastbuild = _transition_alias_rule("fastbuild") +transition_alias_opt = _transition_alias_rule("opt") diff --git a/examples/crate_universe/vendor_local_patching/vendor/cfg-if-1.0.0/BUILD.bazel b/examples/crate_universe/vendor_local_patching/vendor/cfg-if-1.0.0/BUILD.bazel new file mode 100644 index 0000000000..0b2a1a7488 --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/vendor/cfg-if-1.0.0/BUILD.bazel @@ -0,0 +1,53 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//vendor_local_patching:crates_vendor +############################################################################### + +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +rust_library( + name = "cfg_if", + srcs = glob( + include = ["**/*.rs"], + allow_empty = False, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2018", + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=cfg-if", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "1.0.0", +) diff --git a/examples/crate_universe/vendor_local_patching/vendor/defs.bzl b/examples/crate_universe/vendor_local_patching/vendor/defs.bzl new file mode 100644 index 0000000000..225ec2b967 --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/vendor/defs.bzl @@ -0,0 +1,365 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//vendor_local_patching:crates_vendor +############################################################################### +""" +# `crates_repository` API + +- [aliases](#aliases) +- [crate_deps](#crate_deps) +- [all_crate_deps](#all_crate_deps) +- [crate_repositories](#crate_repositories) + +""" + +load("@bazel_skylib//lib:selects.bzl", "selects") + +############################################################################### +# MACROS API +############################################################################### + +# An identifier that represent common dependencies (unconditional). +_COMMON_CONDITION = "" + +def _flatten_dependency_maps(all_dependency_maps): + """Flatten a list of dependency maps into one dictionary. + + Dependency maps have the following structure: + + ```python + DEPENDENCIES_MAP = { + # The first key in the map is a Bazel package + # name of the workspace this file is defined in. + "workspace_member_package": { + + # Not all dependencies are supported for all platforms. + # the condition key is the condition required to be true + # on the host platform. + "condition": { + + # An alias to a crate target. # The label of the crate target the + # Aliases are only crate names. # package name refers to. + "package_name": "@full//:label", + } + } + } + ``` + + Args: + all_dependency_maps (list): A list of dicts as described above + + Returns: + dict: A dictionary as described above + """ + dependencies = {} + + for workspace_deps_map in all_dependency_maps: + for pkg_name, conditional_deps_map in workspace_deps_map.items(): + if pkg_name not in dependencies: + non_frozen_map = dict() + for key, values in conditional_deps_map.items(): + non_frozen_map.update({key: dict(values.items())}) + dependencies.setdefault(pkg_name, non_frozen_map) + continue + + for condition, deps_map in conditional_deps_map.items(): + # If the condition has not been recorded, do so and continue + if condition not in dependencies[pkg_name]: + dependencies[pkg_name].setdefault(condition, dict(deps_map.items())) + continue + + # Alert on any miss-matched dependencies + inconsistent_entries = [] + for crate_name, crate_label in deps_map.items(): + existing = dependencies[pkg_name][condition].get(crate_name) + if existing and existing != crate_label: + inconsistent_entries.append((crate_name, existing, crate_label)) + dependencies[pkg_name][condition].update({crate_name: crate_label}) + + return dependencies + +def crate_deps(deps, package_name = None): + """Finds the fully qualified label of the requested crates for the package where this macro is called. + + Args: + deps (list): The desired list of crate targets. + package_name (str, optional): The package name of the set of dependencies to look up. + Defaults to `native.package_name()`. + + Returns: + list: A list of labels to generated rust targets (str) + """ + + if not deps: + return [] + + if package_name == None: + package_name = native.package_name() + + # Join both sets of dependencies + dependencies = _flatten_dependency_maps([ + _NORMAL_DEPENDENCIES, + _NORMAL_DEV_DEPENDENCIES, + _PROC_MACRO_DEPENDENCIES, + _PROC_MACRO_DEV_DEPENDENCIES, + _BUILD_DEPENDENCIES, + _BUILD_PROC_MACRO_DEPENDENCIES, + ]).pop(package_name, {}) + + # Combine all conditional packages so we can easily index over a flat list + # TODO: Perhaps this should actually return select statements and maintain + # the conditionals of the dependencies + flat_deps = {} + for deps_set in dependencies.values(): + for crate_name, crate_label in deps_set.items(): + flat_deps.update({crate_name: crate_label}) + + missing_crates = [] + crate_targets = [] + for crate_target in deps: + if crate_target not in flat_deps: + missing_crates.append(crate_target) + else: + crate_targets.append(flat_deps[crate_target]) + + if missing_crates: + fail("Could not find crates `{}` among dependencies of `{}`. Available dependencies were `{}`".format( + missing_crates, + package_name, + dependencies, + )) + + return crate_targets + +def all_crate_deps( + normal = False, + normal_dev = False, + proc_macro = False, + proc_macro_dev = False, + build = False, + build_proc_macro = False, + package_name = None): + """Finds the fully qualified label of all requested direct crate dependencies \ + for the package where this macro is called. + + If no parameters are set, all normal dependencies are returned. Setting any one flag will + otherwise impact the contents of the returned list. + + Args: + normal (bool, optional): If True, normal dependencies are included in the + output list. + normal_dev (bool, optional): If True, normal dev dependencies will be + included in the output list.. + proc_macro (bool, optional): If True, proc_macro dependencies are included + in the output list. + proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are + included in the output list. + build (bool, optional): If True, build dependencies are included + in the output list. + build_proc_macro (bool, optional): If True, build proc_macro dependencies are + included in the output list. + package_name (str, optional): The package name of the set of dependencies to look up. + Defaults to `native.package_name()` when unset. + + Returns: + list: A list of labels to generated rust targets (str) + """ + + if package_name == None: + package_name = native.package_name() + + # Determine the relevant maps to use + all_dependency_maps = [] + if normal: + all_dependency_maps.append(_NORMAL_DEPENDENCIES) + if normal_dev: + all_dependency_maps.append(_NORMAL_DEV_DEPENDENCIES) + if proc_macro: + all_dependency_maps.append(_PROC_MACRO_DEPENDENCIES) + if proc_macro_dev: + all_dependency_maps.append(_PROC_MACRO_DEV_DEPENDENCIES) + if build: + all_dependency_maps.append(_BUILD_DEPENDENCIES) + if build_proc_macro: + all_dependency_maps.append(_BUILD_PROC_MACRO_DEPENDENCIES) + + # Default to always using normal dependencies + if not all_dependency_maps: + all_dependency_maps.append(_NORMAL_DEPENDENCIES) + + dependencies = _flatten_dependency_maps(all_dependency_maps).pop(package_name, None) + + if not dependencies: + if dependencies == None: + fail("Tried to get all_crate_deps for package " + package_name + " but that package had no Cargo.toml file") + else: + return [] + + crate_deps = list(dependencies.pop(_COMMON_CONDITION, {}).values()) + for condition, deps in dependencies.items(): + crate_deps += selects.with_or({ + tuple(_CONDITIONS[condition]): deps.values(), + "//conditions:default": [], + }) + + return crate_deps + +def aliases( + normal = False, + normal_dev = False, + proc_macro = False, + proc_macro_dev = False, + build = False, + build_proc_macro = False, + package_name = None): + """Produces a map of Crate alias names to their original label + + If no dependency kinds are specified, `normal` and `proc_macro` are used by default. + Setting any one flag will otherwise determine the contents of the returned dict. + + Args: + normal (bool, optional): If True, normal dependencies are included in the + output list. + normal_dev (bool, optional): If True, normal dev dependencies will be + included in the output list.. + proc_macro (bool, optional): If True, proc_macro dependencies are included + in the output list. + proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are + included in the output list. + build (bool, optional): If True, build dependencies are included + in the output list. + build_proc_macro (bool, optional): If True, build proc_macro dependencies are + included in the output list. + package_name (str, optional): The package name of the set of dependencies to look up. + Defaults to `native.package_name()` when unset. + + Returns: + dict: The aliases of all associated packages + """ + if package_name == None: + package_name = native.package_name() + + # Determine the relevant maps to use + all_aliases_maps = [] + if normal: + all_aliases_maps.append(_NORMAL_ALIASES) + if normal_dev: + all_aliases_maps.append(_NORMAL_DEV_ALIASES) + if proc_macro: + all_aliases_maps.append(_PROC_MACRO_ALIASES) + if proc_macro_dev: + all_aliases_maps.append(_PROC_MACRO_DEV_ALIASES) + if build: + all_aliases_maps.append(_BUILD_ALIASES) + if build_proc_macro: + all_aliases_maps.append(_BUILD_PROC_MACRO_ALIASES) + + # Default to always using normal aliases + if not all_aliases_maps: + all_aliases_maps.append(_NORMAL_ALIASES) + all_aliases_maps.append(_PROC_MACRO_ALIASES) + + aliases = _flatten_dependency_maps(all_aliases_maps).pop(package_name, None) + + if not aliases: + return dict() + + common_items = aliases.pop(_COMMON_CONDITION, {}).items() + + # If there are only common items in the dictionary, immediately return them + if not len(aliases.keys()) == 1: + return dict(common_items) + + # Build a single select statement where each conditional has accounted for the + # common set of aliases. + crate_aliases = {"//conditions:default": dict(common_items)} + for condition, deps in aliases.items(): + condition_triples = _CONDITIONS[condition] + for triple in condition_triples: + if triple in crate_aliases: + crate_aliases[triple].update(deps) + else: + crate_aliases.update({triple: dict(deps.items() + common_items)}) + + return select(crate_aliases) + +############################################################################### +# WORKSPACE MEMBER DEPS AND ALIASES +############################################################################### + +_NORMAL_DEPENDENCIES = { + "vendor_local_patching": { + _COMMON_CONDITION: { + "rand": Label("//vendor_local_patching/vendor/rand-0.8.5:rand"), + }, + }, +} + +_NORMAL_ALIASES = { + "vendor_local_patching": { + _COMMON_CONDITION: { + }, + }, +} + +_NORMAL_DEV_DEPENDENCIES = { + "vendor_local_patching": { + }, +} + +_NORMAL_DEV_ALIASES = { + "vendor_local_patching": { + }, +} + +_PROC_MACRO_DEPENDENCIES = { + "vendor_local_patching": { + }, +} + +_PROC_MACRO_ALIASES = { + "vendor_local_patching": { + }, +} + +_PROC_MACRO_DEV_DEPENDENCIES = { + "vendor_local_patching": { + }, +} + +_PROC_MACRO_DEV_ALIASES = { + "vendor_local_patching": { + }, +} + +_BUILD_DEPENDENCIES = { + "vendor_local_patching": { + }, +} + +_BUILD_ALIASES = { + "vendor_local_patching": { + }, +} + +_BUILD_PROC_MACRO_DEPENDENCIES = { + "vendor_local_patching": { + }, +} + +_BUILD_PROC_MACRO_ALIASES = { + "vendor_local_patching": { + }, +} + +_CONDITIONS = { + "aarch64-unknown-fuchsia": ["@rules_rust//rust/platform:aarch64-unknown-fuchsia"], + "aarch64-unknown-linux-gnu": ["@rules_rust//rust/platform:aarch64-unknown-linux-gnu"], + "x86_64-apple-darwin": ["@rules_rust//rust/platform:x86_64-apple-darwin"], + "x86_64-pc-windows-msvc": ["@rules_rust//rust/platform:x86_64-pc-windows-msvc"], + "x86_64-unknown-fuchsia": ["@rules_rust//rust/platform:x86_64-unknown-fuchsia"], + "x86_64-unknown-linux-gnu": ["@rules_rust//rust/platform:x86_64-unknown-linux-gnu"], +} diff --git a/examples/crate_universe/vendor_local_patching/vendor/libc-0.2.141/BUILD.bazel b/examples/crate_universe/vendor_local_patching/vendor/libc-0.2.141/BUILD.bazel new file mode 100644 index 0000000000..63e9cd5d37 --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/vendor/libc-0.2.141/BUILD.bazel @@ -0,0 +1,112 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//vendor_local_patching:crates_vendor +############################################################################### + +load("@rules_rust//cargo:defs.bzl", "cargo_build_script") +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +rust_library( + name = "libc", + srcs = glob( + include = ["**/*.rs"], + allow_empty = False, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_root = "src/lib.rs", + edition = "2015", + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=libc", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "0.2.141", + deps = [ + "//vendor_local_patching/vendor/libc-0.2.141:build_script_build", + ], +) + +cargo_build_script( + name = "_bs", + srcs = glob( + include = ["**/*.rs"], + allow_empty = False, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + "**/*.rs", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_name = "build_script_build", + crate_root = "build.rs", + data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + edition = "2015", + pkg_name = "libc", + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=libc", + "manual", + "noclippy", + "norustfmt", + ], + version = "0.2.141", + visibility = ["//visibility:private"], +) + +alias( + name = "build_script_build", + actual = ":_bs", + tags = ["manual"], +) diff --git a/examples/crate_universe/vendor_local_patching/vendor/ppv-lite86-0.2.17/BUILD.bazel b/examples/crate_universe/vendor_local_patching/vendor/ppv-lite86-0.2.17/BUILD.bazel new file mode 100644 index 0000000000..950275a563 --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/vendor/ppv-lite86-0.2.17/BUILD.bazel @@ -0,0 +1,57 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//vendor_local_patching:crates_vendor +############################################################################### + +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +rust_library( + name = "ppv_lite86", + srcs = glob( + include = ["**/*.rs"], + allow_empty = False, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "simd", + "std", + ], + crate_root = "src/lib.rs", + edition = "2018", + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=ppv-lite86", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "0.2.17", +) diff --git a/examples/crate_universe/vendor_local_patching/vendor/rand-0.8.5/BUILD.bazel b/examples/crate_universe/vendor_local_patching/vendor/rand-0.8.5/BUILD.bazel new file mode 100644 index 0000000000..77ea42bc2e --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/vendor/rand-0.8.5/BUILD.bazel @@ -0,0 +1,83 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//vendor_local_patching:crates_vendor +############################################################################### + +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +rust_library( + name = "rand", + srcs = glob( + include = ["**/*.rs"], + allow_empty = False, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "alloc", + "default", + "getrandom", + "libc", + "rand_chacha", + "std", + "std_rng", + ], + crate_root = "src/lib.rs", + edition = "2018", + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=rand", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "0.8.5", + deps = [ + "//vendor_local_patching/vendor/rand_chacha-0.3.1:rand_chacha", + "//vendor_local_patching/vendor/rand_core-0.6.4:rand_core", + ] + select({ + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [ + "//vendor_local_patching/vendor/libc-0.2.141:libc", # aarch64-unknown-fuchsia + ], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [ + "//vendor_local_patching/vendor/libc-0.2.141:libc", # aarch64-unknown-linux-gnu + ], + "@rules_rust//rust/platform:x86_64-apple-darwin": [ + "//vendor_local_patching/vendor/libc-0.2.141:libc", # x86_64-apple-darwin + ], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [ + "//vendor_local_patching/vendor/libc-0.2.141:libc", # x86_64-unknown-fuchsia + ], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [ + "//vendor_local_patching/vendor/libc-0.2.141:libc", # x86_64-unknown-linux-gnu + ], + "//conditions:default": [], + }), +) diff --git a/examples/crate_universe/vendor_local_patching/vendor/rand_chacha-0.3.1/BUILD.bazel b/examples/crate_universe/vendor_local_patching/vendor/rand_chacha-0.3.1/BUILD.bazel new file mode 100644 index 0000000000..e87c561238 --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/vendor/rand_chacha-0.3.1/BUILD.bazel @@ -0,0 +1,60 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//vendor_local_patching:crates_vendor +############################################################################### + +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +rust_library( + name = "rand_chacha", + srcs = glob( + include = ["**/*.rs"], + allow_empty = False, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "std", + ], + crate_root = "src/lib.rs", + edition = "2018", + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=rand_chacha", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "0.3.1", + deps = [ + "//vendor_local_patching/vendor/ppv-lite86-0.2.17:ppv_lite86", + "//vendor_local_patching/vendor/rand_core-0.6.4:rand_core", + ], +) diff --git a/examples/crate_universe/vendor_local_patching/vendor/rand_core-0.6.4/BUILD.bazel b/examples/crate_universe/vendor_local_patching/vendor/rand_core-0.6.4/BUILD.bazel new file mode 100644 index 0000000000..187bc70532 --- /dev/null +++ b/examples/crate_universe/vendor_local_patching/vendor/rand_core-0.6.4/BUILD.bazel @@ -0,0 +1,61 @@ +############################################################################### +# @generated +# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To +# regenerate this file, run the following: +# +# bazel run @@//vendor_local_patching:crates_vendor +############################################################################### + +load("@rules_rust//rust:defs.bzl", "rust_library") + +package(default_visibility = ["//visibility:public"]) + +rust_library( + name = "rand_core", + srcs = glob( + include = ["**/*.rs"], + allow_empty = False, + ), + compile_data = glob( + include = ["**"], + allow_empty = True, + exclude = [ + "**/* *", + ".tmp_git_root/**/*", + "BUILD", + "BUILD.bazel", + "WORKSPACE", + "WORKSPACE.bazel", + ], + ), + crate_features = [ + "alloc", + "getrandom", + "std", + ], + crate_root = "src/lib.rs", + edition = "2018", + rustc_flags = [ + "--cap-lints=allow", + ], + tags = [ + "cargo-bazel", + "crate-name=rand_core", + "manual", + "noclippy", + "norustfmt", + ], + target_compatible_with = select({ + "@rules_rust//rust/platform:aarch64-unknown-fuchsia": [], + "@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [], + "@rules_rust//rust/platform:x86_64-apple-darwin": [], + "@rules_rust//rust/platform:x86_64-pc-windows-msvc": [], + "@rules_rust//rust/platform:x86_64-unknown-fuchsia": [], + "@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + version = "0.6.4", + deps = [ + "//vendor_local_patching/forked/getrandom", + ], +)