|
| 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