Hi Romain,
I've pushed updates to the PR and companion plugins addressing the
feedback. Here's the summary:
Naming
Renamed across the board per the discussion:
- Package: o.a.m.api.build.context → o.a.m.api.build.incremental
- Interface: BuildContext → IncrementalContext
- SPI: CommittableBuildContext → CommittableIncrementalContext
- Impl: DefaultBuildContext → DefaultIncrementalContext
The user-facing skip property stays maven.buildcontext.skip for now — it
can always be updated later, and recognition matters more than consistency
there.
MojoConfigurationDigester — XML tree hashing
Rewrote the digester to walk the XML configuration tree from
MojoExecution.getConfiguration() instead of reflecting over field values.
For each element, it feeds the element name, attributes (minus
default-value), and the expression-evaluated text value into a SHA-1
digest. Expressions like ${project.build.directory} are resolved through
the ExpressionEvaluator, so -D property overrides are properly detected.
Nested elements are handled recursively.
Reflection is only used to read @Incremental annotations on the mojo class
(cached per class) — field values are never accessed via reflection. This
means the digester works correctly with any parameter type, including
collections, maps, and custom objects, without needing type-specific
serialization logic.
@Incremental(consider=false) is preserved — annotating a mojo field
excludes that parameter from change detection. The annotation targets
FIELD, METHOD, PARAMETER, and TYPE, with RUNTIME retention, so it's
available to the digester at execution time.
Companion plugin updates
All four companion plugins have been updated for the rename:
- maven-filtering (#363)
- maven-resources-plugin (#496)
- maven-jar-plugin (#566)
- maven-compiler-plugin (#1096)
Incremental annotation processor scanning (compiler plugin)
While updating the compiler plugin, I also added support for incremental
annotation processing. The compiler plugin now scans processor JARs for
incrementality descriptors before deciding whether to force a full rebuild:
- Reads META-INF/maven/incremental.annotation.processors (Maven-specific,
takes precedence)
- Falls back to META-INF/gradle/incremental.annotation.processors (Gradle's
established convention — Dagger, AutoValue, MapStruct, etc. already ship
these)
- Cross-references with
META-INF/services/javax.annotation.processing.Processor — any
ServiceLoader-declared processor without a descriptor entry triggers
conservative behavior
Format is one line per processor: com.example.MyProcessor,isolating
The aggregate logic: if all processors declare isolating, per-file
incremental compilation is preserved (no REBUILD_ON_ADD /
REBUILD_ON_CHANGE). If any is aggregating, the full set of annotated
sources is reprocessed on any change. dynamic or undeclared processors fall
back to the current full-rebuild-on-change behavior.
This doesn't require any API change — the IncrementalContext already has
the right primitives (Input.associateOutput() for isolating,
InputSet.aggregate() for aggregating). The descriptor format and scanning
logic lives entirely in the compiler plugin.
The PRs are all draft — happy to iterate on any of this.
------------------------
Guillaume Nodet
Le lun. 3 août 2026 à 16:36, Romain Manni-Bucau <[email protected]> a
écrit :
> Hi,
>
> Sounds a very good move, my 2 cts would be
>
> 1. while it ends in the new API it is great
> 2. why reflection since descriptor is in mem at some point? +1 to be able
> to tune it with a dedicated API
> 3. while documented yes IMHO
>
> side note: how would we make compilation incremental with annot proc?
> dedicated API as gradle? should we lean toward an unified api?
>
> Romain Manni-Bucau
> @rmannibucau <https://x.com/rmannibucau> | .NET Blog
> <https://dotnetbirdie.github.io/> | Blog <https://rmannibucau.github.io/>
> | Old
> Blog <http://rmannibucau.wordpress.com> | Github
> <https://github.com/rmannibucau> | LinkedIn
> <https://www.linkedin.com/in/rmannibucau> | Book
> <
> https://www.packtpub.com/en-us/product/java-ee-8-high-performance-9781788473064
> >
> Javaccino <https://javaccino.dev/> founder (Java/.NET service - contact
> via
> linkedin)
>
>
> Le lun. 3 août 2026 à 14:14, Guillaume Nodet <[email protected]> a
> écrit :
>
> > Hi all,
> >
> > I'd like to bring up the incremental build context work for discussion.
> >
> > Background
> >
> > This builds on a long lineage: the original plexus-build-api by Sonatype
> > (Igor Fedorenko), later evolved into Takari's io.takari.incrementalbuild
> > API, which powered m2e's incremental workspace builds in Eclipse. I
> started
> > porting this to Maven 4 in PR #1118 a while back; PR #12576 picks that
> up,
> > modernizes it to Maven 4 conventions (@MojoExecutionScoped DI,
> > @Experimental annotations, PathMatcherFactory reuse), adds performance
> > optimizations, and integrates it with four core plugins as
> > proof-of-concept.
> >
> > What it provides
> >
> > A first-class API in maven-api-core for mojo authors to track input file
> > changes, associate inputs with outputs, skip execution when nothing
> > changed, and get automatic stale output cleanup — all things the old
> > plexus-build-api did, but now as part of Maven's public API with an SPI
> > layer for IDE integration (workspace modes for m2e-style delta builds).
> >
> > The framework automatically digests @Parameter fields and the plugin
> > classpath to detect configuration changes — mojos get this for free
> without
> > implementing their own checks.
> >
> > Performance
> >
> > Benchmarked against stock 3.x plugins on a 20-module reactor (4000
> sources,
> > 600 resources):
> >
> > - No-op rebuild: −44% (15.7s → 8.7s)
> > - Single file change: −40%
> > - Delete + stale cleanup: −48%
> > - Clean build: +39% overhead (amortized after one incremental rebuild)
> >
> > A -Dmaven.buildcontext.skip=true property disables the context entirely
> for
> > CI/release builds.
> >
> > Plugin integrations
> >
> > - maven-resources-plugin#496 + maven-filtering#363
> > - maven-jar-plugin#566
> > - maven-compiler-plugin#1096
> >
> > Questions for discussion
> >
> > 1. Is o.a.m.api.build.context the right package home? (Chosen to avoid
> > collision with build report API in #12572)
> > 2. Automatic @Parameter digestion via reflection — should it be opt-in
> via
> > @Incremental instead?
> > 3. The context is per-mojo-execution, no cross-module coordination.
> > Sufficient for a first iteration?
> >
> > Main PR: https://github.com/apache/maven/pull/12576
> > Original PR: https://github.com/apache/maven/pull/1118
> >
> > Feedback welcome.
> >
> > Guillaume
> >
>