Sbt idiomatic way to add settings

I see this in open source sbt projects:

lazy val project = Project( id = "root", base = file("."), settings = Project.defaultSettings ++ Seq( ... ) ) 

We have also adopted this convention for our own projects. However, today I tried sbt-ensime with such a project, and running "gen-ensime" gave me an error:

 [error] (*:update) java.lang.IllegalArgumentException: Cannot add dependency 'org.scala-lang#scala-compiler;2.11.7' to configuration 'ensime-internal' of module ... because this configuration doesn't exist! 

The proposed fix is ​​here: https://github.com/ensime/ensime-sbt/issues/145

He suggests that I change my project to:

 lazy val project = Project( id = "root", base = file(".") ).settings(Seq( ... ) 

My question is: is this proposed way of defining a project idiomatic and preferred for sbt? Am I losing something using this (in particular, the default settings are still added by default)?

+6
source share
2 answers

It seems that the difference between the two

 .settings(Seq(...)) 

adds your sequence to the 'settings' in the project, but

 Project(settings = ...) 

just write settings without saving old values.

Thus, it seems that .settings () is a safer approach.

Generally. settings () is now more idiomatic, because some sbt plugins may try changing the settings when building the project.

A few snippets from sbt sources:

 /** * The explicitly defined sequence of settings that configure this project. * These do not include the automatically appended settings as configured by `auto`. */ def settings: Seq[Setting[_]] /** Appends settings to the current settings sequence for this project. */ def settings(ss: Def.SettingsDefinition*): Project = copy(settings = (settings: Seq[Def.Setting[_]]) ++ Def.settings(ss: _*)) // TODO: Modify default settings to be the core settings, and automatically add the IvyModule + JvmPlugins. def apply(id: String, base: File, aggregate: => Seq[ProjectReference] = Nil, dependencies: => Seq[ClasspathDep[ProjectReference]] = Nil, delegates: => Seq[ProjectReference] = Nil, settings: => Seq[Def.Setting[_]] = Nil, configurations: Seq[Configuration] = Nil, auto: AddSettings = AddSettings.allDefaults): Project = unresolved(id, base, aggregate, dependencies, delegates, settings, configurations, auto, Plugins.empty, Nil) // Note: JvmModule/IvyModule auto included... def copy(id: String = id, base: File = base, aggregate: => Seq[ProjectReference] = aggregate, dependencies: => Seq[ClasspathDep[ProjectReference]] = dependencies, delegates: => Seq[ProjectReference] = delegates, settings: => Seq[Setting[_]] = settings, configurations: Seq[Configuration] = configurations, auto: AddSettings = auto): Project = unresolved(id, base, aggregate = aggregate, dependencies = dependencies, delegates = delegates, settings, configurations, auto, plugins, autoPlugins) 
+3
source

Both approaches have a right to exist. The transfer of settings in the Project(settings = ...) constructor Project(settings = ...) came from the old days when SBT configurations were static. As autoplugin representations, configuration concepts switched to a variable paradigm, and Project().settings(...) compatible with it.

I prefer the first approach, since it is more explicit.


 [error] (*:update) java.lang.IllegalArgumentException: Cannot add dependency 'org.scala-lang#scala-compiler;2.11.7' to configuration 'ensime-internal' of module ... because this configuration doesn't exist! 

The error can be fixed in two ways:

Project level path

You can explicitly add runtime parameters in the project definition.

 import org.ensime.EnsimePlugin lazy val project = Project( id = "root", base = file("."), settings = Project.defaultSettings ++ EnsimePlugin.projectSettings ++ Seq( ... ) ) 

Global level method

Or you can add stagnation parameters to the default project settings at the global level in ~/.sbt/SBT_VERSION/global.sbt

 import org.ensime.EnsimePlugin EnsimePlugin.projectSettings 
+1
source

All Articles