Skip to content

Propagate .jdeps for java_import - #363

Open
fmeum wants to merge 3 commits into
bazelbuild:masterfrom
fmeum:java-import-reduced-classpath
Open

Propagate .jdeps for java_import#363
fmeum wants to merge 3 commits into
bazelbuild:masterfrom
fmeum:java-import-reduced-classpath

Conversation

@fmeum

@fmeumfmeum commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Downstream Java compilation actions need accurate .jdeps files for their reduced classpath optimization. With this change, java_import now always runs ImportDepsChecker to generate this file, but possibly suppresses its outputs. Note that Bazel (but not Blaze) always silences the output.

Fixes#362

@fmeum
fmeumforce-pushed the java-import-reduced-classpath branch from 1c5b6ea to bbf650bCompareJune 30, 2026 10:08
@fmeumfmeum changed the title Make java_import participate in Java classpath reductionPropagate .jdeps for java_importJun 30, 2026
@fmeum
fmeumforce-pushed the java-import-reduced-classpath branch 2 times, most recently from bd8f649 to 1de17e5CompareJune 30, 2026 10:18

# Default java_toolchain parameters
_BASE_TOOLCHAIN_CONFIGURATION = dict(
deps_checker = Label("@remote_java_tools//:ImportDepsChecker"),

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change for Bazel as the hardcoded mode is error. Can I add a new attribute that makes it configurable on the toolchain level? I can set the default to silence to match the current behavior or to error as a breaking change with a simple migration.

Are you precompiling the tool to a native image at Google?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you precompiling the tool to a native image at Google?

It's a prebuilt jar that runs on the JVM, but it's also a validation action that is not on the critical path (#362 (comment)).

Using a native image seems like a good idea if it's going to run as a non-validation action so the .jdeps can be used for reduced classpaths.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can I add a new attribute that makes it configurable on the toolchain level?

Bazel supports tags = ["incomplete-deps"] on java_import. Having a real attribute (on the toolchain and/or individual java_imports) is probably better than leaning on tags for this.

cc @hvadehra

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My main concern is that external repos using java_import would be very difficult to opt out unless there is a global (toolchain) switch.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only be a breaking change for Bazel 7, which is okay I guess. I also don't see why we need a separate switch - one can just unset deps_checker on the toolchain.

@fmeum
fmeumforce-pushed the java-import-reduced-classpath branch 4 times, most recently from 1206db6 to 14e031cCompareJune 30, 2026 10:30
With `--experimental_java_classpath=bazel_no_fallback` (and as a double-compilation
pessimization under the default `bazel` mode), a `java_import` defeated the reduced-classpath
optimization for every target depending on it. Unlike a `java_library` header jar, which is built
by turbine (emitting a jdeps and repackaging the supertype closure), a `java_import` interface jar
is built by ijar and contributed no compile-time dependency artifact, so downstream reduced
classpaths pruned the import's transitive jars.
`java_import` now runs `ImportDepsChecker` (newly wired into the default toolchain's `deps_checker`)
over its jars and propagates the resulting jdeps proto as `compile_jdeps`. The checker records the
full transitive supertype closure, so this is correct for supertype chains of any depth. It runs in
`silence` mode (purely additive, never a new build failure) and only when the import has
deps/exports; the jdeps is consumed lazily.
Fixesbazelbuild#362
@fmeum
fmeumforce-pushed the java-import-reduced-classpath branch from 14e031c to 08211fdCompareJune 30, 2026 10:31
@fmeum

Copy link
Copy Markdown
ContributorAuthor

@cushon

@fmeum
fmeum marked this pull request as ready for review June 30, 2026 10:34
@fmeum
fmeum requested review from a team and hvadehra as code ownersJune 30, 2026 10:34

# Default java_toolchain parameters
_BASE_TOOLCHAIN_CONFIGURATION = dict(
deps_checker = Label("@remote_java_tools//:ImportDepsChecker"),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only be a breaking change for Bazel 7, which is okay I guess. I also don't see why we need a separate switch - one can just unset deps_checker on the toolchain.

Comment threadtest/java/common/rules/java_import_tests.bzl
Comment threadtest/java/common/rules/java_import_tests.bzl Outdated
Comment threadtest/java/common/rules/java_import_tests.bzl Outdated
Comment threadtest/java/common/rules/java_import_tests.bzl Outdated
Comment threadtest/java/common/rules/java_import_tests.bzl
@hvadehrahvadehra added P3 We're not considering to work on this, but happy to review a PR. (No assignee) enhancement New feature or request labels Jul 6, 2026
- Actually test the previously unused incomplete-deps-tagged target and
fix the assertions that all checked the same target.
- Use java_info_subject.from_target() for readable failure messages.
- Tag the test with min_bazel_8 since the rules_java Starlark
implementation is used from Bazel 8 on.
- Add a test for the ImportDepsChecker action's --checking_mode (and
--rule_label) flag, covering both the default java_import behavior
(always silence) and a rule that enforces the check via
skip_incomplete_deps_check = False (error, or silence with the
incomplete-deps tag).
@fmeum
fmeumforce-pushed the java-import-reduced-classpath branch from 7a08799 to 463ff11CompareJuly 7, 2026 13:42
@fmeum
fmeum requested a review from hvadehraJuly 7, 2026 13:44
# java_import only generates the jdeps proto, it never fails the build on incomplete deps.
assert_action = env.expect.that_target(target).action_named("ImportDepsChecker")
assert_action.contains_flag_values([
("--checking_mode", "silence"),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail internally (where this will be "error"). Mind putting just this test case in test/java/bazel/rules/java_import_tests.bzl?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@fmeum
fmeum requested a review from hvadehraJuly 8, 2026 14:47
The --checking_mode=silence assertion does not hold internally.
@fmeum
fmeumforce-pushed the java-import-reduced-classpath branch from 84facbd to 5daac7dCompareJuly 8, 2026 14:48
@hvadehra

Copy link
Copy Markdown
Member

Just a heads up: adding the jdep to JavaInfo breaks things internally with downstream kotlin rules. Will take some time to figure out.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancementNew feature or requestP3We're not considering to work on this, but happy to review a PR. (No assignee)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

classpath reduction defeated by transitive java_import dependencies

3 participants

@fmeum@hvadehra@cushon