4

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
floating cat
  • 678
  • 7
  • 11

1 Answers1

2

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.

Mario Galic
  • 47,285
  • 6
  • 56
  • 98