bazelbuild / bazelbuild/bazel

Feat: Support pluggable Error Prone plugins via java_package_configuration

Open
#29,910 25 comments 0 reactions 0 assignees View on GitHub
P3 team-Rules-Java type: feature request
Dominant language
Java
Stars
25.8k
Forks
4.6k
Avg merge
2d 20h
Merged PRs (30d)
72

Description

### Description
Currently, there is no clean, public-facing API in Bazel or `@bazel_tools` to compile a custom `JavaBuilder` binary with extra Error Prone plugins/checkers (e.g., custom checks fetched from Maven) and use it in a custom `java_toolchain`. Extending the default `JavaBuilder` requires knowledge of internal Bazel targets, private dependencies (like `@io_bazel//third_party`), and complex packaging/merging logic.

This proposal introduces a clean, public-facing Starlark API exposed under `@bazel_tools//tools/jdk:javabuilder.bzl` that allows clients to easily define custom `JavaBuilder` binaries and Error Prone check suites.

### Prerequisite: Move JavaBuilder to `rules_java`
Currently, the source code for the `JavaBuilder` compiler wrapper resides in the Bazel repository under `src/java_tools/buildjar/`. To enable clean customization of JavaBuilder and its dependencies from Starlark, `JavaBuilder` should be migrated to the `rules_java` repository first.

#### Required Changes:
1. **Bazel Repository**:
- Remove `src/java_tools/buildjar/` from the source tree.
- Update `tools/BUILD` (`embedded_tools_srcs`) to remove JavaBuilder source filegroups.
- Update `scripts/bootstrap/BUILD.bootstrap` to reference `@rules_java//java_tools/buildjar:bootstrap_VanillaJavaBuilder_deploy.jar` and `@rules_java//java_tools/buildjar:bootstrap_genclass_deploy.jar`.
- Remove the `java_tools` packaging targets from `src/BUILD` (as release archives will be built by `rules_java`).
2. **`rules_java` Repository**:
- Import the `src/java_tools/buildjar/` directory and configure its BUILD targets.
- Resolve its external dependencies (e.g. Guava, AutoValue, JSR305) using `rules_java`'s module/workspace dependencies.
- Expose the Starlark APIs (`default_javabuilder`, `errorprone_with_custom_plugins`) from `rules_java` directly.
- Set up release pipelines to build and package `java_tools.zip` for distribution.

### Proposed API Changes
We introduce two new public-facing rules/macros in `@bazel_tools//tools/jdk:javabuilder.bzl`:
1. `default_javabuilder`: A macro that packages a `JavaBuilder` executable. The default vanilla `JavaBuilder` is built by passing the default third-party Error Prone core libraries, while custom configurations can pass custom merged Error Prone engines.
2. `errorprone_with_custom_plugins`: A rule that merges a base Error Prone library (e.g. core Error Prone fetched from Maven) with custom checkers/plugins.

```starlark
load("@bazel_tools//tools/jdk:javabuilder.bzl", "default_javabuilder", "errorprone_with_custom_plugins")
load("@rules_java//toolchains:default_java_toolchain.bzl", "DEFAULT_TOOLCHAIN_CONFIGURATION", "default_java_toolchain")

# 1. Merge core Error Prone with a custom plugin
errorprone_with_custom_plugins(
name = "my_errorprone",
errorprone = "@maven//:com_google_errorprone_error_prone_core",
plugins = [":my_plugin"],
)

# 2. Build the custom JavaBuilder deploy jar
default_javabuilder(
name = "custom_javabuilder",
errorprone = [":my_errorprone"],
)

# 3. Associate it with a custom java_toolchain
default_java_toolchain(
name = "custom_toolchain",
configuration = DEFAULT_TOOLCHAIN_CONFIGURATION,
javabuilder = ":custom_javabuilder_deploy.jar",
)
```

> [!NOTE]
> **Package-Level Configuration**: Once a custom `JavaBuilder` is registered with the toolchain, users can configure the activation, severity, and options of these custom checkers on a package-by-package basis using the existing `java_package_configuration` API's `javacopts` attribute (e.g. passing `"-Xep:CustomCheck:ERROR"` for strict packages and `"-Xep:CustomCheck:OFF"` for legacy packages).

### Implementation Overview & Expected Diffs

#### 1. Bazel Core Diffs

* **API & Refactored JavaBuilder Targets** (`src/java_tools/buildjar/java/com/google/devtools/build/buildjar/BUILD`):
```diff
+java_library(
+ name = "javabuilder_errorprone_api",
+ srcs = ["javac/plugins/errorprone/ErrorProneInvoker.java"],
+ visibility = ["//visibility:public"],
+)
+
java_library(
- name = "buildjar",
- srcs = glob(["**/*.java"]),
- deps = ["//third_party:error_prone", ...],
+ name = "javabuilder_without_errorprone",
+ srcs = glob(
+ ["**/*.java"],
+ exclude = ["javac/plugins/errorprone/ErrorProneInvokerImpl.java"],
+ ),
+ deps = [
+ ":javabuilder_errorprone_api",
+ # other non-errorprone dependencies
+ ],
)
```
* **ServiceLoader Hook** in JavaBuilder:
```diff
+ServiceLoader loader = ServiceLoader.load(ErrorProneInvoker.class);
+Iterator iterator = loader.iterator();
+if (iterator.hasNext()) {
+ ErrorProneInvoker invoker = iterator.next();
+ invoker.init(context);
+}
```
* **Export API & Base targets in `@bazel_tools`** (`tools/BUILD`):
```diff
filegroup(
name = "embedded_tools_srcs",
srcs = [
...
+ "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:javabuilder_errorprone_api",
+ "//src/java_tools/buildjar/java/com/google/devtools/build/buildjar:javabuilder_without_errorprone",
...
],
)
```

#### 2. `rules_java` Diffs

* **Assemble JavaBuilder via `default_javabuilder`** (`toolchains/default_java_toolchain.bzl`):
```diff
+load("@bazel_tools//tools/jdk:javabuilder.bzl", "default_javabuilder")

def default_java_toolchain(name, ...):
+ default_javabuilder(
+ name = name + "_javabuilder",
+ errorprone = ["@rules_java//third_party:error_prone"],
+ )
+
native.java_toolchain(
name = name,
- javabuilder = ["@bazel_tools//tools/jdk:JavaBuilder_deploy.jar"],
+ javabuilder = [":" + name + "_javabuilder_deploy.jar"],
...
)
```

Contributor guide

Open the contributing guide

Research direction

Start by reading the JavaBuilder sources under src/java_tools/buildjar/ and the related targets in src/BUILD, tools/BUILD, and scripts/bootstrap/BUILD.bootstrap. Then inspect rules_java's toolchains/default_java_toolchain.bzl and its dependency configuration. Done means JavaBuilder can be migrated and packaged through the proposed public Starlark APIs, with custom Error Prone plugins usable in a java_toolchain.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
build-system
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.