Describe the bug
pants.backend.codegen.protobuf.java reads the generic ProtobufGrpcToggleField (available on both protobuf_source and protobuf_sources targets, regardless of which codegen backend is active) to decide whether to (a) enable gRPC Java stub generation and (b) inject the grpc-java runtime (grpc-netty-shaded, grpc-protobuf, grpc-stub, org.apache.tomcat:annotations-api) as an inferred dependency:
src/python/pants/backend/codegen/protobuf/java/rules.py:163-171 — gates the protoc-gen-grpc-java plugin invocation on request.protocol_target.get(ProtobufGrpcToggleField).value.
src/python/pants/backend/codegen/protobuf/java/dependency_inference.py:29-38,126-141 — ProtobufJavaRuntimeDependencyInferenceFieldSet requires ProtobufGrpcToggleField, and infer_protobuf_java_runtime_dependency conditionally adds the grpc-java runtime coordinates when request.field_set.grpc.value is set.
pants.backend.codegen.protobuf.scala never reads this field:
src/python/pants/backend/codegen/protobuf/scala/rules.py:228 — generate_scala_from_protobuf always invokes the ScalaPB shim with a bare f"--scala_out={output_dir}". ScalaPB's own codegen supports a colon-separated modifier on --scala_out (--scala_out=grpc:<dir>) that turns on its built-in *Grpc.scala service-stub generation — sbt-protoc/ScalaPB passes this by default whenever a .proto declares a service, but Pants's Scala backend has no code path that ever adds it. ProtobufGrpcToggleField isn't even imported in this file.
src/python/pants/backend/codegen/protobuf/scala/dependency_inference.py:28,79-88 — ScalaPBRuntimeDependencyInferenceFieldSet.required_fields is (ProtobufDependenciesField, JvmResolveField) only, and infer_scalapb_runtime_dependency unconditionally returns just the base scalapb-runtime_<binary_version> artifact. There's no equivalent of the Java backend's grpc-runtime injection, so even if (1) were fixed, generated *Grpc.scala files referencing scalapb.grpc.* / io.grpc.* would fail to compile with object grpc is not a member of package scalapb / object io is not a member of package <root>.
The net effect: protobuf_sources(grpc=True) on a target resolved by the Scala backend silently produces plain message classes with no service stubs and no gRPC runtime dependency — no error, no warning, just nothing happens. This is surprising because the field already exists generically on protobuf_source/protobuf_sources and visibly works for the Java backend, so grpc=True looks like supported, portable behavior. It's a feature-parity gap between the two backends, not a missing feature.
Pants version
Confirmed present as of main (2.33.0a0 in progress) and 2.32.0. Introduced when ScalaPB codegen/dependency-inference were added (#13853, #14898) — those predate ProtobufGrpcToggleField support even in the Java backend and were never revisited when Java gained it.
OS
N/A (backend logic bug, not platform-specific)
Additional info
protobuf_source/protobuf_sources' ProtobufGrpcToggleField is defined once, generically, in pants/backend/codegen/protobuf/target_types.py and consumed per-backend; it is not itself backend-specific.
- A minimal repro: a
protobuf_sources(grpc=True) target whose .proto declares a service, resolved once under a JVM resolve with the Java backend active and once with the Scala backend active. Java backend: generates FooServiceGrpc.java and injects grpc-java coordinates. Scala backend: generates only Foo.scala (message classes), no FooServiceGrpc.scala, no scalapb-runtime-grpc/io.grpc.* dependency — grpc=True has zero observable effect.
- I have a candidate fix (mirrors the exact pattern in
pants.backend.codegen.protobuf.java.dependency_inference) and am happy to open a PR.
Describe the bug
pants.backend.codegen.protobuf.javareads the genericProtobufGrpcToggleField(available on bothprotobuf_sourceandprotobuf_sourcestargets, regardless of which codegen backend is active) to decide whether to (a) enable gRPC Java stub generation and (b) inject the grpc-java runtime (grpc-netty-shaded,grpc-protobuf,grpc-stub,org.apache.tomcat:annotations-api) as an inferred dependency:src/python/pants/backend/codegen/protobuf/java/rules.py:163-171— gates theprotoc-gen-grpc-javaplugin invocation onrequest.protocol_target.get(ProtobufGrpcToggleField).value.src/python/pants/backend/codegen/protobuf/java/dependency_inference.py:29-38,126-141—ProtobufJavaRuntimeDependencyInferenceFieldSetrequiresProtobufGrpcToggleField, andinfer_protobuf_java_runtime_dependencyconditionally adds the grpc-java runtime coordinates whenrequest.field_set.grpc.valueis set.pants.backend.codegen.protobuf.scalanever reads this field:src/python/pants/backend/codegen/protobuf/scala/rules.py:228—generate_scala_from_protobufalways invokes the ScalaPB shim with a baref"--scala_out={output_dir}". ScalaPB's own codegen supports a colon-separated modifier on--scala_out(--scala_out=grpc:<dir>) that turns on its built-in*Grpc.scalaservice-stub generation — sbt-protoc/ScalaPB passes this by default whenever a.protodeclares aservice, but Pants's Scala backend has no code path that ever adds it.ProtobufGrpcToggleFieldisn't even imported in this file.src/python/pants/backend/codegen/protobuf/scala/dependency_inference.py:28,79-88—ScalaPBRuntimeDependencyInferenceFieldSet.required_fieldsis(ProtobufDependenciesField, JvmResolveField)only, andinfer_scalapb_runtime_dependencyunconditionally returns just the basescalapb-runtime_<binary_version>artifact. There's no equivalent of the Java backend's grpc-runtime injection, so even if (1) were fixed, generated*Grpc.scalafiles referencingscalapb.grpc.*/io.grpc.*would fail to compile withobject grpc is not a member of package scalapb/object io is not a member of package <root>.The net effect:
protobuf_sources(grpc=True)on a target resolved by the Scala backend silently produces plain message classes with no service stubs and no gRPC runtime dependency — no error, no warning, just nothing happens. This is surprising because the field already exists generically onprotobuf_source/protobuf_sourcesand visibly works for the Java backend, sogrpc=Truelooks like supported, portable behavior. It's a feature-parity gap between the two backends, not a missing feature.Pants version
Confirmed present as of
main(2.33.0a0 in progress) and 2.32.0. Introduced when ScalaPB codegen/dependency-inference were added (#13853, #14898) — those predateProtobufGrpcToggleFieldsupport even in the Java backend and were never revisited when Java gained it.OS
N/A (backend logic bug, not platform-specific)
Additional info
protobuf_source/protobuf_sources'ProtobufGrpcToggleFieldis defined once, generically, inpants/backend/codegen/protobuf/target_types.pyand consumed per-backend; it is not itself backend-specific.protobuf_sources(grpc=True)target whose.protodeclares aservice, resolved once under a JVM resolve with the Java backend active and once with the Scala backend active. Java backend: generatesFooServiceGrpc.javaand injects grpc-java coordinates. Scala backend: generates onlyFoo.scala(message classes), noFooServiceGrpc.scala, noscalapb-runtime-grpc/io.grpc.*dependency —grpc=Truehas zero observable effect.pants.backend.codegen.protobuf.java.dependency_inference) and am happy to open a PR.