.copy(...)
许多案例类被使用 Contraband 生成的伪案例类替换。将 .copy(foo = xxx)
迁移到 withFoo(xxx)
。假设您有 m: ModuleID
,并且您当前正在调用 m.copy(revision = "1.0.1")
。以下是您可以迁移它的方法
m.withRevision("1.0.1")
sbt 0.13、sbt 1.0 和 sbt 1.1 需要 sbtPlugin
设置和脚本化插件来开发 sbt 插件。sbt 1.2.1 将两者合并为 SbtPlugin
插件。
从 project/plugins.sbt
中删除脚本化插件,只需使用
lazy val root = (project in file("."))
.enablePlugins(SbtPlugin)
如果您要跨构建 sbt 插件,我们提供的一个方法是使用特定于 sbt 版本的源目录 src/main/scala-sbt-0.13
和 src/main/scala-sbt-1.0
。在那里,您可以定义一个名为 PluginCompat
的对象,如下所示
package sbtfoo
import sbt._
import Keys._
object PluginCompat {
type UpdateConfiguration = sbt.librarymanagement.UpdateConfiguration
def subMissingOk(c: UpdateConfiguration, ok: Boolean): UpdateConfiguration =
c.withMissingOk(ok)
}
现在,subMissingOk(...)
函数可以以特定于 sbt 版本的方式实现。
在 sbt 0.13 中,键使用两种不同的语法进行作用域限定:一种用于 sbt 的 shell,另一种用于代码中。
<project-id>/config:intask::key
key in (<project-id>, Config, intask)
从 sbt 1.1.0 开始,对键进行作用域限定的语法已统一为 shell 和构建定义,都使用以下 **斜杠语法**
<project-id> / Config / intask / key
以下是一些示例
version in ThisBuild := "1.0.0-SNAPSHOT"
lazy val root = (project in file("."))
.settings(
name := "hello",
scalacOptions in Compile += "-Xlint",
scalacOptions in (Compile, console) --= Seq("-Ywarn-unused", "-Ywarn-unused-import"),
fork in Test := true
)
现在它们写成
ThisBuild / version := "1.0.0-SNAPSHOT"
lazy val root = (project in file("."))
.settings(
name := "hello",
Compile / scalacOptions += "-Xlint",
Compile / console / scalacOptions --= Seq("-Ywarn-unused", "-Ywarn-unused-import"),
Test / fork := true
)
现在 sbt 的 shell 中也使用相同的语法
sbt:hello> name
[info] hello
sbt:hello> ThisBuild / version
[info] 1.0.0-SNAPSHOT
sbt:hello> show Compile / scalacOptions
[info] * -Xlint
sbt:hello> show Compile / console / scalacOptions
[info] * -Xlint
sbt:hello> Test / fork
[info] true
有一个 用于统一斜杠语法的语法 Scalafix 规则,可以半自动地将现有的 sbt 0.13 语法重写为斜杠语法。目前,它需要使用 scalafix CLI,而且不是很精确(因为它是一个只查看代码形状的语法规则),但它完成了大部分工作。
$ scalafix --rules=https://gist.githubusercontent.com/eed3si9n/57e83f5330592d968ce49f0d5030d4d5/raw/7f576f16a90e432baa49911c9a66204c354947bb/Sbt0_13BuildSyntax.scala *.sbt project/*.scala
在 sbt 0.13 之前(sbt 0.9 到 0.12),在构建中经常看到 sbt 的三个方面的用法
<<=
、<+=
、<++=
(foo, bar) map { (f, b) => ... }
)project/Build.scala
中使用 Build
特性sbt 0.13 的发布(已经超过 3 年了!)引入了 .value
DSL,它允许更易于阅读和编写代码,有效地使前两个方面变得多余,并且它们已从官方文档中删除。
类似地,sbt 0.13 引入的多项目 build.sbt
使 Build
特性变得多余。此外,sbt 0.13 中现在标准的自动插件功能启用了插件设置的自动排序和自动导入功能,但它使 Build.scala
更难维护。
由于它们已在 sbt 1.0.0 中删除,因此我们将在此为您提供如何迁移代码的指导。
对于诸如以下简单的表达式
a <<= aTaskDef
b <+= bTaskDef
c <++= cTaskDefs
只需将它们替换为等效的
a := aTaskDef.value
b += bTaskDef.value
c ++= cTaskDefs.value
如上所述,有两个元组增强 .apply
和 .map
。区别在于您是为 SettingKey
还是 TaskKey
定义设置,您对前者使用 .apply
,对后者使用 .map
val sett1 = settingKey[String]("SettingKey 1")
val sett2 = settingKey[String]("SettingKey 2")
val sett3 = settingKey[String]("SettingKey 3")
val task1 = taskKey[String]("TaskKey 1")
val task2 = taskKey[String]("TaskKey 2")
val task3 = taskKey[String]("TaskKey 3")
val task4 = taskKey[String]("TaskKey 4")
sett1 := "s1"
sett2 := "s2"
sett3 <<= (sett1, sett2)(_ + _)
task1 := { println("t1"); "t1" }
task2 := { println("t2"); "t2" }
task3 <<= (task1, task2) map { (t1, t2) => println(t1 + t2); t1 + t2 }
task4 <<= (sett1, sett2) map { (s1, s2) => println(s1 + s2); s1 + s2 }
(请记住,您可以根据设置定义任务,但反之则不行)
使用 .value
DSL,您无需知道或记住您的键是 SettingKey
还是 TaskKey
sett1 := "s1"
sett2 := "s2"
sett3 := sett1.value + sett2.value
task1 := { println("t1"); "t1" }
task2 := { println("t2"); "t2" }
task3 := { println(task1.value + task2.value); task1.value + task2.value }
task4 := { println(sett1.value + sett2.value); sett1.value + sett2.value }
.dependsOn
、.triggeredBy
或 .runBefore
时的迁移 当调用 .dependsOn
时,而不是
a <<= a dependsOn b
将其定义为
a := (a dependsOn b).value
**注意**:在 sbt 0.13.13 及更早版本中,由于问题 #1444,您需要在 .triggeredBy
和 .runBefore
中使用 <<=
运算符。
Task
的情况 对于使用 sbt 的 Task 类型的键,例如 sourceGenerators
和 resourceGenerators
val sourceGenerators =
settingKey[Seq[Task[Seq[File]]]]("List of tasks that generate sources")
val resourceGenerators =
settingKey[Seq[Task[Seq[File]]]]("List of tasks that generate resources")
以前您将它们定义为
sourceGenerators in Compile <+= buildInfo
对于 sbt 1,您将它们定义为
Compile / sourceGenerators += buildInfo
或一般来说,
Compile / sourceGenerators += Def.task { List(file1, file2) }
InputKey
的迁移 使用 InputKey
时,而不是
run <<= docsRunSetting
在迁移时,您不能使用 .value
,而要使用 .evaluated
run := docsRunSetting.evaluated
对于基于 Build 特性的构建,例如
import sbt._
import Keys._
import xyz.XyzPlugin.autoImport._
object HelloBuild extends Build {
val shared = Defaults.defaultSettings ++ xyz.XyzPlugin.projectSettings ++ Seq(
organization := "com.example",
version := "0.1.0",
scalaVersion := "2.12.18")
lazy val hello =
Project("Hello", file("."),
settings = shared ++ Seq(
xyzSkipWrite := true)
).aggregate(core)
lazy val core =
Project("hello-core", file("core"),
settings = shared ++ Seq(
description := "Core interfaces",
libraryDependencies ++= scalaXml.value)
)
def scalaXml = Def.setting {
scalaBinaryVersion.value match {
case "2.10" => Nil
case _ => ("org.scala-lang.modules" %% "scala-xml" % "1.0.6") :: Nil
}
}
}
您可以迁移到 build.sbt
val shared = Seq(
organization := "com.example",
version := "0.1.0",
scalaVersion := "2.12.18"
)
lazy val helloRoot = (project in file("."))
.aggregate(core)
.enablePlugins(XyzPlugin)
.settings(
shared,
name := "Hello",
xyzSkipWrite := true
)
lazy val core = (project in file("core"))
.enablePlugins(XyzPlugin)
.settings(
shared,
name := "hello-core",
description := "Core interfaces",
libraryDependencies ++= scalaXml.value
)
def scalaXml = Def.setting {
scalaBinaryVersion.value match {
case "2.10" => Nil
case _ => ("org.scala-lang.modules" %% "scala-xml" % "1.0.6") :: Nil
}
}
project/Build.scala
重命名为 build.sbt
。import sbt._
、import Keys._
和任何自动导入。shared
、helloRoot
等)移出 object HelloBuild
,并删除 HelloBuild
。Project(...)
更改为 (project in file("x"))
风格,并调用其 settings(...)
方法传递设置。这样,自动插件就可以根据插件依赖项重新排序其设置顺序。name
设置应设置为保留旧名称。shared
中删除 Defaults.defaultSettings
,因为这些设置已由内置自动插件设置,也从 shared
中删除 xyz.XyzPlugin.projectSettings
,并改为调用 enablePlugins(XyzPlugin)
。**注意**:Build
特性已弃用,但您仍然可以使用 project/*.scala
文件来组织构建和/或定义临时插件。请参阅 组织构建。
在 0.13.x 中,您使用其他仓库而不是 Maven Central 仓库
externalResolvers := Resolver.withDefaultResolvers(resolvers.value, mavenCentral = false)
在 1.x 之后,withDefaultResolvers
被重命名为 combineDefaultResolvers
。与此同时,其中一个参数 userResolvers
变成了 Vector
,而不是 Seq
。
您可以使用 toVector
来帮助迁移。
externalResolvers := Resolver.combineDefaultResolvers(resolvers.value.toVector, mavenCentral = false)
Vector
。