Skip to content

Commit

Permalink
Allow overriding crate universe packages to local packages (#2674)
Browse files Browse the repository at this point in the history
Allow external crates to be aliased to local targets

In some cases it may be desirable to alias a public crate to a locally
define rust_library target, even for dependencies of crates that are not
being overriden.
Support this use case by swapping out `alias` for `rust_library` when
a user overrides the target using an annotation.

---------

Co-authored-by: Daniel Wagner-Hall <[email protected]>
  • Loading branch information
ograff and illicitonion authored Jun 6, 2024
1 parent e3a77c4 commit 33f93ac
Show file tree
Hide file tree
Showing 261 changed files with 6,590 additions and 3,547 deletions.
6 changes: 5 additions & 1 deletion crate_universe/private/crate.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ def _annotation(
rustc_env = None,
rustc_env_files = None,
rustc_flags = None,
shallow_since = None):
shallow_since = None,
override_targets = None):
"""A collection of extra attributes and settings for a particular crate
Args:
Expand Down Expand Up @@ -166,6 +167,8 @@ def _annotation(
rustc_flags (list, optional): A list of strings to set on a crate's `rust_library::rustc_flags` attribute.
shallow_since (str, optional): An optional timestamp used for crates originating from a git repository
instead of a crate registry. This flag optimizes fetching the source code.
override_targets (dict, optional): A dictionary of alternate tagets to use when something depends on this crate to allow
the parent repo to provide its own version of this dependency. Keys can be `proc_marco`, `build_script`, `lib`, `bin`.
Returns:
string: A json encoded string containing the specified version and separately all other inputs.
Expand Down Expand Up @@ -209,6 +212,7 @@ def _annotation(
rustc_env_files = _stringify_list(rustc_env_files),
rustc_flags = rustc_flags,
shallow_since = shallow_since,
override_targets = override_targets,
),
))

Expand Down
4 changes: 4 additions & 0 deletions crate_universe/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@ pub(crate) struct CrateAnnotations {

/// Transition rule to use instead of `native.alias()`.
pub(crate) alias_rule: Option<AliasRule>,

/// The crates to use instead of the generated one.
pub(crate) override_targets: Option<BTreeMap<String, Label>>,
}

macro_rules! joined_extra_member {
Expand Down Expand Up @@ -410,6 +413,7 @@ impl Add for CrateAnnotations {
patches: joined_extra_member!(self.patches, rhs.patches, BTreeSet::new, BTreeSet::extend),
extra_aliased_targets: joined_extra_member!(self.extra_aliased_targets, rhs.extra_aliased_targets, BTreeMap::new, BTreeMap::extend),
alias_rule: self.alias_rule.or(rhs.alias_rule),
override_targets: self.override_targets.or(rhs.override_targets),
};

output
Expand Down
32 changes: 32 additions & 0 deletions crate_universe/src/context/crate_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,28 @@ pub(crate) enum Rule {
BuildScript(TargetAttributes),
}

impl Rule {
/// The keys that can be used in override_targets to override these Rule sources.
/// These intentionally match the accepted `Target.kind`s returned by cargo-metadata.
pub(crate) fn override_target_key(&self) -> &'static str {
match self {
Self::Library(..) => "lib",
Self::ProcMacro(..) => "proc-macro",
Self::Binary(..) => "bin",
Self::BuildScript(..) => "custom-build",
}
}

pub(crate) fn crate_name(&self) -> &str {
match self {
Self::Library(attrs)
| Self::ProcMacro(attrs)
| Self::Binary(attrs)
| Self::BuildScript(attrs) => &attrs.crate_name,
}
}
}

/// A set of attributes common to most `rust_library`, `rust_proc_macro`, and other
/// [core rules of `rules_rust`](https://bazelbuild.github.io/rules_rust/defs.html).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
Expand Down Expand Up @@ -312,6 +334,11 @@ pub(crate) struct CrateContext {
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(default)]
pub(crate) alias_rule: Option<AliasRule>,

/// Targets to use instead of the default target for the crate.
#[serde(skip_serializing_if = "BTreeMap::is_empty")]
#[serde(default)]
pub(crate) override_targets: BTreeMap<String, Label>,
}

impl CrateContext {
Expand Down Expand Up @@ -497,6 +524,7 @@ impl CrateContext {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::new(),
alias_rule: None,
override_targets: BTreeMap::new(),
}
.with_overrides(extras)
}
Expand Down Expand Up @@ -668,6 +696,10 @@ impl CrateContext {
}
}
}

if let Some(override_targets) = &crate_extra.override_targets {
self.override_targets.extend(override_targets.clone());
}
}

self
Expand Down
4 changes: 4 additions & 0 deletions crate_universe/src/context/platforms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
};

let configurations =
Expand Down Expand Up @@ -215,6 +216,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
}
}

Expand Down Expand Up @@ -300,6 +302,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
};

let configurations =
Expand Down Expand Up @@ -365,6 +368,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
};

let configurations =
Expand Down
2 changes: 1 addition & 1 deletion crate_universe/src/lockfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ mod test {
);

assert_eq!(
Digest("4148d6b336e574a67417f77fb4727e9c1b014a0b5ab90771f57285f96bca0fee".to_owned()),
Digest("610cbb406b7452d32ae31c45ec82cd3b3b1fb184c3411ef613c948d88492441b".to_owned()),
digest,
);
}
Expand Down
79 changes: 52 additions & 27 deletions crate_universe/src/rendering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,33 +371,43 @@ impl Renderer {
}

for rule in &krate.targets {
match rule {
Rule::BuildScript(target) => {
load("@rules_rust//cargo:defs.bzl", "cargo_build_script");
let cargo_build_script =
self.make_cargo_build_script(platforms, krate, target)?;
starlark.push(Starlark::CargoBuildScript(cargo_build_script));
starlark.push(Starlark::Alias(Alias {
rule: AliasRule::default().rule(),
name: target.crate_name.clone(),
actual: Label::from_str("_bs").unwrap(),
tags: BTreeSet::from(["manual".to_owned()]),
}));
}
Rule::ProcMacro(target) => {
load("@rules_rust//rust:defs.bzl", "rust_proc_macro");
let rust_proc_macro = self.make_rust_proc_macro(platforms, krate, target)?;
starlark.push(Starlark::RustProcMacro(rust_proc_macro));
}
Rule::Library(target) => {
load("@rules_rust//rust:defs.bzl", "rust_library");
let rust_library = self.make_rust_library(platforms, krate, target)?;
starlark.push(Starlark::RustLibrary(rust_library));
}
Rule::Binary(target) => {
load("@rules_rust//rust:defs.bzl", "rust_binary");
let rust_binary = self.make_rust_binary(platforms, krate, target)?;
starlark.push(Starlark::RustBinary(rust_binary));
if let Some(override_target) = krate.override_targets.get(rule.override_target_key()) {
starlark.push(Starlark::Alias(Alias {
rule: AliasRule::default().rule(),
name: rule.crate_name().to_owned(),
actual: override_target.clone(),
tags: BTreeSet::from(["manual".to_owned()]),
}));
} else {
match rule {
Rule::BuildScript(target) => {
load("@rules_rust//cargo:defs.bzl", "cargo_build_script");
let cargo_build_script =
self.make_cargo_build_script(platforms, krate, target)?;
starlark.push(Starlark::CargoBuildScript(cargo_build_script));
starlark.push(Starlark::Alias(Alias {
rule: AliasRule::default().rule(),
name: target.crate_name.clone(),
actual: Label::from_str("_bs").unwrap(),
tags: BTreeSet::from(["manual".to_owned()]),
}));
}
Rule::ProcMacro(target) => {
load("@rules_rust//rust:defs.bzl", "rust_proc_macro");
let rust_proc_macro =
self.make_rust_proc_macro(platforms, krate, target)?;
starlark.push(Starlark::RustProcMacro(rust_proc_macro));
}
Rule::Library(target) => {
load("@rules_rust//rust:defs.bzl", "rust_library");
let rust_library = self.make_rust_library(platforms, krate, target)?;
starlark.push(Starlark::RustLibrary(rust_library));
}
Rule::Binary(target) => {
load("@rules_rust//rust:defs.bzl", "rust_binary");
let rust_binary = self.make_rust_binary(platforms, krate, target)?;
starlark.push(Starlark::RustBinary(rust_binary));
}
}
}
}
Expand Down Expand Up @@ -967,6 +977,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down Expand Up @@ -1004,6 +1015,7 @@ mod test {
disable_pipelining: true,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down Expand Up @@ -1044,6 +1056,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down Expand Up @@ -1084,6 +1097,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down Expand Up @@ -1121,6 +1135,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down Expand Up @@ -1160,6 +1175,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down Expand Up @@ -1214,6 +1230,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down Expand Up @@ -1247,6 +1264,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down Expand Up @@ -1286,6 +1304,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down Expand Up @@ -1337,6 +1356,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down Expand Up @@ -1447,6 +1467,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down Expand Up @@ -1493,6 +1514,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down Expand Up @@ -1545,6 +1567,7 @@ mod test {
repository: None,
license: None,
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down Expand Up @@ -1608,6 +1631,7 @@ mod test {
repository: None,
license: None,
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down Expand Up @@ -1678,6 +1702,7 @@ mod test {
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

Expand Down
4 changes: 3 additions & 1 deletion docs/crate_universe.md
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,8 @@ crate.annotation(<a href="#crate.annotation-version">version</a>, <a href="#crat
<a href="#crate.annotation-build_script_rustc_env">build_script_rustc_env</a>, <a href="#crate.annotation-build_script_toolchains">build_script_toolchains</a>, <a href="#crate.annotation-compile_data">compile_data</a>, <a href="#crate.annotation-compile_data_glob">compile_data_glob</a>,
<a href="#crate.annotation-crate_features">crate_features</a>, <a href="#crate.annotation-data">data</a>, <a href="#crate.annotation-data_glob">data_glob</a>, <a href="#crate.annotation-deps">deps</a>, <a href="#crate.annotation-extra_aliased_targets">extra_aliased_targets</a>, <a href="#crate.annotation-gen_binaries">gen_binaries</a>,
<a href="#crate.annotation-disable_pipelining">disable_pipelining</a>, <a href="#crate.annotation-gen_build_script">gen_build_script</a>, <a href="#crate.annotation-patch_args">patch_args</a>, <a href="#crate.annotation-patch_tool">patch_tool</a>, <a href="#crate.annotation-patches">patches</a>,
<a href="#crate.annotation-proc_macro_deps">proc_macro_deps</a>, <a href="#crate.annotation-rustc_env">rustc_env</a>, <a href="#crate.annotation-rustc_env_files">rustc_env_files</a>, <a href="#crate.annotation-rustc_flags">rustc_flags</a>, <a href="#crate.annotation-shallow_since">shallow_since</a>)
<a href="#crate.annotation-proc_macro_deps">proc_macro_deps</a>, <a href="#crate.annotation-rustc_env">rustc_env</a>, <a href="#crate.annotation-rustc_env_files">rustc_env_files</a>, <a href="#crate.annotation-rustc_flags">rustc_flags</a>, <a href="#crate.annotation-shallow_since">shallow_since</a>,
<a href="#crate.annotation-override_targets">override_targets</a>)
</pre>

A collection of extra attributes and settings for a particular crate
Expand Down Expand Up @@ -685,6 +686,7 @@ A collection of extra attributes and settings for a particular crate
| <a id="crate.annotation-rustc_env_files"></a>rustc_env_files | A list of labels to set on a crate's <code>rust_library::rustc_env_files</code> attribute. | `None` |
| <a id="crate.annotation-rustc_flags"></a>rustc_flags | A list of strings to set on a crate's <code>rust_library::rustc_flags</code> attribute. | `None` |
| <a id="crate.annotation-shallow_since"></a>shallow_since | An optional timestamp used for crates originating from a git repository instead of a crate registry. This flag optimizes fetching the source code. | `None` |
| <a id="crate.annotation-override_targets"></a>override_targets | A dictionary of alternate tagets to use when something depends on this crate to allow the parent repo to provide its own version of this dependency. Keys can be <code>proc_marco</code>, <code>build_script</code>, <code>lib</code>, <code>bin</code>. | `None` |

**RETURNS**

Expand Down
33 changes: 33 additions & 0 deletions examples/crate_universe/WORKSPACE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,39 @@ load(

complicated_dependencies_crate_repositories()

###############################################################################
# O V E R R I D E T A R G E T
###############################################################################

crates_repository(
name = "override_target",
annotations = {
"foo": [crate.annotation(
override_targets = {"lib": "@//override_target:foo"},
)],
},
cargo_lockfile = "//override_target:Cargo.Bazel.lock",
# `generator` is not necessary in official releases.
# See load satement for `cargo_bazel_bootstrap`.
generator = "@cargo_bazel_bootstrap//:cargo-bazel",
lockfile = "//override_target:cargo-bazel-lock.json",
packages = {
"foo": crate.spec(
version = "0.0.0",
),
},
splicing_config = splicing_config(
resolver_version = "2",
),
)

load(
"@override_target//:defs.bzl",
override_target_crate_repositories = "crate_repositories",
)

override_target_crate_repositories()

###############################################################################

# Used for Bazel CI
Expand Down
Loading

0 comments on commit 33f93ac

Please sign in to comment.