Skip to content

Commit 57bee2d

Browse files
committed
Add support for --incompatible_enable_proto_toolchain_resolution
1 parent c40b336 commit 57bee2d

File tree

10 files changed

+152
-13
lines changed

10 files changed

+152
-13
lines changed

.bazelci/presubmit.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,22 @@ tasks:
7373
- "@go_default_sdk//..."
7474
test_targets:
7575
- "//..."
76+
bcr_tests_proto:
77+
name: BCR test module (--incompatible_enable_proto_toolchain_resolution)
78+
platform: ${{ platform }}
79+
bazel: 7.1.1
80+
working_directory: tests/bcr
81+
build_flags:
82+
- "--allow_yanked_versions=all"
83+
- "--incompatible_enable_proto_toolchain_resolution"
84+
test_flags:
85+
- "--allow_yanked_versions=all"
86+
- "--incompatible_enable_proto_toolchain_resolution"
87+
build_targets:
88+
- "//..."
89+
- "@go_default_sdk//..."
90+
test_targets:
91+
- "//..."
7692
macos:
7793
shell_commands:
7894
- tests/core/cgo/generate_imported_dylib.sh

.bazelrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ build:incompatible --incompatible_enforce_config_setting_visibility
3333
build:incompatible --incompatible_disallow_empty_glob
3434
build:incompatible --incompatible_disable_starlark_host_transitions
3535
build:incompatible --nolegacy_external_runfiles
36+
build:incompatible --incompatible_enable_proto_toolchain_resolution
3637
# Also enable all incompatible flags in go_bazel_test by default.
3738
# TODO: Add --incompatible_disallow_empty_glob once
3839
# https://github.com/bazelbuild/bazel-gazelle/pull/1405 has been released.
39-
test:incompatible --test_env=GO_BAZEL_TEST_BAZELFLAGS='--incompatible_load_proto_rules_from_bzl --incompatible_enable_cc_toolchain_resolution --incompatible_config_setting_private_default_visibility --incompatible_enforce_config_setting_visibility --incompatible_disable_starlark_host_transitions --nolegacy_external_runfiles'
40+
test:incompatible --test_env=GO_BAZEL_TEST_BAZELFLAGS='--incompatible_load_proto_rules_from_bzl --incompatible_enable_cc_toolchain_resolution --incompatible_config_setting_private_default_visibility --incompatible_enforce_config_setting_visibility --incompatible_disable_starlark_host_transitions --nolegacy_external_runfiles --incompatible_enable_proto_toolchain_resolution'

