Skip to content

Commit 987c898

Browse files
committed
Add apparent_repo_name macro to prepare for Bzlmod
Part of bazel-contrib#1482. Splits the last component off of canonical repo names to produce the expected repo name. Without Bzlmod, it returns the original name. With Bzlmod enabled, it avoids generating output like: scala_import( name = "_main~scala_deps~io_bazel_rules_scala_scala_compiler", jars = ["scala-compiler-2.12.18.jar"], ) resulting in errors like: ``` ERROR: .../_main~_repo_rules~io_bazel_rules_scala/scala/BUILD: no such target '@@_main~scala_deps~io_bazel_rules_scala_scala_compiler//:io_bazel_rules_scala_scala_compiler': target 'io_bazel_rules_scala_scala_compiler' not declared in package '' defined by .../_main~scala_deps~io_bazel_rules_scala_scala_compiler/BUILD and referenced by '@@_main~_repo_rules~io_bazel_rules_scala//scala:default_toolchain_scala_compile_classpath_provider' ``` Also fixes the following error when attaching resources from custom repos to targets under Bzlmod: ```txt $ bazel test //test/src/main/scala/scalarules/test/resources:all 1) Scala library depending on resources from external resource-only jar::allow to load resources(scalarules.test.resources.ScalaLibResourcesFromExternalDepTest) java.lang.NullPointerException at scalarules.test.resources.ScalaLibResourcesFromExternalDepTest.get(ScalaLibResourcesFromExternalDepTest.scala:17) at scalarules.test.resources.ScalaLibResourcesFromExternalDepTest.$anonfun$new$3(ScalaLibResourcesFromExternalDepTest.scala:11) at scalarules.test.resources.ScalaLibResourcesFromExternalDepTest.$anonfun$new$2(ScalaLibResourcesFromExternalDepTest.scala:11) ``` Can be replaced with a future bazel-skylib implementation, if accepted into that repo. --- We can't rely on the specific canonical repository name format: > Repos generated by extensions have canonical names in the form of > `module_repo_canonical_name+extension_name+repo_name`. For extensions > hosted in the root module, the `module_repo_canonical_name` part is > replaced with the string `_main`. Note that the canonical name format is > not an API you should depend on — it's subject to change at any time. > > - https://bazel.build/external/extension#repository_names_and_visibility The change to no longer encode module versions in canonical repo names in Bazel 7.1.0 is a recent example of Bazel maintainers altering the format: - bazelbuild/bazel#21316 And the maintainers recently replaced the `~` delimiter with `+` in the upcoming Bazel 8 release due to build performance issues on Windows: - bazelbuild/bazel#22865 This function assumes the only valid `repo_name` characters are letters, numbers, '_', '-', and '.'. It finds the last character not in this set, and returns the contents of `name` following this character. This is valid so long as this condition holds: - https://github.com/bazelbuild/bazel/blob/7.3.2/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryName.java#L159-L162
1 parent cd22d88 commit 987c898

File tree

4 files changed

+39
-4
lines changed

4 files changed

+39
-4
lines changed

scala/private/macros/bzlmod.bzl

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""Utilities for working with Bazel modules"""
2+
3+
def apparent_repo_name(label_or_name):
4+
"""Return a repository's apparent repository name.
5+
6+
Can be replaced with a future bazel-skylib implementation, if accepted into
7+
that repo.
8+
9+
Args:
10+
label_or_name: a Label or repository name string
11+
12+
Returns:
13+
The apparent repository name
14+
"""
15+
repo_name = getattr(label_or_name, "repo_name", label_or_name)
16+
17+
# Bazed on this pattern from the Bazel source:
18+
# com.google.devtools.build.lib.cmdline.RepositoryName.VALID_REPO_NAME
19+
for i in range(len(repo_name) - 1, -1, -1):
20+
c = repo_name[i]
21+
if not (c.isalnum() or c in "_-."):
22+
return repo_name[i + 1:]
23+
return repo_name

scala/private/resources.bzl

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
load(":macros/bzlmod.bzl", "apparent_repo_name")
2+
13
def paths(resources, resource_strip_prefix):
24
"""Return a list of path tuples (target, source) where:
35
target - is a path in the archive (with given prefix stripped off)
@@ -13,7 +15,13 @@ def paths(resources, resource_strip_prefix):
1315

1416
def _target_path(resource, resource_strip_prefix):
1517
path = _target_path_by_strip_prefix(resource, resource_strip_prefix) if resource_strip_prefix else _target_path_by_default_prefixes(resource)
16-
return _strip_prefix(path, "/")
18+
return _update_external_target_path(_strip_prefix(path, "/"))
19+
20+
def _update_external_target_path(target_path):
21+
if not target_path.startswith("external/"):
22+
return target_path
23+
prefix, repo_name, rest = target_path.split("/")
24+
return "/".join([prefix, apparent_repo_name(repo_name), rest])
1725

1826
def _target_path_by_strip_prefix(resource, resource_strip_prefix):
1927
# Start from absolute resource path and then strip roots so we get to correct short path

scala/scala_maven_import_external.bzl

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ the following macros are defined below that utilize jvm_import_external:
3535
- java_import_external - to demonstrate that the original functionality of `java_import_external` stayed intact.
3636
"""
3737

38+
load("//scala/private:macros/bzlmod.bzl", "apparent_repo_name")
3839
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "read_netrc", "read_user_netrc", "use_netrc")
3940

4041
# https://github.com/bazelbuild/bazel/issues/13709#issuecomment-1336699672
@@ -136,7 +137,7 @@ def _jvm_import_external(repository_ctx):
136137
"",
137138
"alias(",
138139
" name = \"jar\",",
139-
" actual = \"@%s\"," % repository_ctx.name,
140+
" actual = \"@%s\"," % apparent_repo_name(repository_ctx.name),
140141
")",
141142
"",
142143
]))

third_party/repositories/repositories.bzl

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
load("//scala/private:macros/bzlmod.bzl", "apparent_repo_name")
12
load(
23
"//third_party/repositories:scala_2_11.bzl",
34
_artifacts_2_11 = "artifacts",
@@ -95,8 +96,10 @@ def repositories(
9596
default_artifacts = artifacts_by_major_scala_version[major_scala_version]
9697
artifacts = dict(default_artifacts.items() + overriden_artifacts.items())
9798
for id in for_artifact_ids:
99+
generated_rule_name = apparent_repo_name(id) + suffix
98100
_scala_maven_import_external(
99101
name = id + suffix,
102+
generated_rule_name = generated_rule_name,
100103
artifact = artifacts[id]["artifact"],
101104
artifact_sha256 = artifacts[id]["sha256"],
102105
licenses = ["notice"],
@@ -111,13 +114,13 @@ def repositories(
111114
# See: https://github.com/bazelbuild/rules_scala/pull/1573
112115
# Hopefully we can deprecate and remove it one day.
113116
if suffix and scala_version == SCALA_VERSION:
114-
_alias_repository(name = id, target = id + suffix)
117+
_alias_repository(name = id, target = generated_rule_name)
115118

116119
def _alias_repository_impl(rctx):
117120
""" Builds a repository containing just two aliases to the Scala Maven artifacts in the `target` repository. """
118121

119122
format_kwargs = {
120-
"name": rctx.name,
123+
"name": apparent_repo_name(rctx.name),
121124
"target": rctx.attr.target,
122125
}
123126
rctx.file("BUILD", """alias(

0 commit comments

Comments
 (0)