首页 > 解决方案 > 如何以 DRY 方式过滤/禁用 SBT 中所有子项目的 scalac 选项

问题描述

我的项目有多个子项目,我在这个项目中使用了sbt-tpolecat1个。我在我的代码中使用了 Java 框架。这个框架大量使用流畅的接口,所以我需要在我的代码中抑制许多“丢弃的非单位值”警告。

sbt-tpolecat提供了许多开箱即用的有用 scalac 选项,我只想-Wvalue-discard为我的用例排除 scalac 选项。

问题是我在这个项目中有 4-5 个子项目2 。现在我需要将以下内容添加到每个子项目的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"))))

有没有办法以 DRY 方式在所有子项目中排除此选项?我当前的子项目层次结构类似于:

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

标签: scalasbt

解决方案


常用设置值

在多项目构建中分解出通用设置是一种常见做法

在 val 中定义一系列常用设置并将它们添加到每个项目中。以这种方式学习的概念更少。

例如

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)

常用设置自动插件

自动插件可以为每个项目设置设置。在下创建如下小插件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")))
  )
}

覆盖

override def requires = plugins.JvmPlugin

应该有效地启用插件,而无需显式enablePlugin调用build.sbt.

覆盖设置onLoad

onLoad在所有项目都构建和加载后发生在最后。

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" :: _)

还要考虑他们如何通过removeScalacOptions.


推荐阅读