MODULE.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module(
1010
bazel_dep(name = "bazel_features", version = "1.9.1", repo_name = "io_bazel_rules_go_bazel_features")
1111
bazel_dep(name = "bazel_skylib", version = "1.2.0")
1212
bazel_dep(name = "platforms", version = "0.0.4")
13-
bazel_dep(name = "rules_proto", version = "4.0.0")
13+
bazel_dep(name = "rules_proto", version = "6.0.0-rc2")
1414
bazel_dep(name = "protobuf", version = "3.19.2", repo_name = "com_google_protobuf")
1515

1616
go_sdk = use_extension("//go:extensions.bzl", "go_sdk")

WORKSPACE

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,51 @@ workspace(name = "io_bazel_rules_go")
33
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
44
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
55

6+
# The non-polyfill version of this is needed by rules_proto below.
7+
http_archive(
8+
name = "bazel_features",
9+
sha256 = "d7787da289a7fb497352211ad200ec9f698822a9e0757a4976fd9f713ff372b3",
10+
strip_prefix = "bazel_features-1.9.1",
11+
url = "https://github.com/bazel-contrib/bazel_features/releases/download/v1.9.1/bazel_features-v1.9.1.tar.gz",
12+
)
13+
14+
load("@bazel_features//:deps.bzl", "bazel_features_deps")
15+
16+
bazel_features_deps()
17+
618
go_rules_dependencies()
719

820
go_register_toolchains(version = "1.21.8")
921

22+
http_archive(
23+
name = "rules_proto",
24+
sha256 = "71fdbed00a0709521ad212058c60d13997b922a5d01dbfd997f0d57d689e7b67",
25+
strip_prefix = "rules_proto-6.0.0-rc2",
26+
url = "https://github.com/bazelbuild/rules_proto/releases/download/6.0.0-rc2/rules_proto-6.0.0-rc2.tar.gz",
27+
)
28+
29+
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")
30+
31+
rules_proto_dependencies()
32+
33+
load("@rules_proto//proto:toolchains.bzl", "rules_proto_toolchains")
34+
35+
rules_proto_toolchains()
36+
37+
http_archive(
38+
name = "toolchains_protoc",
39+
sha256 = "b312e6de6485e01f753cb87fa09b4193f1762593141790dd0a90abf5e520b1d7",
40+
strip_prefix = "toolchains_protoc-0.2.1",
41+
url = "https://github.com/alexeagle/toolchains_protoc/releases/download/v0.2.1/toolchains_protoc-v0.2.1.tar.gz",
42+
)
43+
44+
load("@toolchains_protoc//protoc:toolchain.bzl", "protoc_toolchains")
45+
46+
protoc_toolchains(
47+
name = "protoc_toolchains",
48+
version = "v25.3",
49+
)
50+
1051
http_archive(
1152
name = "com_google_protobuf",
1253
sha256 = "75be42bd736f4df6d702a0e4e4d30de9ee40eac024c4b845d17ae4cc831fe4ae",

proto/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ go_proto_compiler(
127127
non_go_reset_target(
128128
name = "protoc",
129129
dep = "@com_google_protobuf//:protoc",
130+
deprecation = "No longer used by rules_go, will be removed in a future release.",
130131
visibility = ["//visibility:public"],
131132
)
132133

proto/compiler.bzl

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ load(
1616
"@bazel_skylib//lib:paths.bzl",
1717
"paths",
1818
)
19+
load(
20+
"@rules_proto//proto:proto_common.bzl",
21+
"ProtoLangToolchainInfo",
22+
proto_toolchains = "toolchains",
23+
)
1924
load(
2025
"//go:def.bzl",
2126
"GoLibrary",
@@ -31,6 +36,15 @@ load(
3136
"go_reset_target",
3237
)
3338

39+
# This is actually a misuse of Proto toolchains: The proper way to use `protoc` would be to go
40+
# through a Go-specific `proto_lang_toolchain` and use the methods on `proto_common` to interact
41+
# with `protoc`. Since rules_go has a very bespoke setup with customizable compilers and the need
42+
# to apply reset transitions in case `protoc` *is* built from source, this would require major
43+
# changes.
44+
# TODO: Revisit this after --incompatible_enable_proto_toolchain_resolution has been enabled by
45+
# default.
46+
_PROTO_TOOLCHAIN_TYPE = "@rules_proto//proto:toolchain_type"
47+
3448
GoProtoCompiler = provider(
3549
doc = "Information and dependencies needed to generate Go code from protos",
3650
fields = {
@@ -104,7 +118,7 @@ def go_proto_compile(go, compiler, protos, imports, importpath):
104118
transitive_descriptor_sets = depset(direct = [], transitive = desc_sets)
105119

106120
args = go.actions.args()
107-
args.add("-protoc", compiler.internal.protoc)
121+
args.add("-protoc", compiler.internal.protoc.executable)
108122
args.add("-importpath", importpath)
109123
args.add("-out_path", outpath)
110124
args.add("-plugin", compiler.internal.plugin)
@@ -122,7 +136,6 @@ def go_proto_compile(go, compiler, protos, imports, importpath):
122136
inputs = depset(
123137
direct = [
124138
compiler.internal.go_protoc,
125-
compiler.internal.protoc,
126139
compiler.internal.plugin,
127140
],
128141
transitive = [transitive_descriptor_sets],
@@ -132,6 +145,7 @@ def go_proto_compile(go, compiler, protos, imports, importpath):
132145
mnemonic = "GoProtocGen",
133146
executable = compiler.internal.go_protoc,
134147
toolchain = GO_TOOLCHAIN_LABEL,
148+
tools = [compiler.internal.protoc],
135149
arguments = [args],
136150
env = go.env,
137151
# We may need the shell environment (potentially augmented with --action_env)
@@ -172,6 +186,11 @@ def _go_proto_compiler_impl(ctx):
172186
go = go_context(ctx)
173187
library = go.new_library(go)
174188
source = go.library_to_source(go, ctx.attr, library, ctx.coverage_instrumented())
189+
proto_toolchain = proto_toolchains.find_toolchain(
190+
ctx,
191+
legacy_attr = "_legacy_proto_toolchain",
192+
toolchain_type = _PROTO_TOOLCHAIN_TYPE,
193+
)
175194
return [
176195
GoProtoCompiler(
177196
deps = ctx.attr.deps,
@@ -181,7 +200,7 @@ def _go_proto_compiler_impl(ctx):
181200
options = ctx.attr.options,
182201
suffix = ctx.attr.suffix,
183202
suffixes = ctx.attr.suffixes,
184-
protoc = ctx.executable._protoc,
203+
protoc = proto_toolchain.proto_compiler,
185204
go_protoc = ctx.executable._go_protoc,
186205
plugin = ctx.executable.plugin,
187206
import_path_option = ctx.attr.import_path_option,
@@ -210,16 +229,20 @@ _go_proto_compiler = rule(
210229
cfg = "exec",
211230
default = "//go/tools/builders:go-protoc",
212231
),
213-
"_protoc": attr.label(
214-
executable = True,
215-
cfg = "exec",
216-
default = "//proto:protoc",
217-
),
218232
"_go_context_data": attr.label(
219233
default = "//:go_context_data",
220234
),
221-
},
222-
toolchains = [GO_TOOLCHAIN],
235+
} | proto_toolchains.if_legacy_toolchain({
236+
"_legacy_proto_toolchain": attr.label(
237+
# Setting cfg = "exec" here as the legacy_proto_toolchain target
238+
# already needs to apply the non_go_tool_transition. Flipping the
239+
# two would be more idiomatic, but proto_toolchains.find_toolchain
240+
# doesn't support split transitions.
241+
cfg = "exec",
242+
default = "//proto/private:legacy_proto_toolchain",
243+
),
244+
}),
245+
toolchains = [GO_TOOLCHAIN] + proto_toolchains.use_toolchain(_PROTO_TOOLCHAIN_TYPE),
223246
)
224247

225248
def go_proto_compiler(name, **kwargs):

proto/private/BUILD.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
load(":toolchain.bzl", "legacy_proto_toolchain")
2+
3+
legacy_proto_toolchain(
4+
name = "legacy_proto_toolchain",
5+
visibility = ["//proto:__pkg__"],
6+
)

proto/private/toolchain.bzl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Copyright 2024 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Helper that wraps --proto_compiler into a ProtoLangToolchainInfo for backwards
16+
# compatibility with --noincompatible_enable_proto_toolchain_resolution.
17+
18+
load(
19+
"@rules_proto//proto:proto_common.bzl",
20+
"ProtoLangToolchainInfo",
21+
)
22+
load(
23+
"//go/private/rules:transition.bzl",
24+
"go_reset_target",
25+
"non_go_tool_transition",
26+
)
27+
28+
def _legacy_proto_toolchain_impl(ctx):
29+
return [
30+
ProtoLangToolchainInfo(
31+
proto_compiler = ctx.attr._protoc.files_to_run,
32+
),
33+
]
34+
35+
legacy_proto_toolchain = rule(
36+
implementation = _legacy_proto_toolchain_impl,
37+
cfg = non_go_tool_transition,
38+
attrs = {
39+
"_protoc": attr.label(
40+
default = configuration_field(fragment = "proto", name = "proto_compiler"),
41+
),
42+
"_allowlist_function_transition": attr.label(
43+
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
44+
),
45+
},
46+
fragments = ["proto"],
47+
)

tests/bcr/.bazelversion

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6.0.0
1+
6.3.0

tests/bcr/MODULE.bazel

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ local_path_override(
2121
bazel_dep(name = "gazelle", version = "0.33.0")
2222
bazel_dep(name = "protobuf", version = "3.19.6")
2323

24+
# Required with --incompatible_enable_proto_toolchain_resolution.
25+
# Avoids building protoc from source, which speeds up CI runs.
26+
bazel_dep(name = "toolchains_protoc", version = "0.2.1")
27+
2428
go_sdk = use_extension("@my_rules_go//go:extensions.bzl", "go_sdk")
2529
go_sdk.download(
2630
patch_strip = 1,

0 commit comments

Comments
 (0)