Change-detect and quiet the automatic sbt meta-build export#2958
Conversation
The sbt-bloop plugin exports the sbt meta-build (the build definition under project/) on every load so Metals can compile it. This made sbt startup slower and noisier than without the plugin. - Skip the on-load export when a fingerprint of the files under project/ is unchanged. The fingerprint is stamped in .bloop whenever bloopInstall exports the meta-build, so startup is fast and silent once the build definition is stable, while edits/additions/deletions still regenerate. - Log the automatic export at debug level; a manual bloopInstall still reports as before. - Add a bloopExportMetaBuild opt-out via the BLOOP_EXPORT_META_BUILD environment variable / bloop.export-meta-build system property (global, covers nested meta-builds) or the per-layer setting. Adds scripted tests for change detection (edit/add/delete) and the opt-out across nested meta-build layers.
| * are still invalidated. Inputs that are not files under `project/` (system | ||
| * properties, environment variables, …) are out of scope. | ||
| */ | ||
| private def metaBuildFingerprint(buildBase: File): String = { |
There was a problem hiding this comment.
We shouldn't calculate the fingerprints ourselves, this something that sbt is doing and we should delegate to it if needed.
There was a problem hiding this comment.
The meta-build export is now opt-in via the bloop.export-meta-build system property (default off), so there's nothing to change-detect: a plain sbt never exports the meta-build, and when the property is set it always regenerates fresh.
| } else if (isMetaBuild) { | ||
| // Stamp the change-detection fingerprint so the next load can skip, | ||
| // regardless of whether this `bloopInstall` was automatic or manual. | ||
| writeMetaBuildFingerprint(metaBuildBase) |
There was a problem hiding this comment.
Maybe instead of writting we could use a java property? -Dexport-meta=true or something along those lines? We could add it by default in Metals when running bloopInstall.
There was a problem hiding this comment.
Added -Dbloop.export-meta-build=true (default off), so Metals can set it when running bloopInstall. I namespaced the property to match the existing bloop.export-jar-classifiers. Happy to rename to export-meta or whatever you'd prefer. Heads-up for the changelog: any non-Metals consumer that relied on the old default auto-export will now need to set this property.
|
Added the property to metals scalameta/metals#8538 |
Closes #1357.
Problem
The sbt-bloop plugin exports the sbt meta-build (the build definition under
project/) to bloop on every load, so Metals can compile and navigateproject/*.scala/*.sbt. This makessbtstartup slower and prints confusing (and duplicated)[success] Generated …jsonlines on every load.Fully reverting the auto-export isn't an option (Metals depends on it) so this keeps it on by default but removes the cost and the noise.
What changed
project/(path + mtime + size, withtarget/.bloopsubtrees pruned) is unchanged. The fingerprint is stamped in.bloopwheneverbloopInstallexports the meta-build, so a steady-statesbtstartup is fast and silent, while edits / additions / deletions regenerate. Change detection fails safe: any IO error falls back to exporting, so it can never break load.debug; a manualbloopInstallkeeps its usual[success]output. Quietness is keyed on the on-load path rather than on "is this a meta-build", so manual runs are unaffected.bloopExportMetaBuild. Disable globally with-Dbloop.export-meta-build=falseorBLOOP_EXPORT_META_BUILD=false(read at every meta-build layer, so it also covers nestedproject/projectbuilds), or per layer withGlobal / bloopExportMetaBuild := false. Documented indocs/build-tools/sbt.md.Scope / caveat
The fingerprint tracks files under
project/only. Inputs read from elsewhere — system properties, environment variables, or files outsideproject/— are not detected; abloopInstall(or any edit underproject/) forces a refresh. This is documented in the new docs section.Sorry for long PR, wanted to split/stack it, but wasn't very successful.