使用函式庫範例建置 Scala 應用程式
您可以使用 IntelliJ 原生匯入器 或 Eclipse Buildship 在 IDE 中開啟此範例。 |
若要讓您的軟體專案做好成長準備,您可以將 Gradle 專案整理成多個子專案,以模組化您正在建置的軟體。在本指南中,您將學習如何以 Scala 應用程式的範例來建構此類專案。不過,一般概念適用於您使用 Gradle 建置的任何軟體。您可以逐步遵循指南,從頭開始建立新專案,或使用上述連結下載完整的範例專案。
您將建置的內容
您將建置一個包含一個應用程式和多個函式庫專案的 Scala 應用程式。
您需要準備的內容
-
文字編輯器或 IDE - 例如 IntelliJ IDEA
-
Java 開發套件 (JDK),版本 8 或更高 - 例如 AdoptOpenJDK
建立專案資料夾
Gradle 內建一個名為 init
的任務,用於在空資料夾中初始化新的 Gradle 專案。init
任務使用(同樣內建的)wrapper
任務來建立 Gradle wrapper 指令碼,gradlew
。
第一步是為新專案建立一個資料夾並將目錄變更為該資料夾。
$ mkdir demo $ cd demo
執行 init 任務
在新的專案目錄內,使用終端機中的下列指令執行 init
任務:gradle init
。當出現提示時,選取 1: application
專案類型和 4: Scala
作為實作語言。之後,選取 2: Add library projects
。接著,你可以選擇用於撰寫 buildscript 的 DSL - 1 : Groovy
或 2: Kotlin
。對於其他問題,請按 Enter 使用預設值。
輸出結果會如下所示
$ gradle init Select type of project to generate: 1: basic 2: application 3: library 4: Gradle plugin Enter selection (default: basic) [1..4] 1 Split functionality across multiple subprojects?: 1: no - only one application project 2: yes - application and library projects Enter selection (default: no - only one application project) [1..2] 2 Select implementation language: 1: C++ 2: Groovy 3: Java 4: Kotlin 5: Scala 6: Swift Enter selection (default: Java) [1..6] 4 Select build script DSL: 1: Groovy 2: Kotlin Enter selection (default: Groovy) [1..2] 1 Project name (default: demo): Source package (default: demo): BUILD SUCCESSFUL 2 actionable tasks: 2 executed
init
任務會產生具有下列結構的新專案
├── gradle (1)
│ ├── libs.versions.toml (2)
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew (3)
├── gradlew.bat (3)
├── settings.gradle.kts (4)
├── buildSrc
│ ├── build.gradle.kts (5)
│ ├── settings.gradle.kts (5)
│ └── src
│ └── main
│ └── kotlin (6)
│ ├── buildlogic.scala-application-conventions.gradle.kts
│ ├── buildlogic.scala-common-conventions.gradle.kts
│ └── buildlogic.scala-library-conventions.gradle.kts
├── app
│ ├── build.gradle.kts (7)
│ └── src
│ ├── main (8)
│ │ └── java
│ │ └── demo
│ │ └── app
│ │ ├── App.java
│ │ └── MessageUtils.scala
│ └── test (9)
│ └── java
│ └── demo
│ └── app
│ └── MessageUtilsTest.scala
├── list
│ ├── build.gradle.kts (7)
│ └── src
│ ├── main (8)
│ │ └── java
│ │ └── demo
│ │ └── list
│ │ └── LinkedList.scala
│ └── test (9)
│ └── java
│ └── demo
│ └── list
│ └── LinkedListTest.scala
└── utilities
├── build.gradle.kts (7)
└── src
└── main (8)
└── java
└── demo
└── utilities
├── JoinUtils.scala
├── SplitUtils.scala
└── StringUtils.scala
├── gradle (1)
│ ├── libs.versions.toml (2)
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew (3)
├── gradlew.bat (3)
├── settings.gradle (4)
├── buildSrc
│ ├── build.gradle (5)
│ ├── settings.gradle (5)
│ └── src
│ └── main
│ └── groovy (6)
│ ├── buildlogic.scala-application-conventions.gradle
│ ├── buildlogic.scala-common-conventions.gradle
│ └── buildlogic.scala-library-conventions.gradle
├── app
│ ├── build.gradle (7)
│ └── src
│ ├── main (8)
│ │ └── java
│ │ └── demo
│ │ └── app
│ │ ├── App.java
│ │ └── MessageUtils.java
│ └── test (9)
│ └── java
│ └── demo
│ └── app
│ └── MessageUtilsTest.java
├── list
│ ├── build.gradle (7)
│ └── src
│ ├── main (8)
│ │ └── java
│ │ └── demo
│ │ └── list
│ │ └── LinkedList.java
│ └── test (9)
│ └── java
│ └── demo
│ └── list
│ └── LinkedListTest.java
└── utilities
├── build.gradle (7)
└── src
└── main (8)
└── java
└── demo
└── utilities
├── JoinUtils.java
├── SplitUtils.java
└── StringUtils.java
1 | 產生 wrapper 檔案的資料夾 |
2 | 產生版本目錄 |
3 | Gradle wrapper 啟動指令碼 |
4 | 設定檔案,用於定義建置名稱和子專案 |
5 | buildSrc 的建置指令碼,用於設定建置邏輯的相依性 |
6 | 使用 Groovy 或 Kotlin DSL 撰寫的慣例外掛的原始碼資料夾 |
7 | 三個子專案的建置指令碼 - app 、list 和 utilities |
8 | 各個子專案中的 Scala 原始碼資料夾 |
9 | 子專案中的 Scala 測試原始碼資料夾 |
現在,你已經設定好專案,可以建置一個模組化為多個子專案的 Scala 應用程式。
檢閱專案檔案
settings.gradle(.kts)
檔案中有兩行有趣的程式碼
rootProject.name = "demo"
include("app", "list", "utilities")
rootProject.name = 'demo'
include('app', 'list', 'utilities')
-
rootProject.name
會將名稱指派給建置,這會覆寫根據建置所在的目錄來命名建置的預設行為。建議設定一個固定的名稱,因為如果專案是共用的,資料夾可能會變更 - 例如作為 Git 儲存庫的根目錄。 -
include("app", "list", "utilities")
定義建置包含對應資料夾中的三個子專案。可以透過擴充清單或新增更多include(…)
陳述式來新增更多子專案。
由於我們的建置包含多個子專案,我們想要在它們之間共用建置邏輯和設定。為此,我們使用位於 buildSrc
資料夾中的所謂慣例外掛。buildSrc
中的慣例外掛是一種使用 Gradle 的外掛系統來撰寫可重複使用的建置設定區塊的簡易方法。
在這個範例中,我們可以找到三個基於彼此的慣例外掛
plugins {
scala (1)
}
repositories {
mavenCentral() (2)
}
dependencies {
constraints {
implementation("org.apache.commons:commons-text:1.11.0") (3)
implementation("org.scala-lang:scala-library:2.13.12")
}
implementation("org.scala-lang:scala-library") (4)
testImplementation("org.junit.jupiter:junit-jupiter:5.10.1") (5)
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
tasks.named<Test>("test") {
useJUnitPlatform() (6)
}
plugins {
id 'scala' (1)
}
repositories {
mavenCentral() (2)
}
dependencies {
constraints {
implementation 'org.apache.commons:commons-text:1.11.0' (3)
implementation 'org.scala-lang:scala-library:2.13.12'
}
implementation 'org.scala-lang:scala-library' (4)
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1' (5)
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform() (6)
}
scala-common-conventions
定義一些設定,這些設定應由我們的 Scala 專案共用,而與它們是代表函式庫還是實際應用程式無關。首先,我們套用Scala 外掛 (1),以取得建置 Scala 專案的所有功能。然後,我們宣告一個儲存庫 — mavenCentral()
— 作為外部相依性的來源 (2),定義相依性約束 (3),以及所有子專案共用的標準相依性,並將 JUnit 5 設定為測試架構 (4…)。其他共用設定,例如編譯器旗標或 JVM 版本相容性,也可以在此設定。
plugins {
id("buildlogic.scala-common-conventions") (1)
`java-library` (2)
}
plugins {
id 'buildlogic.scala-common-conventions' (1)
id 'java-library' (2)
}
plugins {
id("buildlogic.scala-common-conventions") (1)
application (2)
}
plugins {
id 'buildlogic.scala-common-conventions' (1)
id 'application' (2)
}
scala-library-conventions
和 scala-application-conventions
都套用 scala-common-conventions
外掛 (1),因此在其中執行的設定會由函式庫和應用程式專案共用。接下來,它們分別套用 java-library
或 application
外掛 (2),進而將我們共用的設定邏輯與函式庫或應用程式的特定設定結合。雖然此範例中沒有更細緻的設定,但函式庫或應用程式專案特定的建置設定可以放入其中一個慣例外掛指令碼中。
我們來看看子專案中的 build.gradle(.kts)
檔案。
plugins {
id("buildlogic.scala-application-conventions")
}
dependencies {
implementation("org.apache.commons:commons-text")
implementation(project(":utilities"))
}
application {
mainClass = "demo.app.App" (1)
}
plugins {
id 'buildlogic.scala-application-conventions'
}
dependencies {
implementation 'org.apache.commons:commons-text'
implementation project(':utilities')
}
application {
mainClass = 'demo.app.App' (1)
}
plugins {
id("buildlogic.scala-library-conventions")
}
plugins {
id 'buildlogic.scala-library-conventions'
}
plugins {
id("buildlogic.scala-library-conventions")
}
dependencies {
api(project(":list"))
}
plugins {
id 'buildlogic.scala-library-conventions'
}
dependencies {
api project(':list')
}
檢視建置指令碼後,我們可以看到它們包含多達三個區塊
-
每個建置指令碼都應該有一個
plugins {}
區塊來套用外掛。在結構良好的建置中,它可能只套用一個 慣例外掛,如同此範例。然後,慣例外掛會負責套用和設定核心 Gradle 外掛 (例如application
或java-library
) 其他慣例外掛或來自外掛入口網站的社群外掛。 -
其次,如果專案有相依性,則應加入
dependencies {}
區塊。相依性可以是外部的,例如我們在scala-common-conventions
中加入的 JUnit 相依性,或可以指向其他本機子專案。為此,我們使用project(…)
符號。在我們的範例中,utilities
函式庫需要list
函式庫。而app
使用utilities
函式庫。如果本機專案彼此相依,則 Gradle 會負責建置相依專案,但僅在需要時。如需深入了解,請參閱關於 Gradle 中相依性管理 的文件。 -
第三,外掛可能有一個或多個設定區塊。這些區塊僅應在建置指令碼中直接使用,如果它們設定某個專案的特定設定。否則,此類設定也屬於慣例外掛。在此範例中,我們使用特定於
application
外掛的application {}
區塊,將app
專案中的mainClass
設定為demo.app.App
(1)。
最後一個建置檔案是 buildSrc
中的 build.gradle(.kts)
檔案。
plugins {
`kotlin-dsl` (1)
}
repositories {
gradlePluginPortal() (2)
}
plugins {
id 'groovy-gradle-plugin' (1)
}
repositories {
gradlePluginPortal() (2)
}
此檔案設定建立慣例外掛本身的階段。透過套用其中一個外掛進行外掛開發 — groovy-gradle-plugin
或 kotlin-dsl
— (1) 我們啟用支援撰寫慣例外掛作為 buildSrc
中的建置檔案。這些就是我們在上面已檢查過的慣例外掛。此外,我們新增 Gradle 的外掛入口網站作為儲存庫 (2),讓我們得以存取社群外掛。若要使用外掛,需要在 dependencies {}
區塊中將其宣告為相依性。
除了 Gradle 建置檔案之外,您可以在對應資料夾中找到範例 Scala 原始碼和測試原始碼。歡迎修改這些產生的原始碼和測試,以探索 Gradle 在執行建置(如後續所述)時如何對變更做出反應。
執行測試
您可以使用 ./gradlew check
執行所有子專案中的所有測試。當您以純粹的任務名稱(例如 check
)呼叫 Gradle 時,任務將會在提供該名稱的所有子專案中執行。若要只針對特定子專案,您可以使用任務的完整路徑。例如,:app:check
將只執行 app
專案的測試。不過,在此範例中,其他子專案仍會編譯,因為 app
宣告對它們有相依性。
$ ./gradlew check BUILD SUCCESSFUL 9 actionable tasks: 9 executed
如果所有測試都順利通過,Gradle 就不會在主控台中列印更多輸出。您可以在 <subproject>/build/reports
資料夾中找到測試報告。歡迎變更一些範例程式碼或測試,然後重新執行 check
,看看如果測試失敗會發生什麼事。
執行應用程式
感謝 application
外掛,您可以直接從命令列執行應用程式。run
任務會指示 Gradle 執行指派給 mainClass
屬性的類別中的 main
方法。
$ ./gradlew run > Task :app:run Hello world! BUILD SUCCESSFUL 2 actionable tasks: 2 executed
您第一次執行 wrapper 腳本 gradlew 時,可能會延遲一段時間,因為 gradle 的版本會下載並儲存在您本機的 ~/.gradle/wrapper/dists 資料夾中。
|
套件應用程式
application
外掛也會為您套件應用程式及其所有相依性。封存檔也會包含一個腳本,讓您可以使用單一命令啟動應用程式。
$ ./gradlew build BUILD SUCCESSFUL in 0s 7 actionable tasks: 7 executed
如果您執行如上所示的完整建置,Gradle 會為您產生兩種格式的封存檔:app/build/distributions/app.tar
和 app/build/distributions/app.zip
。
發佈建置掃描
深入了解您的建置在幕後執行哪些作業的最佳方式,就是發布建置掃描。為此,只要執行 Gradle 並加上 --scan
旗標即可。
$ ./gradlew build --scan BUILD SUCCESSFUL in 0s 7 actionable tasks: 7 executed Publishing a build scan to scans.gradle.com requires accepting the Gradle Terms of Service defined at https://gradle.com/terms-of-service. Do you accept these terms? [yes, no] yes Gradle Terms of Service accepted. Publishing build scan... https://gradle.com/s/5u4w3gxeurtd2
按一下連結,探索已執行的任務、已下載的相依性,以及更多詳細資料!
摘要
就是這樣!您現在已成功使用 Gradle 設定並建置 Scala 應用程式專案。您已學會如何
-
初始化產生 Scala 應用程式的專案
-
透過結合多個子專案來建立模組化軟體專案
-
在
buildSrc
中使用慣例外掛程式,在子專案之間共用建置設定邏輯 -
在所有子專案中執行名稱相似的任務
-
在特定子專案中執行任務
-
建置、套件化並執行應用程式
後續步驟
當您的專案成長時,您可能會對如何設定 JVM 專案、建置多專案建置和相依性管理有興趣