Scala - 構建工具



SBT 代表 **簡單構建工具**。SBT 是一段時間以來 Scala 社群中非常流行和最常用的構建工具。它廣泛的接受度和功能範圍使其成為任何 Scala 專案的明確選擇。SBT 流行的一個主要原因是構建定義是用 Scala 編寫的。

SBT 安裝

就像 **Maven** 一樣,您可以將 SBT 下載為壓縮資料夾。安裝只需解壓縮即可。除了解壓縮之外,還可以根據您的平臺使用各種工具安裝 SBT。對於 Mac:使用 brew,對於 Debian Linux 使用 SDKMAN。在 Windows 上,使用 MSI 安裝程式安裝 SBT。

第一個專案

在計算機上安裝 SBT 後,您可以使用 giter8 建立一個基本專案。

首先,執行以下命令:

sbt new scala/scala-seed.g8

根據 giter8 的說明,將生成一個新的專案目錄。專案目錄包含:

myProject/
   project/
      build.properties
   src/
      main/
         resources/
         scala/
      test/
         resources/
         scala/
   build.sbt

要檢視 project/build.properties 檔案,請使用以下命令開啟檔案:`$ cat project/build.properties`

內容應為:

sbt.version = 1.8.2

您還可以修改 `sbt.version` 以更改專案構建的 SBT 版本。因此,您可以確保每個參與專案協作的人員都使用相同的 SBT 版本進行構建。接下來,執行 sbt 啟動器並檢查 sbt 版本。如果本地有 SBT 版本 1.8.2,則 SBT 啟動器將自動下載它。

SBT 工作流程

要執行 SBT 命令,可以使用 SBT 命令進入 SBT shell 或在每個命令前新增 sbt 字首。我們將在此處使用第二種方法,並在每個命令前新增 sbt 字首。我們將討論最常用的 SBT 任務。

編譯

要編譯並檢查錯誤,請使用 `compile` 命令。例如:

sbt compile
[info] welcome to sbt 1.8.2 (AdoptOpenJDK Java 11.0.12)
// more logs
[success] Total time: 2 s, completed Nov 9, 2023, 3:30:15 PM

測試編譯

您可以使用 test:compile 命令編譯測試類。SBT 會先編譯非測試類,然後再編譯測試類。執行 test:compile 命令:

sbt test:compile
[info] welcome to sbt 1.8.2 (AdoptOpenJDK Java 11.0.12)
[info] compiling 1 Scala source to /myProject/target/scala-2.13/classes ...
[info] compiling 1 Scala source to /myProject/target/scala-2.13/test-classes ...
[success] Total time: 3 s, completed Nov 9, 2023, 3:35:20 PM

測試

如上所述的目錄結構中,/src/test/scala/ 是測試源的標準位置。giter8 模板已包含一個 HelloSpec。例如:

sbt test
[info] welcome to sbt 1.8.2 (AdoptOpenJDK Java 11.0.12)
// more logs
[info] HelloSpec:
[info] The Hello object
[info] - should say hello
[info] Run completed in 212 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 1 s, completed Nov 9, 2023, 3:40:35 PM

執行

您可以使用 run 命令執行專案的 main 函式。您可以使用 mainClass 屬性配置 main 函式或擴充套件 scala.App 特質。giter8 模板包含一個擴充套件 scala.App 特質的類。例如:

sbt run
[info] welcome to sbt 1.8.2 (AdoptOpenJDK Java 11.0.12)
// more logs
[info] running com.example.MyApp 
Hello, Scala!
[success] Total time: 0 s, completed Nov 9, 2023, 3:45:20 PM

軟體工程師會對工具進行各種測試。他們將從多個 main 類執行命令。例如:

sbt run
[info] welcome to sbt 1.8.2 (AdoptOpenJDK Java 11.0.12)
// more logs
Multiple main classes detected. Select one to run:
 [1] com.example.MyApp
 [2] com.example.AnotherApp

Enter number: 2
[info] running com.example.AnotherApp 
Greetings from AnotherApp!
[success] Total time: 278 s (04:38), completed Nov 9, 2023, 4:15:45 PM

清理

您可以使用 `clean` 命令刪除先前生成的 target 目錄。例如:

sbt clean
[info] welcome to sbt 1.8.2 (AdoptOpenJDK Java 11.0.12)
// more logs
[success] Total time: 0 s, completed Nov 9, 2023, 4:20:15 PM

