В процессе разработки часто есть две отдельные фазы: «грязная разработка», когда разработчики работают над решениями, тестируют различные концепции и вводят временные структуры кода, и фаза «очистки» для уточнения кода перед отправкой окончательной версии или тянуть запрос. Во время грязной разработки часто возникают недостатки, такие как избыточный или мертвый код и неиспользуемый импорт, отсутствующие явные типы и т. д. В этом контексте полезно, чтобы код компилировался, даже если во время разработки появляются предупреждения.
Как я могу настроить SBT для использования различных scalacOptions для этих разных этапов кодирования?
Предположим, что для этапа «грязной разработки» я хотел бы использовать пустые scalacOptions, но при окончательной очистке они могут выглядеть так:
val scalaCompilerOptions = Seq(
"-Xfatal-warnings",
"-Xlint:-missing-interpolator,_",
"-Xlint:adapted-args",
"-Xlint:constant",
"-Xlint:-byname-implicit",
"-Ywarn-unused:imports",
"-Ywarn-unused:patvars",
"-Ywarn-unused:privates",
"-Ywarn-unused:locals",
"-Ywarn-unused:explicits",
"-Ywarn-unused:params",
"-Ywarn-unused:implicits",
"-Ywarn-value-discard",
"-Ywarn-dead-code",
"-deprecation",
"-feature",
"-unchecked",
...
)
В идеале, при входе в задачу test:compile он должен использовать пустой scalacOptions, но при использовании test (или package или distTgz) будут применяться ограничительные параметры.
sbt.версия=1.7.2





В sbt вы можете создавать разные подмодули с разными конфигурациями.
Приложение
// the application
lazy val app = project
.in(file("."))
.settings(
name := "my-app",
libraryDependencies += (
dependency1,
dependency2,
// ...
dependencyN,
)
)
а затем разные подмодули с разными конфигурациями
lazy val testPackage = project
// we put the results in a build folder
.in(file("build/test"))
.settings(
scalacOptions in Compile := Seq(
// options for test
),
// override the resource directory
resourceDirectory in Compile := (resourceDirectory in (app, Compile)).value,
mappings in Universal += {
((resourceDirectory in Compile).value / "test.conf") -> "conf/application.conf"
}
)
.dependsOn(app)
// bascially identical despite the configuration differences
lazy val stagePackage = project
.in(file("build/stage"))
.settings(
scalacOptions in Compile := Seq(
// options for stage
),
resourceDirectory in Compile := (resourceDirectory in (app, Compile)).value,
mappings in Universal += {
((resourceDirectory in Compile).value / "stage.conf") -> "conf/application.conf"
}
)
.dependsOn(app)
lazy val prodPackage = project
.in(file("build/prod"))
.settings(
scalacOptions in Compile := Seq(
// options for prod
),
resourceDirectory in Compile := (resourceDirectory in (app, Compile)).value,
mappings in Universal += {
((resourceDirectory in Compile).value / "prod.conf") -> "conf/application.conf"
}
)
.dependsOn(app)
В плагине sbt-native-packager есть хороший пример того, как это сделать.
Один из способов (не единственный) — создать собственную настройку, а затем scalacOptions зависеть от этой настройки. Затем вы можете изменить настройку в любое время с помощью set.
Например, в сборке sbt для компилятора Scala 2 (https://github.com/scala/scala) мы хотим отключить фатальные предупреждения при локальной разработке, но включить в CI.
Итак, наш build.sbt имеет:
val fatalWarnings = settingKey[Boolean](
"are compiler warnings fatal")
Global / fatalWarnings := insideCI.value
// then in whatever context is appropriate in your build,
Compile / scalacOptions ++= {
if (fatalWarnings.value) Seq("-Werror")
else Nil
}
Затем локально, когда мы хотим временно включить фатальные предупреждения, set Global / fatalWarnings := true.
Мне это кажется немного более легким решением, чем предложение Гастона.
Для справки, sbt-tpolecat имеет встроенную функциональность.