本页假定您已安装 sbt 1。
让我们从示例开始,而不是解释 sbt 的工作原理或原因。
$ mkdir foo-build
$ cd foo-build
$ touch build.sbt
$ sbt
[info] Updated file /tmp/foo-build/project/build.properties: set sbt.version to 1.9.3
[info] welcome to sbt 1.9.3 (Eclipse Adoptium Java 17.0.8)
[info] Loading project definition from /tmp/foo-build/project
[info] loading settings for project foo-build from build.sbt ...
[info] Set current project to foo-build (in build file:/tmp/foo-build/)
[info] sbt server started at local:///Users/eed3si9n/.sbt/1.0/server/abc4fb6c89985a00fd95/sock
[info] started sbt server
sbt:foo-build>
要退出 sbt shell,请键入 exit
或使用 Ctrl+D(Unix)或 Ctrl+Z(Windows)。
sbt:foo-build> exit
按照惯例,我们将使用 sbt:...>
或 >
提示符来表示我们位于 sbt 交互式 shell 中。
$ sbt
sbt:foo-build> compile
在 compile
命令(或任何其他命令)前面添加 ~
会导致该命令在项目中的某个源文件修改时自动重新执行。例如
sbt:foo-build> ~compile
[success] Total time: 0 s, completed 28 Jul 2023, 13:32:35
[info] 1. Monitoring source files for foo-build/compile...
[info] Press <enter> to interrupt or '?' for more options.
让之前的命令继续运行。从另一个 shell 或在您的文件管理器中,在 foo-build 目录中创建以下嵌套目录:src/main/scala/example
。然后,使用您喜欢的编辑器在 example
目录中创建 Hello.scala
,如下所示
package example
object Hello {
def main(args: Array[String]): Unit = {
println("Hello")
}
}
这个新文件应该会被正在运行的命令拾取
[info] Build triggered by /tmp/foo-build/src/main/scala/example/Hello.scala. Running 'compile'.
[info] compiling 1 Scala source to /tmp/foo-build/target/scala-2.12/classes ...
[success] Total time: 0 s, completed 28 Jul 2023, 13:38:55
[info] 2. Monitoring source files for foo-build/compile...
[info] Press <enter> to interrupt or '?' for more options.
按 Enter
退出 ~compile
。
在 sbt shell 中,按两次向上箭头以找到您在开头执行的 compile
命令。
sbt:foo-build> compile
使用 help
命令获取有关可用命令的基本帮助。
sbt:foo-build> help
<command> (; <command>)* Runs the provided semicolon-separated commands.
about Displays basic information about sbt and the build.
tasks Lists the tasks defined for the current project.
settings Lists the settings defined for the current project.
reload (Re)loads the current project or changes to plugins project or returns from it.
new Creates a new sbt build.
new Creates a new sbt build.
projects Lists the names of available projects or temporarily adds/removes extra builds to the session.
....
显示特定任务的描述
sbt:foo-build> help run
Runs a main class, passing along arguments provided on the command line.
sbt:foo-build> run
[info] running example.Hello
Hello
[success] Total time: 0 s, completed 28 Jul 2023, 13:40:31
sbt:foo-build> set ThisBuild / scalaVersion := "2.13.12"
[info] Defining ThisBuild / scalaVersion
[info] The new value will be used by Compile / bspBuildTarget, Compile / dependencyTreeCrossProjectId and 50 others.
[info] Run `last` for details.
[info] Reapplying settings...
[info] set current project to foo-build (in build file:/tmp/foo-build/)
检查 scalaVersion
设置
sbt:foo-build> scalaVersion
[info] 2.13.12
我们可以使用 session save
保存临时设置。
sbt:foo-build> session save
[info] Reapplying settings...
[info] set current project to foo-build (in build file:/tmp/foo-build/)
[warn] build source files have changed
[warn] modified files:
[warn] /tmp/foo-build/build.sbt
[warn] Apply these changes by running `reload`.
[warn] Automatically reload the build when source changes are detected by setting `Global / onChangedBuildSource := ReloadOnSourceChanges`.
[warn] Disable this warning by setting `Global / onChangedBuildSource := IgnoreSourceChanges`.
build.sbt
文件现在应该包含
ThisBuild / scalaVersion := "2.13.12"
使用编辑器,将 build.sbt
更改为以下内容
ThisBuild / scalaVersion := "2.13.12"
ThisBuild / organization := "com.example"
lazy val hello = (project in file("."))
.settings(
name := "Hello"
)
使用 reload
命令重新加载构建。该命令会导致 build.sbt
文件被重新读取,并应用其设置。
sbt:foo-build> reload
[info] welcome to sbt 1.9.3 (Eclipse Adoptium Java 17.0.8)
[info] loading project definition from /tmp/foo-build/project
[info] loading settings for project hello from build.sbt ...
[info] set current project to Hello (in build file:/tmp/foo-build/)
sbt:Hello>
请注意,提示符现在已更改为 sbt:Hello>
。
使用编辑器,将 build.sbt
更改为以下内容
ThisBuild / scalaVersion := "2.13.12"
ThisBuild / organization := "com.example"
lazy val hello = project
.in(file("."))
.settings(
name := "Hello",
libraryDependencies += "org.scala-lang" %% "toolkit-test" % "0.1.7" % Test
)
使用 reload
命令来反映 build.sbt
中的更改。
sbt:Hello> reload
sbt:Hello> test
sbt:Hello> ~testQuick
让之前的命令继续运行,使用编辑器创建一个名为 src/test/scala/example/HelloSuite.scala
的文件
class HelloSuite extends munit.FunSuite {
test("Hello should start with H") {
assert("hello".startsWith("H"))
}
}
~testQuick
应该会拾取更改
[info] 2. Monitoring source files for hello/testQuick...
[info] Press <enter> to interrupt or '?' for more options.
[info] Build triggered by /tmp/foo-build/src/test/scala/example/HelloSuite.scala. Running 'testQuick'.
[info] compiling 1 Scala source to /tmp/foo-build/target/scala-2.13/test-classes ...
HelloSuite:
==> X HelloSuite.Hello should start with H 0.004s munit.FailException: /tmp/foo-build/src/test/scala/example/HelloSuite.scala:4 assertion failed
3: test("Hello should start with H") {
4: assert("hello".startsWith("H"))
5: }
at munit.FunSuite.assert(FunSuite.scala:11)
at HelloSuite.$anonfun$new$1(HelloSuite.scala:4)
[error] Failed: Total 1, Failed 1, Errors 0, Passed 0
[error] Failed tests:
[error] HelloSuite
[error] (Test / testQuick) sbt.TestsFailedException: Tests unsuccessful
使用编辑器,将 src/test/scala/example/HelloSuite.scala
更改为
class HelloSuite extends munit.FunSuite {
test("Hello should start with H") {
assert("Hello".startsWith("H"))
}
}
确认测试通过,然后按 Enter
退出连续测试。
使用编辑器,将 build.sbt
更改为以下内容
ThisBuild / scalaVersion := "2.13.12"
ThisBuild / organization := "com.example"
lazy val hello = project
.in(file("."))
.settings(
name := "Hello",
libraryDependencies ++= Seq(
"org.scala-lang" %% "toolkit" % "0.1.7",
"org.scala-lang" %% "toolkit-test" % "0.1.7" % Test
)
)
使用 reload
命令来反映 build.sbt
中的更改。
我们可以查明纽约当前的天气。
sbt:Hello> console
[info] Starting scala interpreter...
Welcome to Scala 2.13.12 (OpenJDK 64-Bit Server VM, Java 17).
Type in expressions for evaluation. Or try :help.
scala> :paste
// Entering paste mode (ctrl-D to finish)
import sttp.client4.quick._
import sttp.client4.Response
val newYorkLatitude: Double = 40.7143
val newYorkLongitude: Double = -74.006
val response: Response[String] = quickRequest
.get(
uri"https://api.open-meteo.com/v1/forecast?latitude=$newYorkLatitude&longitude=$newYorkLongitude¤t_weather=true"
)
.send()
println(ujson.read(response.body).render(indent = 2))
// press Ctrl+D
// Exiting paste mode, now interpreting.
{
"latitude": 40.710335,
"longitude": -73.99307,
"generationtime_ms": 0.36704540252685547,
"utc_offset_seconds": 0,
"timezone": "GMT",
"timezone_abbreviation": "GMT",
"elevation": 51,
"current_weather": {
"temperature": 21.3,
"windspeed": 16.7,
"winddirection": 205,
"weathercode": 3,
"is_day": 1,
"time": "2023-08-04T10:00"
}
}
import sttp.client4.quick._
import sttp.client4.Response
val newYorkLatitude: Double = 40.7143
val newYorkLongitude: Double = -74.006
val response: sttp.client4.Response[String] = Response({"latitude":40.710335,"longitude":-73.99307,"generationtime_ms":0.36704540252685547,"utc_offset_seconds":0,"timezone":"GMT","timezone_abbreviation":"GMT","elevation":51.0,"current_weather":{"temperature":21.3,"windspeed":16.7,"winddirection":205.0,"weathercode":3,"is_day":1,"time":"2023-08-04T10:00"}},200,,List(:status: 200, content-encoding: deflate, content-type: application/json; charset=utf-8, date: Fri, 04 Aug 2023 10:09:11 GMT),List(),RequestMetadata(GET,https://api.open-meteo.com/v1/forecast?latitude=40.7143&longitude...
scala> :q // to quit
将 build.sbt
更改为以下内容
ThisBuild / scalaVersion := "2.13.12"
ThisBuild / organization := "com.example"
lazy val hello = project
.in(file("."))
.settings(
name := "Hello",
libraryDependencies ++= Seq(
"org.scala-lang" %% "toolkit" % "0.1.7",
"org.scala-lang" %% "toolkit-test" % "0.1.7" % Test
)
)
lazy val helloCore = project
.in(file("core"))
.settings(
name := "Hello Core"
)
使用 reload
命令来反映 build.sbt
中的更改。
sbt:Hello> projects
[info] In file:/tmp/foo-build/
[info] * hello
[info] helloCore
sbt:Hello> helloCore/compile
将 build.sbt
更改为以下内容
ThisBuild / scalaVersion := "2.13.12"
ThisBuild / organization := "com.example"
val toolkitTest = "org.scala-lang" %% "toolkit-test" % "0.1.7"
lazy val hello = project
.in(file("."))
.settings(
name := "Hello",
libraryDependencies ++= Seq(
"org.scala-lang" %% "toolkit" % "0.1.7",
toolkitTest % Test
)
)
lazy val helloCore = project
.in(file("core"))
.settings(
name := "Hello Core",
libraryDependencies += toolkitTest % Test
)
设置 aggregate,以便发送到 hello
的命令也会广播到 helloCore
ThisBuild / scalaVersion := "2.13.12"
ThisBuild / organization := "com.example"
val toolkitTest = "org.scala-lang" %% "toolkit-test" % "0.1.7"
lazy val hello = project
.in(file("."))
.aggregate(helloCore)
.settings(
name := "Hello",
libraryDependencies ++= Seq(
"org.scala-lang" %% "toolkit" % "0.1.7",
toolkitTest % Test
)
)
lazy val helloCore = project
.in(file("core"))
.settings(
name := "Hello Core",
libraryDependencies += toolkitTest % Test
)
在 reload
之后,~testQuick
现在将在两个子项目上运行
sbt:Hello> ~testQuick
按 Enter
退出连续测试。
使用 .dependsOn(...)
添加对其他子项目的依赖。另外,让我们将 toolkit 依赖项移到 helloCore
。
ThisBuild / scalaVersion := "2.13.12"
ThisBuild / organization := "com.example"
val toolkitTest = "org.scala-lang" %% "toolkit-test" % "0.1.7"
lazy val hello = project
.in(file("."))
.aggregate(helloCore)
.dependsOn(helloCore)
.settings(
name := "Hello",
libraryDependencies += toolkitTest % Test
)
lazy val helloCore = project
.in(file("core"))
.settings(
name := "Hello Core",
libraryDependencies += "org.scala-lang" %% "toolkit" % "0.1.7",
libraryDependencies += toolkitTest % Test
)
让我们在 helloCore
中使用 toolkit 中的 uJson。
ThisBuild / scalaVersion := "2.13.12"
ThisBuild / organization := "com.example"
val toolkitTest = "org.scala-lang" %% "toolkit-test" % "0.1.7"
lazy val hello = project
.in(file("."))
.aggregate(helloCore)
.dependsOn(helloCore)
.settings(
name := "Hello",
libraryDependencies += toolkitTest % Test
)
lazy val helloCore = project
.in(file("core"))
.settings(
name := "Hello Core",
libraryDependencies += "org.scala-lang" %% "toolkit" % "0.1.7",
libraryDependencies += toolkitTest % Test
)
在 reload
之后,添加 core/src/main/scala/example/core/Weather.scala
package example.core
import sttp.client4.quick._
import sttp.client4.Response
object Weather {
def temp() = {
val response: Response[String] = quickRequest
.get(
uri"https://api.open-meteo.com/v1/forecast?latitude=40.7143&longitude=-74.006¤t_weather=true"
)
.send()
val json = ujson.read(response.body)
json.obj("current_weather")("temperature").num
}
}
接下来,将 src/main/scala/example/Hello.scala
更改为以下内容
package example
import example.core.Weather
object Hello {
def main(args: Array[String]): Unit = {
val temp = Weather.temp()
println(s"Hello! The current temperature in New York is $temp C.")
}
}
让我们运行该应用程序以查看它是否有效
sbt:Hello> run
[info] compiling 1 Scala source to /tmp/foo-build/core/target/scala-2.13/classes ...
[info] compiling 1 Scala source to /tmp/foo-build/target/scala-2.13/classes ...
[info] running example.Hello
Hello! The current temperature in New York is 22.7 C.
使用编辑器,创建 project/plugins.sbt
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.9.4")
接下来,将 build.sbt
更改为以下内容以添加 JavaAppPackaging
ThisBuild / scalaVersion := "2.13.12"
ThisBuild / organization := "com.example"
val toolkitTest = "org.scala-lang" %% "toolkit-test" % "0.1.7"
lazy val hello = project
.in(file("."))
.aggregate(helloCore)
.dependsOn(helloCore)
.enablePlugins(JavaAppPackaging)
.settings(
name := "Hello",
libraryDependencies += toolkitTest % Test,
maintainer := "A Scala Dev!"
)
lazy val helloCore = project
.in(file("core"))
.settings(
name := "Hello Core",
libraryDependencies += "org.scala-lang" %% "toolkit" % "0.1.7",
libraryDependencies += toolkitTest % Test
)
sbt:Hello> reload
...
sbt:Hello> dist
[info] Wrote /private/tmp/foo-build/target/scala-2.13/hello_2.13-0.1.0-SNAPSHOT.pom
[info] Main Scala API documentation to /tmp/foo-build/target/scala-2.13/api...
[info] Main Scala API documentation successful.
[info] Main Scala API documentation to /tmp/foo-build/core/target/scala-2.13/api...
[info] Wrote /tmp/foo-build/core/target/scala-2.13/hello-core_2.13-0.1.0-SNAPSHOT.pom
[info] Main Scala API documentation successful.
[success] All package validations passed
[info] Your package is ready in /tmp/foo-build/target/universal/hello-0.1.0-SNAPSHOT.zip
以下是如何运行打包的应用程序
$ /tmp/someother
$ cd /tmp/someother
$ unzip -o -d /tmp/someother /tmp/foo-build/target/universal/hello-0.1.0-SNAPSHOT.zip
$ ./hello-0.1.0-SNAPSHOT/bin/hello
Hello! The current temperature in New York is 22.7 C.
请注意,为了使此操作正常工作,需要运行 Docker 守护程序。
sbt:Hello> Docker/publishLocal
....
[info] Built image hello with tags [0.1.0-SNAPSHOT]
以下是如何运行容器化的应用程序
$ docker run hello:0.1.0-SNAPSHOT
Hello! The current temperature in New York is 22.7 C.
将 build.sbt
更改为以下内容
ThisBuild / version := "0.1.0"
ThisBuild / scalaVersion := "2.13.12"
ThisBuild / organization := "com.example"
val toolkitTest = "org.scala-lang" %% "toolkit-test" % "0.1.7"
lazy val hello = project
.in(file("."))
.aggregate(helloCore)
.dependsOn(helloCore)
.enablePlugins(JavaAppPackaging)
.settings(
name := "Hello",
libraryDependencies += toolkitTest % Test,
maintainer := "A Scala Dev!"
)
lazy val helloCore = project
.in(file("core"))
.settings(
name := "Hello Core",
libraryDependencies += "org.scala-lang" %% "toolkit" % "0.1.7",
libraryDependencies += toolkitTest % Test
)
sbt:Hello> ++3.3.1!
[info] Forcing Scala version to 3.3.1 on all projects.
[info] Reapplying settings...
[info] Set current project to Hello (in build file:/tmp/foo-build/)
检查 scalaVersion
设置
sbt:Hello> scalaVersion
[info] helloCore / scalaVersion
[info] 3.3.1
[info] scalaVersion
[info] 3.3.1
此设置将在 reload
之后消失。
要详细了解 dist
,请尝试 help
和 inspect
。
sbt:Hello> help dist
Creates the distribution packages.
sbt:Hello> inspect dist
要在依赖项任务上递归调用 inspect,请使用 inspect tree
。
sbt:Hello> inspect tree dist
[info] dist = Task[java.io.File]
[info] +-Universal / dist = Task[java.io.File]
....
您也可以在批处理模式下运行 sbt,直接从终端传递 sbt 命令。
$ sbt clean "testOnly HelloSuite"
注意:在批处理模式下运行需要每次都启动 JVM 并进行 JIT,因此您的构建运行速度会慢得多。对于日常编码,我们建议使用 sbt shell 或 ~testQuick
等连续测试。
您可以使用 sbt new
命令快速设置一个简单的“Hello world”构建。
$ sbt new scala/scala-seed.g8
....
A minimal Scala project.
name [My Something Project]: hello
Template applied in ./hello
当提示您输入项目名称时,请键入 hello
。
这将在名为 hello
的目录下创建一个新项目。
本页基于 William“Scala William”Narmontas 编写的Essential sbt 教程。