1. 通用最佳實務

通用最佳實務 

此頁面描述使用 sbt 的最佳實務。

project/ vs. ~/.sbt/ 

任何建置專案所必需的內容都應放在 project/ 中。這包括像是 Web 外掛程式之類的項目。~/.sbt/ 應包含用於處理建置的本機自訂和命令,但並非必要。例如 IDE 外掛程式。

本機設定 

有兩個選項適用於特定使用者的設定。此類設定的一個範例是在解析器清單開頭插入本機 Maven 儲存庫

resolvers := {
  val localMaven = "Local Maven Repository" at "file://"+Path.userHome.absolutePath+"/.m2/repository"
  localMaven +: resolvers.value
}
  1. 將特定於使用者的設定放在全域 .sbt 檔案中,例如 $HOME/.sbt/1.0/global.sbt。這些設定將會套用到所有專案。
  2. 將設定放在專案中未受版本控制的 .sbt 檔案中,例如 <project>/local.sbt。sbt 會合併多個 .sbt 檔案中的設定,因此您仍然可以擁有標準的 <project>/build.sbt 並將其簽入版本控制。

.sbtrc 

將 sbt 啟動時要執行的命令放在 .sbtrc 檔案中,每行一個。這些命令會在載入專案之前執行,可用於定義別名等。sbt 會依序執行 $HOME/.sbtrc(如果存在)中的命令,然後執行 <project>/.sbtrc(如果存在)中的命令。

產生檔案 

將任何產生的檔案寫入輸出目錄的子目錄,該目錄由 target 設定指定。這樣可以輕鬆地在建置後清除,並提供一個組織產生檔案的單一位置。任何特定於 Scala 版本的產生檔案應放入 crossTarget 中,以進行有效的跨建置。

如需產生原始碼和資源,請參閱 產生檔案

不要硬式編碼 

不要硬式編碼常數,例如輸出目錄 target/。這對於外掛程式來說尤其重要。使用者可能會將 target 設定變更為指向 build/,例如,並且外掛程式需要遵循此設定。相反地,請使用設定,例如

myDirectory := target.value / "sub-directory"

不要「變更」檔案 

建置自然包含大量檔案操作。我們如何將此與任務系統協調一致?任務系統在其他方面可以幫助我們避免可變狀態。一種方法(也是建議的方法和 sbt 預設任務使用的方法)是僅將任何給定檔案寫入一次,並且僅從單一任務寫入。

建置產品(或副產品)應該僅由一個任務寫入一次。然後,任務至少應提供作為其結果建立的檔案。想要使用檔案的其他任務應該映射該任務,同時獲取檔案參考並確保該任務已執行(因此已建構檔案)。顯然,您無法對使用者或其他修改檔案的程序做太多處理,但您可以透過將檔案內容視為任務層級的不可變內容,使建置控制下的 I/O 更具可預測性。

例如

lazy val makeFile = taskKey[File]("Creates a file with some content.")

// define a task that creates a file,
//  writes some content, and returns the File
makeFile := {
    val f: File = file("/tmp/data.txt")
    IO.write(f, "Some content")
    f
}

// The result of makeFile is the constructed File,
//   so useFile can map makeFile and simultaneously
//   get the File and declare the dependency on makeFile
useFile :=
    doSomething( makeFile.value )

這種安排並非總是可行,但應該是規則,而不是例外。

使用絕對路徑 

僅建構絕對檔案。請指定絕對路徑

file("/home/user/A.scala")

或從絕對基礎建構檔案

base / "A.scala"

這與「不要硬式編碼」最佳實務有關,因為正確的方法涉及參考 baseDirectory 設定。例如,以下將 myPath 設定定義為 <base>/licenses/ 目錄。

myPath := baseDirectory.value / "licenses"

在 Java(因此也在 Scala 中),相對檔案是相對於目前工作目錄的。由於多種原因,工作目錄並不總是與建置根目錄相同。

此規則的唯一例外是指定專案的基本目錄時。在此,為方便起見,sbt 將為您解析相對於建置根目錄的相對檔案。

解析器組合子 

  1. 在任何地方使用 token 來清楚分隔 Tab 鍵完成的邊界。
  2. 不要重疊或巢狀化標記。此處的行為未指定,將來很可能會產生錯誤。
  3. 使用 flatMap 進行一般遞迴。sbt 的組合子是嚴格的,以限制產生的類別數量,因此請像這樣使用 flatMap
lazy val parser: Parser[Int] =
  token(IntBasic) flatMap { i =>
    if(i <= 0)
      success(i)
    else
      token(Space ~> parser)
  }

此範例定義一個解析器,解析以空格分隔的整數清單,以負數結尾,並傳回最後的負數。