Skip to content

bazel: add java_proto_library targets for all protos#607

Open
smolkaj wants to merge 1 commit intop4lang:mainfrom
smolkaj:add-java-proto-library
Open

bazel: add java_proto_library targets for all protos#607
smolkaj wants to merge 1 commit intop4lang:mainfrom
smolkaj:add-java-proto-library

Conversation

@smolkaj
Copy link
Copy Markdown
Member

@smolkaj smolkaj commented Apr 11, 2026

Summary

Adds first-class java_proto_library wrappers for p4info_proto, p4types_proto, p4data_proto, and p4runtime_proto, alongside the existing cc/py/go targets:

  • //proto/p4/config/v1:p4info_java_proto
  • //proto/p4/config/v1:p4types_java_proto
  • //proto/p4/v1:p4data_java_proto
  • //proto/p4/v1:p4runtime_java_proto

They're also added to each package's proto_build_test so they're exercised on every CI run.

Motivation

Every downstream Kotlin/Java consumer of p4runtime today (e.g. 4ward, DVaaS, sonic-pins) has to define these wrappers locally and duplicate them package by package. Shipping them upstream removes that boilerplate.

There's a second motivation that's become sharper with recent Kotlin tooling: Bazel rule sets like rules_kotlin with experimental_strict_kotlin_deps = "error" require a direct java_proto_library dep for every proto whose generated classes your code references. Generated Java classes that materialize transitively via another java_proto_library don't satisfy the check — you need the direct target, by name. Without upstream wrappers, every strict-deps-enabled consumer has to define them locally, even though the generated .class files are bit-identical across callers.

