Reputation: 2826
I want to group settings by the context in which they apply in my build.sbt. Instead of
foo in ThisBuild := bar
baz in ThisBuild := bar
bar in Compile := 5
quux in Compile := 7
I'd like something that roughly looks like (don't care much about the specific syntax/API, just the conceptual grouping and lack of repetition)
in(ThisBuild) {
foo := bar
baz := bar
}
in(Compile) {
bar := 5
quux := 7
}
Is such a thing possible/clean/idiomatic?
Upvotes: 3
Views: 600
Reputation: 95624
As a supplement to Jacek's answer, I'd encourage you to see sbt 0.13.5's JvmPlugin.scala and Defaults.scala. JvmPlugin
is an auto plugin that's enabled by default and adds basic JVM tasks like compile:compile
and test:test
.
For instance, Defaults.defaultConfigs
adds both compile:compile
and test:test
as follows:
lazy val defaultConfigs: Seq[Setting[_]] =
inConfig(Compile)(compileSettings) ++
inConfig(Test)(testSettings) ++
inConfig(Runtime)(Classpaths.configSettings)
As Jacek noted, the expected type on the passed in settings are all Seq[Def.Setting[_]]
. Like
lazy val testSettings: Seq[Setting[_]] = configSettings ++ testTasks
These sequences can be constructed by appending reused sequences that are scoped in different ways as testTasks:
lazy val testTasks: Seq[Setting[_]] =
testTaskOptions(test) ++
testTaskOptions(testOnly) ++
testTaskOptions(testQuick) ++
testDefaults ++ Seq(
....
test := {
val trl = (testResultLogger in (Test, test)).value
val taskName = Project.showContextKey(state.value)(resolvedScoped.value)
trl.run(streams.value.log, executeTests.value, taskName)
},
testOnly <<= inputTests(testOnly),
testQuick <<= inputTests(testQuick)
)
If you're using multi-project build.sbt, the project scoping would be done by passing the settings to project's settings method.
lazy val root = (project in file("."))
lazy val foo = project.
settings(yourSettings: _*).
settings(someOtherSettings: _*)
lazy val bar = project.
settings(yourSettings: _*).
settings(someOtherSettings: _*)
You can define def yourSettings
in build.sbt
(or project/foo.scala
). When you start to find passing settings explicitly to be tedious, you can define an autoplugin similar to sbt's JvmPlugin
. This would let you write:
lazy val root = (project in file("."))
lazy val foo = project.
enablePlugins(FooPlugin, BarPlugin)
lazy val bar = project.
enablePlugins(FooPlugin, BarPlugin)
Edit:
If you make FooPlugin
and BarPlugin
triggered out of thin air, you could write:
lazy val root = (project in file("."))
lazy val foo, bar = project
See Plugins for the details.
I want to clarify that you can chose the degree of magic/automation when it comes to auto plugins. In the above, both FooPlugin
and BarPlugin
are triggered out of nothing, but you could easily make BarPlugin
triggered by FooPlugin
or not triggered at all. This is meant to automate things like "use coffeescript plugin for all web-related projects". I hope I'm still on-topic with your question "I want to group settings by the context."
Upvotes: 2
Reputation: 74679
For Compile
configuration use inConfig
as follows:
inConfig(Compile) {
Seq(
bar := 5,
quux := 7
)
}
For ThisBuild
scope use inScope
as follows:
inScope(ThisScope.copy(project=Select(ThisBuild))) {
Seq(
foo := bar,
baz := bar
)
}
Note that all the in*
methods work for Seq
s.
Note also that since they appear in build.sbt
file they're automatically scoped to the project the build definition belongs to. Obviously, in ThisBuild
settings belong to the build.
As to the idiomatic nature of using the in*
methods in *.sbt
files, I have never seen them in the files. Since they're pretty new (since sbt 0.13) people could be yet to catch up with their use.
The trait ProjectExtra
offers inConfig
, inTask
and inScope
methods. As @copumpkin pointed out in the comment there's no inProject
method that would complement the others. I've no idea why, but with inScope
it is not necessary and neither are the inConfig
and inTask
since they pretty much map a scope to a config or a task with the other axes unchanged.
For reference, this is the definition of Scope
:
final case class Scope(project: ScopeAxis[Reference], config: ScopeAxis[ConfigKey], task: ScopeAxis[AttributeKey[_]], extra: ScopeAxis[AttributeMap])
Upvotes: 3