此頁面描述使用 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
}
.sbt
檔案中,例如 $HOME/.sbt/1.0/global.sbt
。這些設定將會套用到所有專案。.sbt
檔案中,例如 <project>/local.sbt
。sbt 會合併多個 .sbt 檔案中的設定,因此您仍然可以擁有標準的 <project>/build.sbt
並將其簽入版本控制。將 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 將為您解析相對於建置根目錄的相對檔案。
token
來清楚分隔 Tab 鍵完成的邊界。flatMap
進行一般遞迴。sbt 的組合子是嚴格的,以限制產生的類別數量,因此請像這樣使用 flatMaplazy val parser: Parser[Int] =
token(IntBasic) flatMap { i =>
if(i <= 0)
success(i)
else
token(Space ~> parser)
}
此範例定義一個解析器,解析以空格分隔的整數清單,以負數結尾,並傳回最後的負數。