Skip to content

Commit bb790c6

Browse files
Copilotchrisrueger
andauthored
Add docs for -rebuildtriggerpolicy instruction
Agent-Logs-Url: https://github.com/bndtools/bnd/sessions/57d334d7-fc24-4905-ba18-38784bd01631 Co-authored-by: chrisrueger <188422+chrisrueger@users.noreply.github.com>
1 parent 24171ca commit bb790c6

1 file changed

Lines changed: 88 additions & 0 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
---
2+
layout: default
3+
class: Project
4+
title: -rebuildtriggerpolicy (always|api)
5+
summary: Controls when a rebuilt bundle is treated as changed for downstream builds.
6+
---
7+
8+
# -rebuildtriggerpolicy
9+
10+
## Intention
11+
12+
When a bundle is rebuilt in a bnd workspace, downstream projects check whether they need to rebuild by inspecting the `lastModified` timestamp of the dependency's output JAR. By default (`always`), every rebuild updates the JAR's timestamp, and all downstream projects recompile even if nothing relevant to them actually changed.
13+
14+
The `api` policy eliminates unnecessary cascade rebuilds by preserving the output JAR's timestamp when the rebuild did not produce a meaningfully different artifact. Two levels of comparison are performed in order:
15+
16+
1. **Content digest** — A stable, timeless hash of the entire JAR content (excludes timestamps embedded in entries). If the content is byte-identical to the previous build, the timestamp is preserved immediately. This covers cases such as a comment-only source change where the compiler produces identical bytecode.
17+
18+
2. **API digest** — A hash of the _exported API surface_: the public and protected types, methods, and fields in all packages listed in `Export-Package`. If the content changed (e.g. a method body was modified) but the exported API is identical, the timestamp is still preserved. Downstream projects that only consume the exported API will not see any change and therefore skip rebuilding.
19+
20+
When the timestamp is preserved, downstream projects' staleness checks find that the dependency is not newer than their own output, so no cascade rebuild is triggered — not even the recursive `isStale()` check that runs before any timestamp comparison.
21+
22+
The two digest sidecar files (`.digest` and `.api-digest`, stored next to the output JAR) are created on the first build with this policy and updated on every subsequent build. They are intentionally **not** created when the default `always` policy is active, to avoid polluting existing projects.
23+
24+
> **Note:** The `api` policy only considers _exported_ packages. Changes to private packages or internal implementation classes are intentionally invisible to this check and will preserve the timestamp, because downstream bundles cannot legally depend on them.
25+
26+
## Values
27+
28+
| Value | Description |
29+
|-------|-------------|
30+
| `always` | _(default)_ Every rebuild updates the JAR timestamp. All downstream projects will be considered stale and rebuild. |
31+
| `api` | Preserves the JAR timestamp when the rebuilt content is byte-identical **or** when the exported API surface is unchanged. Downstream projects only rebuild when the API actually changes. |
32+
33+
## Sidecar files
34+
35+
When the `api` policy is active, bnd stores two small sidecar files next to each output JAR (e.g. `myproject.jar`):
36+
37+
| File | Contains |
38+
|------|----------|
39+
| `myproject.jar.digest` | Hex-encoded SHA-1 of the entire JAR content (timeless) |
40+
| `myproject.jar.api-digest` | Hex-encoded SHA-1 of the exported API surface |
41+
42+
These files are used to compare builds across sessions. They can safely be added to `.gitignore` or your VCS ignore list because they are always regenerated on the next build.
43+
44+
## Examples
45+
46+
### Enable API-level optimization globally (workspace `cnf/build.bnd`)
47+
48+
```properties
49+
# Preserve JAR timestamps when only non-API implementation details change.
50+
# Avoids rebuilding all downstream projects after minor internal edits.
51+
-rebuildtriggerpolicy: api
52+
```
53+
54+
### Enable only for Eclipse; use default (always) for Gradle and other builds
55+
56+
Bndtools in Eclipse typically runs incremental builds on every save. Enabling the `api` policy there prevents a change in one project from cascading through all dependents when nothing in the exported API changed. Regular Gradle CI builds, which build everything from scratch, do not need the optimization and can keep the safe default.
57+
58+
```properties
59+
# In cnf/build.bnd or bnd.bnd:
60+
-rebuildtriggerpolicy: ${if;${driver;eclipse};api;always}
61+
```
62+
63+
The `${driver;eclipse}` macro evaluates to `true` when the build is driven by the Bndtools Eclipse builder, and to an empty string otherwise. The `${if;...;api;always}` macro selects `api` for Eclipse and `always` for everything else (Gradle, Maven, bnd CLI, etc.).
64+
65+
### Enable in a single project only
66+
67+
Place the instruction in the project's `bnd.bnd` file to scope the optimization to that project only:
68+
69+
```properties
70+
# myproject/bnd.bnd
71+
-rebuildtriggerpolicy: api
72+
```
73+
74+
### Force all downstream rebuilds unconditionally (explicit default)
75+
76+
```properties
77+
-rebuildtriggerpolicy: always
78+
```
79+
80+
## Interaction with `-dependson`
81+
82+
The `api` policy works through the existing timestamp-based staleness infrastructure. When a dependency's JAR timestamp is preserved, a downstream project's `isStale()` check — which first recurses into each dependency and then compares timestamps — never sees a newer file and therefore does not rebuild. No additional configuration is required on the consuming project side.
83+
84+
## See Also
85+
86+
* [`-dependson`](dependson.html) — Declares explicit project build-order dependencies.
87+
* [`-builderignore`](builderignore.html) — Excludes directories from the Eclipse/Gradle incremental builder.
88+
* [`${driver}`](../macros/driver.html) — Macro that returns the current build driver (`eclipse`, `gradle`, `bnd`, …).

0 commit comments

Comments
 (0)