Skip to content

Commit 5e08a42

Browse files
committed
feat: add a way to reference well-known types without protobuf repo
The files were already in the include/ folder of every protoc zip file we fetched. We just have to generate proto_library targets for them, similar to what go_repository does to generate BUILD files for Go libraries
1 parent 074b4a2 commit 5e08a42

File tree

7 files changed

+44
-6
lines changed

7 files changed

+44
-6
lines changed

MODULE.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ bazel_dep(name = "rules_proto", version = "6.0.0-rc2")
1111
bazel_dep(name = "platforms", version = "0.0.8")
1212

1313
protoc = use_extension("//protoc:extensions.bzl", "protoc")
14-
protoc.toolchain(version = "v25.3")
15-
use_repo(protoc, "toolchains_protoc_hub")
14+
protoc.toolchain(google_protobuf = "com_google_protobuf", version = "v25.3")
15+
use_repo(protoc, "com_google_protobuf", "toolchains_protoc_hub")
1616

1717
register_toolchains("@toolchains_protoc_hub//:all")
1818

examples/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package(default_visibility = ["//visibility:public"])
66
proto_library(
77
name = "foo_proto",
88
srcs = ["foo.proto"],
9+
deps = ["@com_google_protobuf//:any_proto"],
910
)
1011

1112
py_proto_library(

examples/foo.proto

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
syntax = "proto3";
22

3+
import "google/protobuf/any.proto";
4+
35
option java_package = "proto";
46

57
message Foo {
68
string msg = 1;
9+
repeated google.protobuf.Any details = 2;
710
}

protoc/extensions.bzl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def _proto_extension_impl(module_ctx):
1717

1818
# Ensure the root wins in case of differences
1919
if mod.is_root:
20-
protoc_toolchains(toolchain.name, register = False, version = toolchain.version)
20+
protoc_toolchains(toolchain.name, register = False, google_protobuf = toolchain.google_protobuf, version = toolchain.version)
2121
root_name = toolchain.name
2222
else:
2323
registrations[toolchain.name] = toolchain.version
@@ -33,6 +33,9 @@ protoc = module_extension(
3333
Base name for generated repositories, allowing more than one toolchain to be registered.
3434
Overriding the default is only permitted in the root module.
3535
""", default = DEFAULT_REPOSITORY),
36+
"google_protobuf": attr.string(doc = """A repository containing the exported 'built-in' types:
37+
https://protobuf.dev/reference/protobuf/google.protobuf/
38+
"""),
3639
"version": attr.string(doc = "A tag of protocolbuffers/protobuf repository."),
3740
}),
3841
},

protoc/private/prebuilt_protoc_toolchain.bzl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,21 @@ def _prebuilt_protoc_repo_impl(rctx):
2525
# Generated by @rules_proto//proto/toolchains:prebuilt_protoc_toolchain.bzl
2626
load("@rules_proto//proto/private/rules:proto_toolchain_rule.bzl", "proto_toolchain")
2727
28+
package(default_visibility=["//visibility:public"])
29+
2830
proto_toolchain(
2931
name = "prebuilt_protoc_toolchain",
3032
proto_compiler = "{protoc_label}",
3133
visibility = ["//visibility:public"],
3234
)
35+
36+
# TODO: add proto_library for each .proto file
37+
# and add deps[] in cases where they dep on each other
38+
proto_library(
39+
name = "any_proto",
40+
srcs = ["include/google/protobuf/any.proto"],
41+
strip_import_prefix = "include",
42+
)
3343
""".format(
3444
protoc_label = ":bin/protoc.exe" if rctx.attr.platform.startswith("win") else ":bin/protoc",
3545
))

protoc/private/protoc_toolchains.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ toolchain(
4242
toolchain_type = "@rules_proto//proto:toolchain_type",
4343
)
4444
""".format(
45-
platform = platform,
45+
platform = platform.replace("-", "_"),
4646
user_repository_name = repository_ctx.attr.user_repository_name,
4747
compatible_with = meta["compatible_with"],
4848
)

protoc/toolchain.bzl

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,39 @@ load("//protoc/private:prebuilt_protoc_toolchain.bzl", "prebuilt_protoc_repo")
1818
load("//protoc/private:protoc_toolchains.bzl", "protoc_toolchains_repo")
1919
load("//protoc/private:versions.bzl", "PROTOC_PLATFORMS")
2020

21-
def protoc_toolchains(name, version, register = True):
21+
def _google_protobuf_alias_repo_impl(rctx):
22+
rctx.file("BUILD", """package(default_visibility=["//visibility:public"])
23+
alias(name = "any_proto", actual = "@{0}//:any_proto")
24+
""".format(rctx.attr.alias_to))
25+
26+
_google_protobuf_alias_repo = repository_rule(_google_protobuf_alias_repo_impl, attrs={"alias_to": attr.string()})
27+
28+
def protoc_toolchains(name, version, google_protobuf = None, alias_to = "osx-aarch_64", register = True):
2229
"""A utility method to load all Protobuf toolchains.
2330
2431
Args:
2532
name: base name for generated repositories, allowing multiple protoc versions.
2633
version: a release tag from protocolbuffers/protobuf, e.g. 'v25.3'
34+
google_protobuf: a repository to expose the google.protobuf package, providing the well-known-types.
35+
alias_to: a platform whose download of protoc.zip will become eager, as it will be used to back aliases for the
36+
google_protobuf repo. We cannot rely on toolchain resolution because that doesn't give a way for a label
37+
to reference one of the concrete toolchain targets. We don't want to use select() because that makes
38+
cquery eager-fetch ALL platforms.
2739
register: whether to register the resulting toolchains.
2840
Should be True for WORKSPACE and False under bzlmod.
2941
"""
3042

3143
for platform in PROTOC_PLATFORMS.keys():
32-
prebuilt_protoc_repo(name = ".".join([name, platform]), platform = platform, version = version)
44+
prebuilt_protoc_repo(
45+
# We must replace hyphen with underscore to workaround rules_python
46+
# File "/output-base/external/rules_python~override/python/private/proto/py_proto_library.bzl", line 62, column 17, in _py_proto_aspect_impl
47+
# Error in fail: Cannot generate Python code for a .proto whose path contains '-'
48+
# (external/_main~protoc~toolchains_protoc_hub.osx-aarch_64/include/google/protobuf/any.proto).
49+
name = ".".join([name, platform.replace("-", "_")]),
50+
platform = platform,
51+
version = version)
3352
protoc_toolchains_repo(name = name, user_repository_name = name)
3453
if register:
3554
native.register_toolchains("@{}//:all".format(name))
55+
if google_protobuf:
56+
_google_protobuf_alias_repo(name = google_protobuf, alias_to = ".".join([name, alias_to.replace("-", "_")]))

0 commit comments

Comments
 (0)