build.sbt 檔案

build.sbt 檔案概述了構建過程中的所有內容。它類似於專案的 Maven pom.xml。我們將討論其最常用的概念。

庫依賴項

您可以使用 zzlibraryDependencies 鍵包含更多庫。例如:

// Single library
libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "5.0.0" % Test

// Multiple libraries
libraryDependencies ++= Seq(
   "org.scalatestplus.play" %% "scalatestplus-play" % "5.0.0" % Test,
   "org.mockito" % "mockito-core" % "3.5.13" % Test
)

任務

任務提供值,並由鍵引用。這些可以生成任何 Scala 型別的值。考慮這個將“hello”列印到控制檯的基本任務:

lazy val greetWorld = taskKey[Unit]("Prints 'Hello, World!'")

greetWorld := println("Hello, World!")

現在,執行此 greetWorld 任務:

sbt greetWorld
[info] welcome to sbt 1.8.2 (AdoptOpenJDK Java 11.0.12)
// more logs
Hello, World!
[success] Total time: 0 s, completed Nov 9, 2023, 5:00:15 PM

任務可以將其他任務和屬性作為輸入。例如,建立一個將另一個任務的值乘以 2 的任務:

lazy val two = taskKey[Int]("two")
two := 2

lazy val twoTimesThree = taskKey[Unit]("two times three")
twoTimesThree := println(s"2 * 3 = ${2 * three.value}")

現在,執行此 twoTimesThree 任務:

sbt twoTimesThree
[info] welcome to sbt 1.8.2 (AdoptOpenJDK Java 11.0.12)
// more logs
2 * 3 = 6
[success] Total time: 0 s, completed Nov 9, 2023, 5:20:45 PM

命令

命令是命名操作,將當前構建狀態作為引數並計算新狀態。儘管命令和任務定義看起來相似。但命令功能更強大。它們可以訪問甚至修改狀態。

建立一個更改狀態並向其中新增另一個命令的命令:

lazy val greetCommand = Command.command("greetCommand") { state =>
   println("Greetings from custom command!")
   state
}

lazy val addGreetCommand = Command.command("addGreetCommand") { state =>
   println("Adding greetCommand to defined commands.")
   state.copy(definedCommands = state.definedCommands :+ greetCommand)
}

lazy val root = (project in file("."))
.settings(
   // other settings ..
   commands ++= Seq(addGreetCommand)
)

請注意,greetCommand 不包含在專案命令中。這意味著在呼叫 addGreetCommand 之後,helloCommand 才可訪問。例如,使用 SBT shell 確保狀態得到保留:

sbt
[info] welcome to sbt 1.8.2 (AdoptOpenJDK Java 11.0.12)
// more logs
sbt:myProject> greetCommand
[error] Not a valid command: greetCommand (similar: addGreetCommand, reload)
[error] Not a valid project ID: greetCommand
[error] Expected ':'
[error] Not a valid key: greetCommand (similar: watchBeforeCommand, commands, addGreetCommand)
[error] greetCommand
[error]             ^
sbt:myProject> addGreetCommand
Adding greetCommand to defined commands.
sbt:myProject> greetCommand
Greetings from custom command!

命令別名

如果要一起執行一組任務或命令。您可以使用命令別名。例如,建立一個呼叫 compile 和 test 的別名:

addCommandAlias("buildAndTest", ";compile;test")

現在,執行 sbt buildAndTest 別名:

sbt buildAndTest
[info] welcome to sbt 1.8.2 (AdoptOpenJDK Java 11.0.12)
// compile logs
[success] Total time: 0 s, completed Nov 9, 2023, 6:15:20 PM
// test logs
[info] All tests passed.
[success] Total time: 3 s, completed Nov 9, 2023, 6:15:23 PM

解析器

您可以使用 resolvers 設定為 SBT 新增儲存庫以查詢依賴項。例如,新增 Typesafe 和 Maven2 儲存庫:

resolvers ++= Seq(
   "Typesafe" at "https://repo.typesafe.com/typesafe/releases/",
   "Java.net Maven2 Repository" at "https://download.java.net/maven/2/"
)

外掛

SBT 外掛主要由構建定義組成。簡單來說,外掛允許我們在構建中重用程式碼。您可以在專案中包含一個新外掛,並在 project/plugins.sbt 檔案中定義它。例如,將 scalafmt 外掛新增到我們的專案中:

addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6")
廣告