Conversation
After building a project's JAR, compute a timeless content digest and compare with the previously stored digest. If the content is unchanged, preserve the old JAR's timestamp. This prevents dependent projects from seeing a newer timestamp and triggering unnecessary rebuilds. The optimization uses Jar.getTimelessDigest() which ignores build-time-specific data (BND_LASTMODIFIED, version qualifier) to determine if the meaningful content has changed. A .digest sidecar file stores the hex digest alongside each build output. Agent-Logs-Url: https://github.com/bndtools/bnd/sessions/662b413c-3754-4104-a50f-cb8503721220 Co-authored-by: chrisrueger <188422+chrisrueger@users.noreply.github.com>
Agent-Logs-Url: https://github.com/bndtools/bnd/sessions/662b413c-3754-4104-a50f-cb8503721220 Co-authored-by: chrisrueger <188422+chrisrueger@users.noreply.github.com>
Copilot created this pull request from a session on behalf of
chrisrueger
April 18, 2026 08:49
View session
Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
Compute a SHA-1 digest of the exported API surface (public/protected types, methods, and fields in Export-Package packages) using the existing DiffPluginImpl/JavaElement infrastructure. After building a JAR, store the API digest in a .api-digest sidecar file. When checking isStale() for dependencies, if a dependency's JAR is newer but its API digest hasn't changed, skip the rebuild. This handles the common case where only internal implementation details change (method bodies, private fields) but the exported API surface is unchanged - dependent projects don't need rebuilding. Also records dependency API digest state at build time in a deps-api-digests properties file so we can detect changes between builds. Agent-Logs-Url: https://github.com/bndtools/bnd/sessions/4441a6c7-8747-4fb8-aeac-a4eb08e14c64 Co-authored-by: chrisrueger <188422+chrisrueger@users.noreply.github.com>
…ebuilds Move the API digest check from isStale() into calcPreserveTimestamp(). When a JAR's content changes but its exported API surface is unchanged (e.g. only method bodies modified), the JAR's timestamp is preserved. This prevents downstream projects from ever seeing a newer dependency, eliminating unnecessary cascade rebuilds at the source. Previously, the API digest check was in isStale() as a secondary check, but the recursive dependency.isStale(visited) call could short-circuit before reaching it. By integrating the check into the timestamp preservation logic, the optimization works with the existing staleness infrastructure rather than adding a secondary check that can be bypassed. Removed the now-redundant Level 2 isStale() infrastructure: - hasDependencyApiChanged() - saveDependencyApiDigests() - DEPS_API_DIGESTS constant - deps-api-digests properties file Agent-Logs-Url: https://github.com/bndtools/bnd/sessions/dd3b844c-df7b-41a7-a3f1-eb0c95564c39 Co-authored-by: chrisrueger <188422+chrisrueger@users.noreply.github.com>
Agent-Logs-Url: https://github.com/bndtools/bnd/sessions/dd3b844c-df7b-41a7-a3f1-eb0c95564c39 Co-authored-by: chrisrueger <188422+chrisrueger@users.noreply.github.com>
Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
Contributor
|
First experiments in my larger project look very promising. Simple java changes which do not change public API or the manifest do not cause a downstream rebuild cascade. Only e.g. changes to interfaces , method signatures etc. would cause a downstream rebuild of dependant projects like before. This makes development nicer since it cuts down waiting time a lot. |
Introduce BuildChangePolicy for build digests Move JAR content/API digest computation and timestamp-preservation logic into a new BuildChangePolicy helper and use it from Project.saveBuildWithoutClose. Project now calls BuildChangePolicy.doBuildChangePolicy to decide whether to preserve output timestamps and to obtain digest file paths; persistBuildChangePolicyResult stores digest files and applies the preserved timestamp when appropriate. Added the -buildchangepolicy constant and Syntax help (supports 'always' and 'api' behaviors) and updated option sets and call sites to use the new accessors. Removed the older calcDigest/calcApiDigest/calcPreserveTimestamp helpers and inlined their behavior into the new class to centralize policy behavior. Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
intent is clearer Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
Agent-Logs-Url: https://github.com/bndtools/bnd/sessions/57d334d7-fc24-4905-ba18-38784bd01631 Co-authored-by: chrisrueger <188422+chrisrueger@users.noreply.github.com>
Contributor
|
@peterkir FYI Let's discuss next week. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request introduces a new build optimization to the bnd build system, allowing projects to avoid unnecessary rebuilds of dependent artifacts when the output JAR's content or exported API has not changed. The feature is controlled by a new
-rebuildtriggerpolicyproperty, which can be set to eitheralways(the default) orapi. When set toapi, the system preserves the JAR's timestamp if the content or exported API is unchanged, thereby preventing downstream rebuild cascades. The implementation includes content and API digest calculation and storage, as well as comprehensive tests validating the new behavior.Testing
/cnf/build.bndor to tie it only to Eclipse builds
Press Refresh Bnd Workspace button
rebuild the whole workspace (e.g. clean all just once)
Go to a Bundle A of your choise which has many downstream bundles which depend on A (usually some util bundle at the root of the bundle hiearchy which is used by every bundle)
Pick a random java method and add a
System.out.println("hello");Save the file
Expected result:
Expected result:
Previous bahavior before this PR:
If you remove
-rebuildtriggerpolicyfrombuild.bndif should behave as before this PR - all downstream projects should be build with each change all the time.Key changes:
Build Optimization: Content/API Digest and Timestamp Preservation
RebuildTriggerPolicymechanism inProject.java, which determines whether to preserve the build artifact's timestamp based on content or API digests. This prevents unnecessary downstream rebuilds when the output JAR is unchanged or only non-API changes occurred. The policy supportsalways(default) andapimodes, with digest files (.digestand.api-digest) used for comparison. [1] [2] [3]Configuration and Documentation
-rebuildtriggerpolicyproperty toConstants.javaand included it in the recognized options set. [1] [2]Syntax.java.Testing
ProjectTest.javato verify:Dependency and Import Updates
Project.java. [1] [2] [3] [4] [5]