Skip to content

Per-class tracking to achieve higher level of compilation avoidance#1530

Open
oliviernotteghem wants to merge 1 commit intobazel-contrib:masterfrom
oliviernotteghem:upstream-perclasscompavoidance
Open

Per-class tracking to achieve higher level of compilation avoidance#1530
oliviernotteghem wants to merge 1 commit intobazel-contrib:masterfrom
oliviernotteghem:upstream-perclasscompavoidance

Conversation

@oliviernotteghem
Copy link
Copy Markdown
Contributor

This change adds support for per-class compilation avoidance, enabling fine-grained dependency tracking during Kotlin compilation. When enabled, the jdeps output records exactly
which classes from each dependency JAR are used, along with SHA-256 hashes of their bytecode.

Motivation

Traditional compilation avoidance works at the JAR level—if any file in a dependency JAR changes, all dependents must recompile. Per-class tracking improves this by allowing
build systems to skip recompilation when a dependency JAR changes but the specific classes actually used remain unchanged (same hashes).

Configuration

Two new toolchain attributes:

define_kt_toolchain(
name = "my_toolchain",
experimental_track_class_usage = "on", # Track class usage with hashes
experimental_track_resource_usage = "on", # Track Android R class references
)

Changes

Proto definitions:

  • deps.proto: Added UsedClass message with fullyQualifiedName, internalPath, and hash fields; added usedResources field to Dependencies
  • kotlin_model.proto: Added track_class_usage and track_resource_usage fields

JDeps plugin:

  • Added configuration keys and CLI options for the new tracking flags
  • BaseJdepsGenExtension: Added getHashFromJarEntry() to compute SHA-256 hashes; updated doWriteJdeps() to write UsedClass entries when tracking is enabled
  • JdepsGenExtension (K1): Added resource tracking for Android R class references
  • K2 extensions: Added usedResources support

Builder:

  • Added TRACK_CLASS_USAGE and TRACK_RESOURCE_USAGE flags to KotlinBuilder
  • Pass tracking flags to jdeps plugin in KotlinJvmTaskExecutor

Starlark rules:

  • toolchains.bzl: Added experimental_track_class_usage and experimental_track_resource_usage attributes
  • compile.bzl: Pass tracking flags to builder

Output Format

When enabled, jdeps includes per-class entries:

dependency {
path: "bazel-out/.../libparser.jar" kind: EXPLICIT usedClasses { fullyQualifiedName: "com.lib.Parser" internalPath: "com/lib/Parser.class"
hash: <32 bytes SHA-256>
} }

Testing

Added KotlinBuilderJvmClassTrackingTest with tests verifying:

  • Tracking is disabled by default (no UsedClass entries)
  • Tracking records classes with hashes when enabled
  • Multiple classes are tracked correctly
  • Supertype dependencies are included
  • Hashes are deterministic across compilations

repeated SourceLocation location = 3;

// List of used classes from this dependency (for per-class compilation avoidance).
repeated UsedClass usedClasses = 4;
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.

this is a divergence vs Bazel jdeps

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

See my comment below (where the same proto changes are done in the mentioned PR).

Comment thread kotlin/internal/toolchains.bzl Outdated
],
),
"experimental_track_class_usage": attr.string(
doc = """Enable per-class compilation avoidance. Records which specific classes
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.

turning this on doesn't really enable (as in: cause) any compilation avoidance, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@agluszak : you're absolutely right. To enable consumption of the class usage data and enable more granular compilation avoidance you need also this change on Bazel core bazelbuild/bazel#16457

@oliviernotteghem oliviernotteghem force-pushed the upstream-perclasscompavoidance branch 4 times, most recently from 7bae6b9 to d4a37d3 Compare March 22, 2026 03:21
@oliviernotteghem oliviernotteghem force-pushed the upstream-perclasscompavoidance branch from d4a37d3 to 37c8787 Compare March 22, 2026 17:47
ryanulep pushed a commit to uber-common/rules_kotlin that referenced this pull request Apr 9, 2026
ryanulep pushed a commit to uber-common/rules_kotlin that referenced this pull request Apr 16, 2026
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.

2 participants