blob: 738af0b548551aea96eed2a0cce5e12262461fa3 [file]
"""Repository rule that relies on fetching a protoc binary from GitHub Releases.
It exposes bin/protoc as a proto_toolchain.
"""
load(":versions.bzl", "PROTOC_PLATFORMS", "PROTOC_VERSIONS")
# TODO: we should read this dynamically by `ls *.proto` and then search for "import" statements
# inside the files. Currently this assumes the wkt srcs/deps are fixed over time.
GOOGLE_PROTOBUF_DEP_EDGES = {
"any": [],
"api": ["source_context", "type"],
"compiler/plugin": ["descriptor"],
"descriptor": [],
"duration": [],
"empty": [],
"field_mask": [],
"source_context": [],
"struct": [],
"timestamp": [],
"type": ["any", "source_context"],
"wrappers": [],
}
def _prebuilt_protoc_repo_impl(rctx):
release_version = rctx.attr.version
if release_version == "LATEST":
release_version = PROTOC_VERSIONS.keys()[0]
filename = "{}-{}-{}.zip".format(
"protoc",
release_version.removeprefix("v"),
rctx.attr.platform,
)
url = "https://github.com/protocolbuffers/protobuf/releases/download/{}/{}".format(
release_version,
filename,
)
rctx.download_and_extract(
url = url,
integrity = PROTOC_VERSIONS[release_version][filename],
)
build_content = """\
# Generated by @rules_proto//proto/toolchains:prebuilt_protoc_toolchain.bzl
load("@rules_proto//proto/private/rules:proto_toolchain_rule.bzl", "proto_toolchain")
package(default_visibility=["//visibility:public"])
proto_toolchain(
name = "prebuilt_protoc_toolchain",
proto_compiler = "{protoc_label}",
visibility = ["//visibility:public"],
)
""".format(
protoc_label = ":bin/protoc.exe" if rctx.attr.platform.startswith("win") else ":bin/protoc",
)
for src, deps in GOOGLE_PROTOBUF_DEP_EDGES.items():
build_content += """\
proto_library(
name = "{0}_proto",
srcs = ["include/google/protobuf/{0}.proto"],
deps = [":%s_proto" % dep for dep in {1}],
strip_import_prefix = "include",
)
""".format(src, deps)
rctx.file("BUILD.bazel", build_content)
prebuilt_protoc_repo = repository_rule(
doc = "Download a pre-built protoc and create a concrete toolchains for it",
implementation = _prebuilt_protoc_repo_impl,
attrs = {
"platform": attr.string(
doc = "A platform that protobuf ships a release for",
mandatory = True,
values = PROTOC_PLATFORMS.keys(),
),
"version": attr.string(
doc = "Release tag from protocolbuffers/protobuf repo, e.g. 'v25.3'",
mandatory = True,
),
},
)