Skip to content

Commit c1e58d3

Browse files
authored
feat: bit more configurable proto toolchain (#1718)
* feat: bit more configurable proto toolchain * fix: tests * fix: grpc deps * fix: test_version suite * fix: linting * fix: docs * fix: code review * chore: README.md section for scala_proto_toolchain changes * fix: better attrs ordering for the README example * fix: failing test + linter * fix: README.md and docstring * fix: code fence
1 parent dc8fb8f commit c1e58d3

File tree

12 files changed

+146
-106
lines changed

12 files changed

+146
-106
lines changed

README.md

+55-1
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ with the following `scala_toolchains()` parameters:
494494
```py
495495
scala_toolchains(
496496
scala_proto = True,
497-
scala_proto_enable_all_options = True,
497+
scala_proto_options = [],
498498
)
499499
```
500500

@@ -819,6 +819,60 @@ under WORKSPACE](#6.5.0), with the maximum dependency versions specified in
819819
that section. While this may continue to work for some time, it is not
820820
officially supported.
821821

822+
### `scala_proto_toolchain` changes and new `scalapb_toolchain` macro
823+
824+
`scala_proto_toolchain` has a more flexible plugin configuration schema. The
825+
new `generators` and `generators_opts` attributes replace the following
826+
attributes:
827+
828+
- `with_grpc`
829+
- `with_flat_package`
830+
- `with_single_line_to_string`
831+
- `main_generator`
832+
- `named_generators`
833+
834+
Now each generator (plugin) will get a corresponding name
835+
that can be used for further plugin options setup:
836+
837+
```py
838+
scala_proto_toolchain(
839+
name = "example",
840+
generators = {
841+
"scala": "scripts.ScalaPbCodeGenerator",
842+
"jvm_extra_protobuf_generator": "scalarules.test.extra_protobuf_generator.ExtraProtobufGenerator",
843+
},
844+
generators_opts = {
845+
"scala": [
846+
"grpc",
847+
"single_line_to_proto_string",
848+
],
849+
"jvm_extra_protobuf_generator": [
850+
"grpc",
851+
"single_line_to_proto_string",
852+
],
853+
},
854+
)
855+
```
856+
857+
`scalapb_grpc_deps` no longer exists since it's now the user's responsibility
858+
to configure dependencies based on the provided generators and their options.
859+
860+
The new `scalapb_toolchain` convenience macro wraps `scala_proto_toolchain`
861+
to provide the default [ScalaPB](https://scalapb.github.io/) implementation:
862+
863+
```py
864+
load("//scala_proto:scala_proto_toolchain.bzl", "scalapb_toolchain")
865+
866+
scalapb_toolchain(
867+
name = "my_toolchain",
868+
opts = [
869+
"grpc",
870+
"single_line_to_proto_string",
871+
],
872+
visibility = ["//visibility:public"],
873+
)
874+
```
875+
822876
### Removal of `bind()` aliases for `twitter_scrooge` dependencies
823877

824878
`rules_scala` 7.x removes all of the obsolete [`bind()`][] aliases under

docs/scala_proto_library.md

+15-16
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ which adds a few dependencies needed for ScalaPB:
77
scala_toolchains(
88
# Other toolchains settings...
99
scala_proto = True,
10+
scala_proto_options = [
11+
"grpc",
12+
"flat_package",
13+
"scala3_sources",
14+
],
1015
)
1116

1217
scala_register_toolchains()
@@ -47,9 +52,13 @@ load(
4752

4853
scala_proto_toolchain(
4954
name = "scala_proto_toolchain",
50-
with_grpc = False,
51-
with_flat_package = False,
52-
with_single_line_to_string = False,
55+
generators_opts = {
56+
"scala": [
57+
"grpc",
58+
"flat_package",
59+
"scala3_sources",
60+
]
61+
},
5362
visibility = ["//visibility:public"],
5463
)
5564

@@ -66,12 +75,10 @@ toolchain(
6675
| Attribute name | Description |
6776
| ----------------------------- | ----------------------------------------------------- |
6877
| name | `Name, required`<br/>A unique name for this toolchain. |
69-
| with_grpc | `boolean, optional (default False)`<br/>Enables generation of grpc service bindings for services. |
70-
| with_flat_package | `boolean, optional (default False)`<br/>When true, ScalaPB will not append the protofile base name to the package name. |
71-
| with_single_line_to_string | `boolean, optional (default False)`<br/>Enables generation of toString() methods that use a single line format. |
78+
| generators_opts | `List of strings, optional`<br/>Additional protobuf options like 'grpc', 'flat_package' or 'scala3_sources'. |
7279
| blacklisted_protos | `List of labels, optional`<br/>List of protobuf targets to exclude from recursive building. |
7380
| code_generator | `Label, optional (has default)`<br/>Which code generator to use. A sensible default is provided. |
74-
| named_generators | `String dict, optional` |
81+
| generators | `String dict, optional` |
7582
| extra_generator_dependencies | `List of labels, optional` |
7683
| scalac | `Label, optional (has default)`<br/>Target for scalac. A sensible default is provided. |
7784

@@ -89,7 +96,6 @@ scala_proto_deps_toolchain(
8996
visibility = ["//visibility:public"],
9097
dep_providers = [
9198
":my_compile_deps",
92-
":my_grpc_deps",
9399
],
94100
)
95101

@@ -105,17 +111,10 @@ declare_deps_provider(
105111
deps = ["@dep1", "@dep2"],
106112
visibility = ["//visibility:public"],
107113
)
108-
109-
declare_deps_provider(
110-
name = "my_grpc_deps",
111-
deps_id = "scalapb_grpc_deps",
112-
deps = ["@dep3", "@dep4"],
113-
visibility = ["//visibility:public"],
114-
)
115114
```
116115

117116
### `scala_proto_deps_toolchain` Toolchain Attributes
118117

119118
| Attribute name | Description |
120119
| ----------------------------- | ----------------------------------------------------- |
121-
| dep_providers | `List of labels, optional (has default)`<br/>allows injection of gRPC (deps_id - `scalapb_grpc_deps`) and ScalaPB (deps_id `scalapb_compile_deps`) dependencies |
120+
| dep_providers | `List of labels, optional (has default)`<br/>allows injection of gRPC (deps_id - `scalapb_worker_deps`) and ScalaPB (deps_id `scalapb_compile_deps`) dependencies |

scala/toolchains.bzl

+4-5
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def scala_toolchains(
4242
scalafmt = False,
4343
scalafmt_default_config_path = ".scalafmt.conf",
4444
scala_proto = False,
45-
scala_proto_enable_all_options = False,
45+
scala_proto_options = [],
4646
jmh = False,
4747
twitter_scrooge = False,
4848
twitter_scrooge_deps = {}):
@@ -84,9 +84,8 @@ def scala_toolchains(
8484
scalafmt_default_config_path: the relative path to the default Scalafmt
8585
config file within the repository
8686
scala_proto: whether to instantiate the scala_proto toolchain
87-
scala_proto_enable_all_options: whether to instantiate the scala_proto
88-
toolchain with all options enabled; `scala_proto` must also be
89-
`True` for this to take effect
87+
scala_proto_options: protobuf options, like 'scala3_sources' or 'grpc';
88+
`scala_proto` must also be `True` for this to take effect
9089
jmh: whether to instantiate the Java Microbenchmarks Harness toolchain
9190
twitter_scrooge: whether to instantiate the twitter_scrooge toolchain
9291
twitter_scrooge_deps: dictionary of string to Label containing overrides
@@ -180,7 +179,7 @@ def scala_toolchains(
180179
specs2 = specs2,
181180
scalafmt = scalafmt,
182181
scala_proto = scala_proto,
183-
scala_proto_enable_all_options = scala_proto_enable_all_options,
182+
scala_proto_options = scala_proto_options,
184183
jmh = jmh,
185184
twitter_scrooge = twitter_scrooge,
186185
twitter_scrooge_deps = twitter_scrooge_deps,

scala/toolchains_repo.bzl

+5-12
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def _scala_toolchains_repo_impl(repository_ctx):
4646
repo_attr = repository_ctx.attr
4747
format_args = {
4848
"rules_scala_repo": Label("//:all").repo_name,
49-
"proto_enable_all_options": repo_attr.scala_proto_enable_all_options,
49+
"proto_options": repo_attr.scala_proto_options,
5050
}
5151
toolchains = {}
5252

@@ -96,9 +96,9 @@ _scala_toolchains_repo = repository_rule(
9696
"scala_proto": attr.bool(
9797
doc = "Instantiate the scala_proto toolchain",
9898
),
99-
"scala_proto_enable_all_options": attr.bool(
99+
"scala_proto_options": attr.string_list(
100100
doc = (
101-
"Enable all scala_proto_options; " +
101+
"Protobuf generator options; " +
102102
"scala_proto must also be True for this to take effect"
103103
),
104104
),
@@ -216,21 +216,14 @@ load(
216216
217217
setup_scala_proto_toolchains(
218218
name = "scala_proto",
219-
enable_all_options = {proto_enable_all_options},
219+
default_gen_opts = {proto_options},
220220
)
221221
222222
declare_deps_provider(
223223
name = "scalapb_compile_deps_provider",
224224
deps_id = "scalapb_compile_deps",
225225
visibility = ["//visibility:public"],
226-
deps = DEFAULT_SCALAPB_COMPILE_DEPS,
227-
)
228-
229-
declare_deps_provider(
230-
name = "scalapb_grpc_deps_provider",
231-
deps_id = "scalapb_grpc_deps",
232-
visibility = ["//visibility:public"],
233-
deps = DEFAULT_SCALAPB_GRPC_DEPS,
226+
deps = DEFAULT_SCALAPB_COMPILE_DEPS + DEFAULT_SCALAPB_GRPC_DEPS,
234227
)
235228
236229
declare_deps_provider(

scala_proto/default/default_deps.bzl

+1-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ _DEFAULT_DEP_PROVIDER_FORMAT = (
1717

1818
def scala_proto_deps_providers(
1919
compile = _DEFAULT_DEP_PROVIDER_FORMAT % "compile",
20-
grpc = _DEFAULT_DEP_PROVIDER_FORMAT % "grpc",
2120
worker = _DEFAULT_DEP_PROVIDER_FORMAT % "worker"):
22-
return [compile, grpc, worker]
21+
return [compile, worker]
2322

2423
DEFAULT_SCALAPB_COMPILE_DEPS = [
2524
Label("//scala/private/toolchain_deps:scala_library_classpath"),

scala_proto/private/scala_proto_aspect.bzl

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ def _generate_sources(ctx, toolchain, proto):
7070
args.use_param_file(param_file_arg = "@%s", use_always = True)
7171
for gen, out in outputs.items():
7272
args.add("--" + gen + "_out", out)
73-
args.add("--" + gen + "_opt", toolchain.generators_opts)
73+
if gen in toolchain.generators_opts:
74+
args.add_all(toolchain.generators_opts[gen], format_each = "--{}_opt=%s".format(gen))
7475
args.add_joined("--descriptor_set_in", descriptors, join_with = ctx.configuration.host_path_separator)
7576
args.add_all(sources)
7677

scala_proto/scala_proto_toolchain.bzl

+32-42
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,6 @@ load(
44
_scala_proto_deps_providers = "scala_proto_deps_providers",
55
)
66

7-
def _generators(ctx):
8-
return dict(
9-
ctx.attr.named_generators,
10-
scala = ctx.attr.main_generator,
11-
)
12-
137
def _generators_jars(ctx):
148
generator_deps = ctx.attr.extra_generator_dependencies + [
159
ctx.attr._main_generator_dep,
@@ -19,22 +13,6 @@ def _generators_jars(ctx):
1913
for dep in generator_deps
2014
])
2115

22-
def _generators_opts(ctx):
23-
opts = []
24-
if ctx.attr.with_grpc:
25-
opts.append("grpc")
26-
if ctx.attr.with_flat_package:
27-
opts.append("flat_package")
28-
if ctx.attr.with_single_line_to_string:
29-
opts.append("single_line_to_proto_string")
30-
return ",".join(opts)
31-
32-
def _compile_dep_ids(ctx):
33-
deps = ["scalapb_compile_deps"]
34-
if ctx.attr.with_grpc:
35-
deps.append("scalapb_grpc_deps")
36-
return deps
37-
3816
def _ignored_proto_targets_by_label(ctx):
3917
return {p.label: p for p in ctx.attr.blacklisted_protos}
4018

@@ -49,13 +27,14 @@ def _worker_flags(ctx, generators, jars):
4927
return "--jvm_flags=" + " ".join(["-D%s=%s" % i for i in env.items()])
5028

5129
def _scala_proto_toolchain_impl(ctx):
52-
generators = _generators(ctx)
30+
generators = ctx.attr.generators
5331
generators_jars = _generators_jars(ctx)
32+
compile_dep_ids = ["scalapb_compile_deps"]
5433
toolchain = platform_common.ToolchainInfo(
5534
generators = generators,
5635
generators_jars = generators_jars,
57-
generators_opts = _generators_opts(ctx),
58-
compile_dep_ids = _compile_dep_ids(ctx),
36+
generators_opts = ctx.attr.generators_opts,
37+
compile_dep_ids = compile_dep_ids,
5938
blacklisted_protos = _ignored_proto_targets_by_label(ctx),
6039
protoc = ctx.executable.protoc,
6140
scalac = ctx.attr.scalac.files_to_run,
@@ -66,35 +45,20 @@ def _scala_proto_toolchain_impl(ctx):
6645
return [toolchain]
6746

6847
# Args:
69-
# with_grpc: Enables generation of grpc service bindings for services
70-
# with_flat_package: When true, ScalaPB will not append the protofile base name to the package name
71-
# with_single_line_to_string: Enables generation of toString() methods that use the single line format
7248
# blacklisted_protos: list of protobuf targets to exclude from recursive building
7349
# code_generator: what code generator to use, usually you'll want the default
7450
scala_proto_toolchain = rule(
7551
implementation = _scala_proto_toolchain_impl,
7652
attrs = {
77-
"with_grpc": attr.bool(),
78-
"with_flat_package": attr.bool(),
79-
"with_single_line_to_string": attr.bool(),
8053
"blacklisted_protos": attr.label_list(default = []),
8154
"code_generator": attr.label(
8255
executable = True,
8356
cfg = "exec",
8457
default = Label("//src/scala/scripts:scalapb_worker"),
8558
allow_files = True,
8659
),
87-
# `scripts.ScalaPbCodeGenerator` and `_main_generator_dep` are currently
88-
# necessary to support protoc-bridge < 0.9.8, specifically 0.7.14
89-
# required by Scala 2.11. See #1647 and scalapb/ScalaPB#1771.
90-
#
91-
# If we drop 2.11 support, restore `scalapb.ScalaPbCodeGenerator` here,
92-
# remove `_main_generator_dep`, and delete
93-
# `//src/scala/scripts:scalapb_codegenerator_wrapper` and its files.
94-
"main_generator": attr.string(
95-
default = "scripts.ScalaPbCodeGenerator",
96-
),
97-
"named_generators": attr.string_dict(),
60+
"generators": attr.string_dict(),
61+
"generators_opts": attr.string_list_dict(),
9862
"extra_generator_dependencies": attr.label_list(
9963
providers = [JavaInfo],
10064
),
@@ -121,6 +85,13 @@ scala_proto_toolchain = rule(
12185
[proto rules documentation](https://docs.bazel.build/versions/master/be/protocol-buffer.html#proto_library)
12286
""",
12387
),
88+
# `scripts.ScalaPbCodeGenerator` and `_main_generator_dep` are currently
89+
# necessary to support protoc-bridge < 0.9.8, specifically 0.7.14
90+
# required by Scala 2.11. See #1647 and scalapb/ScalaPB#1771.
91+
#
92+
# If we drop 2.11 support, restore `scalapb.ScalaPbCodeGenerator` here,
93+
# remove `_main_generator_dep`, and delete
94+
# `//src/scala/scripts:scalapb_codegenerator_wrapper` and its files.
12495
"_main_generator_dep": attr.label(
12596
default = Label(
12697
"//src/scala/scripts:scalapb_codegenerator_wrapper",
@@ -132,6 +103,25 @@ scala_proto_toolchain = rule(
132103
},
133104
)
134105

106+
def scalapb_toolchain(name, opts = [], **kwargs):
107+
"""Sets up a scala_proto_toolchain using ScalaPB.
108+
109+
Args:
110+
name: A unique name for this target
111+
opts: scalapb generator options like 'grpc' or 'flat_package'
112+
kwargs: remaining arguments to `scala_proto_toolchain`
113+
"""
114+
scala_proto_toolchain(
115+
name = name,
116+
generators = {
117+
"scala": "scripts.ScalaPbCodeGenerator",
118+
},
119+
generators_opts = {
120+
"scala": opts,
121+
},
122+
**kwargs
123+
)
124+
135125
def _scala_proto_deps_toolchain(ctx):
136126
toolchain = platform_common.ToolchainInfo(
137127
dep_providers = ctx.attr.dep_providers,

0 commit comments

Comments
 (0)