建構配置
sbt
項目根目錄下的
build.sbt
定義了項目的建構配置。
project
目錄下也可以添加
*.scala
建構定義。
可以在
build.sbt
檔案中設定項目的名稱、版本資訊、建構規則、依賴等配置。
build.sbt
檔案遵循
Scala
文法。
一個簡單的
build.sbt
檔案内容如下所示:
name := "項目名稱"
version := "項目版本号"
scalaVersion := "Scala編譯器版本号"
libraryDependencies ++= Seq(
"xx" % "xx" % "xx", //項目Java依賴
...
"xx" % "xx" %% "xx", //項目Scala依賴
...
)
scalacOptions ++= Seq(
"-xxx", //編譯器選項
...
)
enablePlugins(Xxx) //啟用插件
sbt shell
隻在啟動時讀取一遍建構配置。
若在
sbt shell
開啟之後
build.sbt
檔案發生了修改,則已經開啟的
sbt shell
依舊使用之前的建構配置。
若需要已開啟的
sbt shell
使用新的建構配置,則應在
sbt shell
中使用
reload
指令重新加載建構配置。
自定義源碼路徑
sbt
項目預設源碼路徑為
項目根目錄/src
,若需要管理預設路徑之外的源碼,在
build.sbt
中添加:
// 擷取源碼絕對路徑,并建構 File 執行個體
def sourceDir(dir: String) = file(s"${file(".").getAbsolutePath}/$dir")
// 自定義源碼路徑需要修改 unmanagedSourceDirectories 配置項
unmanagedSourceDirectories in Compile ++= Seq(
sourceDir("子目錄1"),
sourceDir("子目錄2"),
...
)
多項目建構
sbt
支援多項目建構,一個項目中可包含多個子項目。
每個子項目均可包含獨立、完整的建構配置。
使用
sbt
環境中預定義的
project
方法指定子項目的路徑:
// 子項目的根路徑為目前路徑下的 xxx 子路徑
// 子項目名稱 ChildProject (變量名稱)
lazy val ChildProject = project in file("xxx")
project
方法建構的執行個體類型為
sbt.Project
,代表子項目的建構定義,執行個體名稱會作為子項目的
ID
。
若
project in file("xxx")
中的路徑資訊
xxx
為
.
(項目目前路徑)時,擷取的執行個體代表預設項目的建構定義。
sbt.Project
類型定義了一系列控制建構配置的方法:
package sbt
sealed trait Project extends AnyRef with ProjectDefinition[ProjectReference] {
...
def in(dir : java.io.File): Project = ... //設定建構定義的對應路徑
def configs(cs: librarymanagement.Configuration*): Project = ...
def dependsOn(deps: ClasspathDep[ProjectReference]*): Project = ... //設定項目依賴
def settings(ss: Def.SettingsDefinition*): Project = ... //設定項目通用配置
def enablePlugins(ns: Plugins*): Project = ... //啟用SBT插件
def disablePlugins(ps: AutoPlugin*) : Project = ... //禁用SBT插件
...
}
使用
settings()
方法向項目中添加通用定義:
childProject
.settings(
libraryDependencies ++= Seq(
...
),
scalacOptions ++= Seq(
...
),
...)
所有能在父級項目中設定的配置都可以添加在子項目的
settings()
方法中。
使用
enablePlugins()/disablePlugins()
方法啟用/禁用
sbt
插件。
使用
dependsOn()
方法設定依賴項目,子項目能引用依賴項目的代碼,并自動引入依賴項目的
libraryDependencies
。
sbt.Project
類型的主要方法均傳回自身執行個體,支援鍊式調用。
常見的配置結構,如下所示:
val root = project in file(".") //父項目配置
.settings(
...
)
...
val child = (project in file("xxx")) //子項目配置
.dependsOn(root) //設定依賴項目
.enablePlugins(xxx) //啟用插件
.settings( //配置相
name := "xxx",
version := "xxx",
scalaVersion := "2.12.x"
libraryDependencies ++= Seq(
... //jar包依賴
),
scalacOptions ++= Seq(
... //編譯器配置
),
...
)
通路建構資訊
sbt
沒有提供通路
build.sbt
中項目建構資訊的接口,使用
sbt
插件
sbt-buildinfo
可以讓項目通路
sbt
的建構資訊。
在
sbt
項目中的
project/plugins.sbt
檔案中引入該插件:
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "版本号")
在項目建構配置檔案
build.sbt
中啟用
sbt-buildinfo
插件:
enablePlugins(BuildInfoPlugin)
sbt-buildinfo
插件的原理是利用
build.sbt
中的項目建構資訊在項目建構時生成額外的源碼,
并以單例對象的形式将建構資訊提供給項目源碼進行通路。
啟用
sbt-buildinfo
插件後會增加插件相關的配置項。
将
build.sbt
中的
name、version、scalaVersion、sbtVersion
等配置項傳入
sbt-buildinfo
插件的
buildInfoKeys
配置項,
通過
buildInfoPackage
配置項設定生成單例的包路徑。
在
build.sbt
檔案中配置
sbt-buildinfo
插件,執行個體如下:
// sbt項目建構資訊
name := "xxx"
version := "xxx"
scalaVersion := "2.12.3"
sbtVersion := "0.13.16"
// 啟用 sbt-buildinfo 插件
enablePlugins(BuildInfoPlugin)
// 設定建構資訊
buildInfoKeys := Seq(name, version, scalaVersion, sbtVersion)
buildInfoPackage := "xxx.yyy.zzz" //将建構資訊生成到 xxx.yyy.zzz 包路徑中
sbt-buildinfo
插件生成的單例對象結構如下所示:
case object BuildInfo {
/** The value is "xxx". */
val name: String = "xxx"
/** The value is "xxx". */
val version: String = "xxx"
/** The value is "2.12.2". */
val scalaVersion: String = "2.12.2"
/** The value is "0.13.15". */
val sbtVersion: String = "0.13.15"
override val toString: String = {
"name: %s, version: %s, scalaVersion: %s, sbtVersion: %s" format (
name, version, scalaVersion, sbtVersion
)
}
}
處理建構沖突
jar
打包時将多個
jar
包依賴引入同一個包時,若依賴的
jar
包包含相對路徑相同的目錄、檔案,則可能産生沖突。
如
com.typesafe.slick:slick
和
com.typesafe.akka:akka-actor
包中的根路徑下均包含
reference.conf
配置檔案,
該配置記錄了子產品運作時必要的預設配置。
若打包時同時依賴這兩個包,則生成的
jar
包中
reference.conf
檔案隻會保留一份。
運作時
akka-actor
或
slick
可能會因為缺少預設配置異常退出。
使用
sbt-assembly
插件可處理建構流程中的檔案沖突。
在
build.sbt
中添加:
assemblyMergeStrategy in assembly := {
case PathList("reference.c·onf") => MergeStrategy.concat //合并沖突檔案内容
}
若使用
IDEA
提供的打包工具,則
sbt-assembly
插件不會生效。
解決沖突檔案的方案是在項目
resource
路徑下手動建立沖突檔案,手動合并來自不同包的沖突檔案内容。