floating cat
floating cat

Reputation: 798

How to filter/disable a scalac option for all subprojects in SBT in a DRY way

My project has multiple subprojects, and I use sbt-tpolecat1 in this project. I use a Java framework in my code. This framework use fluent interface heavily so I need to suppress many "discarded non-Unit value" warnings in my code.

This sbt-tpolecat provided a lot of useful scalac options out of the box, and I just want to exclude the -Wvalue-discard scalac option for my use case.

The problem is I have 4-5 subprojects2 in this project. And now I need to add the below to every subproject's settings:

sub_project_name.settings(
  scalacOptions ~= (_.filterNot(Set("-Wvalue-discard")))
)
// or
sub_project_name.settings(valueDiscardSetting)

lazy val valueDiscardSetting =
  Seq(scalacOptions ~= (_.filterNot(Set("-Wvalue-discard"))))

Is there a way to exclude this option in all subprojects in a DRY way? My current subprojects hierarchy is similar to this:

App -> Frontend -> Common
    -> Backend  -> Common

Upvotes: 4

Views: 959

Answers (1)

Mario Galic
Mario Galic

Reputation: 48430

Common settings val

There is a common practice of factoring out common settings in multi-project builds

define a sequence of common settings in a val and add them to each project. Less concepts to learn that way.

for example

lazy val commonSettings = Seq(
  scalacOptions ~= (_.filterNot(Set("-Wvalue-discard"))),
  ...
)

lazy val util = (project in file("util")).settings(commonSettings)
lazy val core = (project in file("core")).settings(commonSettings)

Common settings auto plugin

Auto plugins can set settings for every project. Create the following small plugin under project/CommonSettingsPlugin.scala

object CommonSettingsPlugin extends AutoPlugin {
  override def requires = plugins.JvmPlugin
  override def trigger = allRequirements
  override lazy val projectSettings = Seq(
    scalacOptions ~= (_.filterNot(Set("-Wvalue-discard")))
  )
}

The override

override def requires = plugins.JvmPlugin

should effectively enable the plugin without having to call explicitly enablePlugin in build.sbt.

Override settings with onLoad

onLoad happens at the end after all projects are built and loaded.

lazy val settingsAlreadyOverridden = SettingKey[Boolean]("settingsAlreadyOverridden","Has overrideSettings command already run?")
settingsAlreadyOverridden := false
commands += Command.command("removeScalacOptions") { state =>
  if (settingsAlreadyOverridden.value) {
    state
  } else {
    Project.extract(state).appendWithSession(
      Seq(
        settingsAlreadyOverridden := true,
        scalacOptions ~= (_.filterNot(Set("-Wvalue-discard")))
      ),
      state
    )
  }
}

onLoad in Global := (onLoad in Global).value andThen ("removeScalacOptions" :: _)

Also consider how they addressed the problem in community-build via removeScalacOptions.

Upvotes: 2

Related Questions