Search code examples
scalasbt

How to apply different scalacOptions in SBT for specific development phases?


During the development process, there are often two distinct phases: "dirty development," where developers work on solutions, test various concepts, and introduce temporary code structures, and a "cleanup" phase to refine the code before submitting a final version or a pull request. During dirty development, it is common to have imperfections such as redundant or dead code and unused imports, missing explicit types, etc. In this context, it is beneficial for the code to compile even when there are warnings during development.

How can I configure SBT to use various scalacOptions for those different phases of coding?

Let's assume that for the "dirty development" phase, I'd like to use empty scalacOptions, but when doing final cleanup, those could look like:

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",
...
)

Ideally, when entering test:compile task, it would use empty scalacOptions, but when using test (or package or distTgz), it would apply the restrictive options.

sbt.version=1.7.2


Solution

  • One way (not the only way) is to make your own setting and then have scalacOptions depend on that setting. Then you can change the setting anytime with set.

    For example, in the sbt build for the Scala 2 compiler (https://github.com/scala/scala), we want to have fatal warnings disabled during local development, but enabled in CI.

    So our build.sbt has:

    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
    }
    

    Then locally when we want to temporarily enable fatal warnings, set Global / fatalWarnings := true.

    This seems like a bit lighter-weight solution to me than Gastón's suggestion.