Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I change the compiler flags of an sbt project without causing recompilation?

Tags:

scala

sbt

It often comes up during testing and debugging a Scala project built with sbt that I need to pass some extra compiler flags for a particular file. For example -Xlog-implicits to debug implicit resolution problems. However, changing scalacOptions either in build.sbt or the console invalidates the cache and causes the whole project / test suite to be recompiled. In addition to being annoying to wait so long, this also means that a lot of noise from irrelevant files is printed. Instead it would be better if I could compile a specific file with some extra flags from the sbt console, but I did not find a way to do this.

like image 815
g.krastev Avatar asked Oct 26 '25 14:10

g.krastev


1 Answers

Problem

The reason why changing the scalac options triggers recompilation is because Zinc, Scala's incremental compiler, cannot possibly now which compiler flags affect the semantics of the incremental compilation, so it's pessimistic about it. I believe this can be improved, and some whitelisted flags can be supported, so that next time people like you don't have to ask about it.

Nevertheless, there's a solution to this problem and it's more generic than it looks like at first sight.

Solution

You can create a subproject in your sbt build which is a copy of the project you want to "log implicits" in, but with -Xlog-implicits enabled by default.

// Let's say foo is your project definition
lazy val foo = project.settings(???)

// You define the copy of your project like this
lazy val foo-implicits = foo
  .copy(id = "foo-implicits")
  .settings(
    target := baseDirectory.value./("another-target"),
    scalacOptions += "-Xlog-implicits"
  )

Note the following properties of this code snippet:

  1. We redefine the project ID because when we reuse a project definition the ID is still the same as the previous one (foo in this case). Sbt fails when there are projects that share the same id.
  2. We redefine the target directory because we want to avoid recompilation. If we keep the same as before, then recompiling foo-implicits will delete the compilation products of the previous compilation (and viceversa). That's exactly what we want to avoid.
  3. We add -Xlog-implicits to the Scalac options as you request in this question. In a generic solution, this piece of code should go away.

When is this useful?

This is useful not only for your use case, but when you want to have different modules of the same project in different Scala versions. The following has two benefits:

  1. You don't use cross-compilation in sbt ++, which is known to have some memory issues.
  2. You can add new library dependencies that only exist for a concrete Scala version.

It has more applications, but I hope this addresses your question.

like image 76
Jorge Vicente Cantero Avatar answered Oct 29 '25 08:10

Jorge Vicente Cantero



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!