此頁面將協助您開始建立自己的設定和任務。
若要了解此頁面,請務必閱讀入門指南中先前的頁面,尤其是 build.sbt 和 任務圖。
Keys 包含許多範例,說明如何定義鍵。大多數鍵都在 Defaults 中實作。
鍵有三種類型。SettingKey
和 TaskKey
在 .sbt 建置定義中說明。請在 輸入任務頁面中閱讀有關 InputKey
的資訊。
Keys 中的一些範例
val scalaVersion = settingKey[String]("The version of Scala used for building.")
val clean = taskKey[Unit]("Deletes files produced by the build, such as generated sources, compiled classes, and task caches.")
鍵建構子有兩個字串參數:鍵的名稱 ("scalaVersion"
) 和文件字串 ("用於建置的 scala 版本。"
)。
請回想一下,從 .sbt 建置定義中,SettingKey[T]
中的類型參數 T
指示設定具有的值的類型。TaskKey[T]
中的 T
指示任務結果的類型。另請回想一下,從 .sbt 建置定義中,設定在專案重新載入之前具有固定值,而任務則會針對每個「任務執行」重新計算(每次有人在 sbt 互動提示符或批次模式中輸入命令時)。
鍵可以定義在 .sbt 檔案、.scala 檔案或 自動外掛程式中。在已啟用的自動外掛程式的 autoImport
物件下找到的任何 val
都會自動匯入您的 .sbt
檔案中。
一旦您為您的任務定義了鍵,您就需要使用任務定義來完成它。您可能正在定義自己的任務,或者您可能正計畫重新定義現有任務。無論哪種方式看起來都一樣;使用 :=
將某些程式碼與任務鍵建立關聯
val sampleStringTask = taskKey[String]("A sample string task.")
val sampleIntTask = taskKey[Int]("A sample int task.")
ThisBuild / organization := "com.example"
ThisBuild / version := "0.1.0-SNAPSHOT"
ThisBuild / scalaVersion := "2.12.18"
lazy val library = (project in file("library"))
.settings(
sampleStringTask := System.getProperty("user.home"),
sampleIntTask := {
val sum = 1 + 2
println("sum: " + sum)
sum
}
)
如果任務具有相依性,您可以使用 value
參考它們的值,如 任務圖中所述。
實作任務最困難的部分通常不是 sbt 特有的;任務只不過是 Scala 程式碼。困難的部分可能是撰寫您的任務的「主體」,以執行您嘗試執行的任何操作。例如,您可能嘗試格式化 HTML,在這種情況下,您可能想要使用 HTML 函式庫(您可以將函式庫相依性新增至您的建置定義,並根據 HTML 函式庫撰寫程式碼,或許)。
sbt 有一些公用程式函式庫和便利功能,特別是您通常可以使用 IO 中的便利 API 來操作檔案和目錄。
當使用 value
從自訂任務相依於其他任務時,一個需要注意的重要細節是任務的執行語意。所謂的執行語意,我們指的是這些任務的確切評估時間。
如果我們以 sampleIntTask
為例,則應該依序嚴格評估任務主體中的每一行。這就是循序語意
sampleIntTask := {
val sum = 1 + 2 // first
println("sum: " + sum) // second
sum // third
}
實際上,JVM 可能會將 sum
內嵌為 3
,但任務的可觀察效果仍會與每一行都依序執行相同。
現在假設我們定義另外兩個自訂任務 startServer
和 stopServer
,並如下修改 sampleIntTask
val startServer = taskKey[Unit]("start server")
val stopServer = taskKey[Unit]("stop server")
val sampleIntTask = taskKey[Int]("A sample int task.")
val sampleStringTask = taskKey[String]("A sample string task.")
ThisBuild / organization := "com.example"
ThisBuild / version := "0.1.0-SNAPSHOT"
ThisBuild / scalaVersion := "2.12.18"
lazy val library = (project in file("library"))
.settings(
startServer := {
println("starting...")
Thread.sleep(500)
},
stopServer := {
println("stopping...")
Thread.sleep(500)
},
sampleIntTask := {
startServer.value
val sum = 1 + 2
println("sum: " + sum)
stopServer.value // THIS WON'T WORK
sum
},
sampleStringTask := {
startServer.value
val s = sampleIntTask.value.toString
println("s: " + s)
s
}
)
從 sbt 互動提示符執行 sampleIntTask
會產生以下結果
> sampleIntTask
stopping...
starting...
sum: 3
[success] Total time: 1 s, completed Dec 22, 2014 5:00:00 PM
若要檢視發生的情況,讓我們看看 sampleIntTask
的圖形符號
與一般的 Scala 方法呼叫不同,在任務上叫用 value
方法不會嚴格評估。相反地,它們只是充當預留位置,表示 sampleIntTask
相依於 startServer
和 stopServer
任務。當您叫用 sampleIntTask
時,sbt 的任務引擎將會
sampleIntTask
之前,先評估任務相依性(部分排序)為了示範最後一點,我們可以從 sbt 互動提示符執行 sampleStringTask
。
> sampleStringTask
stopping...
starting...
sum: 3
s: 3
[success] Total time: 1 s, completed Dec 22, 2014 5:30:00 PM
因為 sampleStringTask
相依於 startServer
和 sampleIntTask
任務,而 sampleIntTask
也相依於 startServer
任務,所以它會以任務相依性的形式出現兩次。如果這是一般的 Scala 方法呼叫,則會評估兩次,但是由於 value
只是表示任務相依性,因此它只會評估一次。以下是 sampleStringTask
評估的圖形符號
如果我們沒有重複資料刪除任務相依性,則在叫用 test
任務時,我們會多次編譯測試來源程式碼,因為 Test / compile
會多次以 Test / test
的任務相依性形式出現。
應該如何實作 stopServer
任務?清除任務的概念不符合任務的執行模型,因為任務是關於追蹤相依性。最後一個操作應變成相依於其他中繼任務的任務。例如,stopServer
應該相依於 sampleStringTask
,屆時 stopServer
應該是 sampleStringTask
。
lazy val library = (project in file("library"))
.settings(
startServer := {
println("starting...")
Thread.sleep(500)
},
sampleIntTask := {
startServer.value
val sum = 1 + 2
println("sum: " + sum)
sum
},
sampleStringTask := {
startServer.value
val s = sampleIntTask.value.toString
println("s: " + s)
s
},
sampleStringTask := {
val old = sampleStringTask.value
println("stopping...")
Thread.sleep(500)
old
}
)
為了示範其運作方式,請從互動提示符執行 sampleStringTask
> sampleStringTask
starting...
sum: 3
s: 3
stopping...
[success] Total time: 1 s, completed Dec 22, 2014 6:00:00 PM
另一種確保某件事在其他事之後發生的方法是使用 Scala。例如,在 project/ServerUtil.scala
中實作簡單的函式,您可以撰寫
sampleIntTask := {
ServerUtil.startServer
try {
val sum = 1 + 2
println("sum: " + sum)
} finally {
ServerUtil.stopServer
}
sum
}
由於純方法呼叫遵循循序語意,因此所有事情都會依序發生。沒有重複資料刪除,因此您必須注意這一點。
如果您發現您有很多自訂程式碼,請考慮將其移至外掛程式,以便在多個建置中重複使用。
這個頁面只是快速瀏覽;關於自訂任務的更多內容,請參閱任務頁面。