smolkaj added a commit to smolkaj/4ward that referenced this pull request Apr 11, 2026
Every Kotlin target in 4ward must now declare every dependency whose
symbols its source actually uses — no more silently relying on a
transitive dep to bring in a class. The same kind of dep-leak that
motivated promoting stf/ to a top-level package (#510) is now caught
at analysis time, across the whole tree, before the reviewer has to
notice.

## What's enabled

`experimental_strict_kotlin_deps = "error"` on a custom Kotlin
toolchain registered ahead of the rules_kotlin default (see
`bazel/BUILD.bazel` and the `register_toolchains` in `MODULE.bazel`).

`experimental_report_unused_deps` is deliberately left off: it
misfires on 4ward's intentional mix of rules_jvm_external Maven
artifacts and Bazel-native targets that provide the same `.class`
files. 4ward uses the Maven style by design so BCR consumers don't
need `known_contributing_modules` boilerplate (see the comment in
`MODULE.bazel`). The strict_kotlin_deps half is where the actual
value lives — it catches the real problem (undeclared transitive
deps) without the noise of the unused-deps half.

## What had to change to make it green

- **`//simulator`** gains four new `java_proto_library` wrappers
  (`p4info_java_proto`, `p4data_java_proto`, `p4types_java_proto`
  alongside the existing `p4runtime_java_proto`). Strict-deps needs a
  *direct* Java wrapper for each proto whose generated classes the
  Kotlin code references — transitively-materialized classes don't
  count. A TODO points at p4lang/p4runtime#607, an upstream PR adding
  these wrappers directly to the p4runtime module. Once that lands
  and a BCR release is out, the 4ward-side wrappers can go away.
- **`//p4runtime`** drops its duplicate `p4info_java_proto` and
  `p4runtime_java_proto` wrappers and re-routes to the canonical ones
  in `//simulator`. Fewer targets, no behavior change.
- **`MODULE.bazel`** gains direct `bazel_dep` entries for `googleapis`
  and `googleapis-java` so `@googleapis//google/rpc:rpc_java_proto`
  is reachable by apparent name (it was previously transitive via
  `@p4runtime`).
- **`bazel/grpc_kotlin.patch`** fixes three strict-deps blockers in
  `grpc_kotlin@1.5.0`: the `compiler/.../generator` target needs the
  JVM variant of `kotlinx-coroutines-core` (the multiplatform JAR
  split is invisible to strict-deps), and the `kt_jvm_grpc_library`
  macro needs to forward `@grpc-java//api`, the JVM coroutines JAR,
  and the user's `java_proto_library` into the generated library's
  `kt_deps`. Wired via `single_version_override` + `patches`, the
  same pattern already used for grpc and behavioral_model.
- **~50 `kt_jvm_library` / `kt_jvm_test` deps** across the tree get
  the right directly-named dep added. Applied mechanically via
  buildozer, then re-translated by hand where strict-deps reported
  a raw `proto_library` label that a Kotlin target can't actually
  consume (every such case had to route through a `java_proto_library`
  wrapper instead).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@smolkaj smolkaj force-pushed the add-java-proto-library branch from 9c33dc5 to a88f348 Compare April 11, 2026 20:03
Add first-class `java_proto_library` wrappers for `p4info_proto`,
`p4types_proto`, `p4data_proto`, and `p4runtime_proto` alongside the
existing cc/py/go targets.

This lets Kotlin/Java consumers depend directly on the generated Java
classes without having to define their own wrappers. Under Bazel rule
sets like rules_kotlin with `strict_kotlin_deps = "error"`, users need
a direct `java_proto_library` dep for every proto whose generated
classes their code references — transitively-materialized Java classes
don't satisfy the check. Today every Kotlin consumer of p4runtime
(e.g. 4ward, DVaaS, sonic-pins) has to define these wrappers locally
and duplicate them package by package; shipping them upstream removes
that boilerplate.

Signed-off-by: Steffen Smolka <steffen.smolka@gmail.com>
@smolkaj smolkaj force-pushed the add-java-proto-library branch from a88f348 to a73a716 Compare April 11, 2026 20:03
@smolkaj smolkaj requested a review from chrispsommers April 11, 2026 20:04
smolkaj added a commit to smolkaj/4ward that referenced this pull request Apr 11, 2026
## Summary

Every Kotlin target in 4ward must now declare every dependency whose
symbols its source actually uses — no more silently relying on a
transitive dep to bring in a class. The same kind of dep-leak that
motivated promoting `stf/` to a top-level package (#510) is now caught
at analysis time, across the whole tree, before a reviewer has to
notice.

This is a ~275-line BUILD-file-only change (no production code touched).
If you've been wondering why a target has an over-broad dep list now,
it's because strict mode requires calling out every symbol source by
name.

## What's enabled

- `experimental_strict_kotlin_deps = "error"` on a custom Kotlin
toolchain registered ahead of the `rules_kotlin` default
(`bazel/BUILD.bazel`, `MODULE.bazel`).
- `experimental_report_unused_deps` is **deliberately not enabled**. It
misfires on 4ward's intentional mix of `rules_jvm_external` Maven
artifacts and Bazel-native targets that provide the same `.class` files.
4ward uses the Maven style by design so BCR consumers don't need
`known_contributing_modules` boilerplate (see the comment in
`MODULE.bazel` and `bcr_test_module/`). The strict-deps half is where
the actual value lives — it catches the real problem (undeclared
transitive deps) without the noise.

## What had to change to make it green

**`//simulator` gains four `java_proto_library` wrappers.** Strict-deps
needs a *direct* Java wrapper for each proto whose generated classes are
referenced — transitively-materialized classes don't count. New:
`p4info_java_proto`, `p4data_java_proto`, `p4types_java_proto`
(alongside the existing `p4runtime_java_proto`). A `TODO` points at
**[p4lang/p4runtime#607](p4lang/p4runtime#607,
an upstream PR I filed that adds these wrappers directly to the
p4runtime module. Once that lands and a BCR release is out, the
4ward-side wrappers can go away.

**`//p4runtime` drops its duplicate Java-proto wrappers.** The package
used to define its own `p4info_java_proto` and `p4runtime_java_proto`
alongside `//simulator`'s copies. Both sets now route through
`//simulator`'s, which is the lower-layer package. Fewer targets, no
behavior change.

**`MODULE.bazel` gains direct `bazel_dep` entries for `googleapis` and
`googleapis-java`** so `@googleapis//google/rpc:rpc_java_proto` is
reachable by apparent name (it was previously transitive via
`@p4runtime`).

**`bazel/grpc_kotlin.patch` is new.** It fixes two classes of
strict-deps blocker in `grpc_kotlin@1.5.0`:
1. The `compiler/.../generator` target declares the common
`kotlinx-coroutines-core` artifact, but strict-deps traces the JVM
classes to the `-jvm` variant (the multiplatform JAR split is invisible
to strict-deps). Fix: switch to the JVM variant.
2. The `kt_jvm_grpc_library` macro generates a `kt_jvm_library` whose
Kotlin source references `io.grpc.*`, `kotlinx.coroutines.*`, and the
user's own proto classes, without declaring them directly. Fix: extend
the macro's hardcoded `kt_deps` to include `@grpc-java//api`, the JVM
coroutines artifact, and forward the caller's `java_proto_library` dep.

Wired via `single_version_override` + `patches` in `MODULE.bazel`, the
same pattern already used for `grpc` and `behavioral_model`. The patch
carries a `TODO` to drop it once an equivalent upstream change lands in
grpc-kotlin.

**~50 `kt_jvm_library` / `kt_jvm_test` deps** get the right
directly-named dep added. Applied mechanically via `buildozer`, then
re-translated by hand where strict-deps reported a raw `proto_library`
label that a Kotlin target can't actually consume — every such case had
to route through a `java_proto_library` wrapper instead.

## Not in scope

- Switching 4ward off the `@fourward_maven//:...` Maven-style deps to
`@grpc-java//...` native Bazel targets. That would break BCR-consumer
ergonomics and is explicitly out of bounds.
- Enabling `report_unused_deps`. Blocked on the same trade-off.

## Test plan
- [x] `bazel build //...` — 1736 targets green
- [x] `bazel test //... --test_tag_filters=-heavy` — 63/63 pass
- [x] `./tools/format.sh` + `./tools/lint.sh` — clean
- [ ] CI green (wait before merging)

## Follow-ups
- p4lang/p4runtime#607 — upstream wrappers, then drop the ones in
`//simulator`.
- A grpc-kotlin upstream PR for the macro change, then drop
`bazel/grpc_kotlin.patch`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant