Skip to content

Commit 190bebe

Browse files
authored
Merge pull request #2958 from jozanek/issue-1357-quiet-meta-build-export
Change-detect and quiet the automatic sbt meta-build export
2 parents 790f55a + 6b50cde commit 190bebe

9 files changed

Lines changed: 81 additions & 3 deletions

File tree

docs/build-tools/sbt.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,5 +261,32 @@ either you or an sbt plugin are incremental and complete as soon as possible.
261261
Lastly, make sure you keep a hot sbt session around as much time as possible. Running `bloopInstall`
262262
a second time in the sbt session is *really* fast.
263263

264+
### Export the sbt meta-build
265+
266+
Bloop can also export the sbt **meta-build** (the build definition under `project/`) so that Metals
267+
and similar tools can compile and navigate your `project/*.scala` and `*.sbt` sources. This is
268+
**opt-in** — a plain `sbt` session does not export the meta-build, so startup stays fast and quiet.
269+
270+
Enable it with the `bloop.export-meta-build` system property or the `BLOOP_EXPORT_META_BUILD`
271+
environment variable. These are read at every meta-build layer, so they also cover nested
272+
`project/project` builds:
273+
274+
```bash
275+
sbt -Dbloop.export-meta-build=true
276+
# or
277+
BLOOP_EXPORT_META_BUILD=true sbt
278+
```
279+
280+
Metals sets this automatically when it runs `bloopInstall`, so meta-build navigation works there
281+
without any extra configuration.
282+
283+
You can also enable it from the build with the `bloopExportMetaBuild` setting, but it only affects the
284+
layer it is defined in (`project/*.sbt` configures the outer meta-build, `project/project/*.sbt` the
285+
next one down), so for nested meta-builds prefer the property or environment variable above:
286+
287+
```scala
288+
Global / bloopExportMetaBuild := true
289+
```
290+
264291
[sbt-configuration]: https://www.scala-sbt.org/1.x/docs/Multi-Project.html
265292
[integration-test-conf]: https://www.scala-sbt.org/1.0/docs/offline/Testing.html#Integration+Tests

integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ object BloopKeys {
6464
settingKey[File]("Directory where to write bloop configuration files")
6565
val bloopIsMetaBuild: SettingKey[Boolean] =
6666
settingKey[Boolean]("Is this a meta build?")
67+
val bloopExportMetaBuild: SettingKey[Boolean] =
68+
settingKey[Boolean]("Automatically export the sbt meta-build on load (needed by Metals).")
6769
val bloopAggregateSourceDependencies: SettingKey[Boolean] =
6870
settingKey[Boolean]("Flag to tell bloop to aggregate bloop config files in the same bloop dir")
6971
val bloopExportJarClassifiers: SettingKey[Option[Set[String]]] =
@@ -151,6 +153,11 @@ object BloopDefaults {
151153
.map(_.split(",").toSet)
152154
.orElse(Some(Set("sources")))
153155
},
156+
BloopKeys.bloopExportMetaBuild := {
157+
Option(System.getProperty("bloop.export-meta-build"))
158+
.orElse(Option(System.getenv("BLOOP_EXPORT_META_BUILD")))
159+
.contains("true")
160+
},
154161
BloopKeys.bloopInstall := bloopInstall.value,
155162
BloopKeys.bloopAggregateSourceDependencies := true,
156163
// Override classifiers so that we don't resolve always docs
@@ -167,10 +174,11 @@ object BloopDefaults {
167174
},
168175
Keys.onLoad := {
169176
val oldOnLoad = Keys.onLoad.value
177+
val isMetaBuild = BloopKeys.bloopIsMetaBuild.value
178+
val exportMetaBuild = BloopKeys.bloopExportMetaBuild.value
170179
oldOnLoad.andThen { state =>
171-
val isMetaBuild = BloopKeys.bloopIsMetaBuild.value
172-
if (!isMetaBuild) state
173-
else runCommandAndRemaining("bloopInstall")(state)
180+
if (isMetaBuild && exportMetaBuild) runCommandAndRemaining("bloopInstall")(state)
181+
else state
174182
}
175183
},
176184
BloopKeys.bloopSupportedConfigurations := List(
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
val foo = project.in(file("."))
2+
3+
def bloopJsons(dir: File): Seq[File] =
4+
Option(dir.listFiles()).toList.flatten.filter { f =>
5+
f.isFile && f.getName.endsWith(".json") && f.getName != "bloop.settings.json"
6+
}
7+
8+
val metaBloopDir = settingKey[File]("Outer meta-build .bloop dir")
9+
metaBloopDir := (ThisBuild / baseDirectory).value / "project" / ".bloop"
10+
11+
val metaMetaBloopDir = settingKey[File]("Nested meta-build .bloop dir")
12+
metaMetaBloopDir := (ThisBuild / baseDirectory).value / "project" / "project" / ".bloop"
13+
14+
val checkExportsAbsent = taskKey[Unit]("Assert neither meta-build layer was exported")
15+
checkExportsAbsent := {
16+
val meta = bloopJsons(metaBloopDir.value)
17+
val metaMeta = bloopJsons(metaMetaBloopDir.value)
18+
assert(meta.isEmpty, s"Expected no outer meta-build export, found: $meta")
19+
assert(metaMeta.isEmpty, s"Expected no nested meta-build export, found: $metaMeta")
20+
}
21+
22+
val checkExportsPresent = taskKey[Unit]("Assert both meta-build layers were exported")
23+
checkExportsPresent := {
24+
assert(bloopJsons(metaBloopDir.value).nonEmpty, "Expected the outer meta-build to be exported")
25+
assert(
26+
bloopJsons(metaMetaBloopDir.value).nonEmpty,
27+
"Expected the nested meta-build to be exported"
28+
)
29+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Global / bloopExportMetaBuild := true
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % sys.props.apply("plugin.version"))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % sys.props.apply("plugin.version"))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % sys.props.apply("plugin.version"))
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# The meta-build export is opt-in: a default load exports neither meta-build layer.
2+
> checkExportsAbsent
3+
# Opt in at both the outer (project/) and nested (project/project/) layers, reload,
4+
# and both must now export.
5+
$ copy-file changes/export-meta.sbt project/export-meta.sbt
6+
$ copy-file changes/export-meta.sbt project/project/export-meta.sbt
7+
> reload
8+
> checkExportsPresent
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// The meta-build export is opt-in; enable it so this test exercises the export.
2+
Global / bloopExportMetaBuild := true

0 commit comments

Comments
 (0)