之前在看別人的 JVM 專案時,有時會發現數個不同的 Module 原始碼卻都指向同一個 Repository,這才發現原來 Gradle 支援複數專案架構。也就是說在一個 Repository 裡可以指定不同子資料夾放置不同的子專案,而 Gradle 在建置專案的時候,會依照這樣的專案架構輸出多個結果,並發佈到不同的 Module 名稱底下。
若大家還記得在我們一開始學習 Gradle 的 init
指令時,也曾經被詢問過是否要建立多個子專案。今天我們就來看一下 Gradle 是如何產生出複數專案架構的?另外也同場加映一下,看類似的複數專案架構要怎麼在 IntelliJ IDEA 裡新增?
首先開啟終端機,先建立一個測試用的資料夾,並切換成工作目錄,接著執行 $ gradle init
,跟著互動式問答一步步建立專案,只是這次在詢問是否要建立 Multiple Subproject 時要選 yes
:
$ gradle init
Select type of project to generate:
1: basic
2: application
3: library
4: Gradle plugin
Enter selection (default: basic) [1..4] 2
Select implementation language:
1: C++
2: Groovy
3: Java
4: Kotlin
5: Scala
6: Swift
Enter selection (default: Java) [1..6] 4
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 build script DSL:
1: Groovy
2: Kotlin
Enter selection (default: Kotlin) [1..2] 2
Project name (default: multi-project-gradle):
Source package (default: multi.project.gradle): io.kraftsman
> Task :init
Get more help with your project: https://docs.gradle.org/7.2/samples/sample_building_kotlin_applications_multi_project.html
BUILD SUCCESSFUL in 25s
2 actionable tasks: 2 executed
專案建立完成後,我們會拿到一個像這樣的專案架構:
├── app
│ ├── build.gradle.kts
│ └── src
│ ├── main
│ │ ├── kotlin
│ │ └── resources
│ └── test
│ ├── kotlin
│ └── resources
├── buildSrc
│ ├── build.gradle.kts
│ └── src
│ └── main
│ └── kotlin
├── list
│ ├── build.gradle.kts
│ └── src
│ ├── main
│ │ ├── kotlin
│ │ └── resources
│ └── test
│ ├── kotlin
│ └── resources
├── utilities
│ ├── build.gradle.kts
│ └── src
│ ├── main
│ │ ├── kotlin
│ │ └── resources
│ └── test
│ └── resources
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle.kts
在這個結構裡 app
、list
、utilities
各自代表 Application、Library、Utilities 專案,這些資料夾都有類似的結構,都有自己的 build.gradle.kts
,src
資料夾裡都有標準的 Module 結構,一個 main
、一個 test
資料夾,裡面各自有 kotlin
及 resources
資料夾。而在最外層則是共享 Gradle Wrapper(gradle
資料夾及 2 個 gradlew
)及 settings.gradle.kts
。最後 buildSrc
是 Gradle Plugin,我們現階段先暫時略過。
打開 settings.gradle.kts
,會發現它將 3 個子資料夾用 include()
的方式匯入:
rootProject.name = "multi-project-gradle"
include("app", "list", "utilities")
接著我們用 IntelliJ IDEA 試著建立類似的複數專案架構。點選 File > New > Project...,依序填入 Name、Location、Project Template、Build System、Project JDK 等資料。
下一步先設定 mainModule 的 Template、Test Framework、Target JVM version。
然後再按一下左上角的 + 按鈕就可以新增一個 Module,我們仿照 Gradle 的結構新增 2 個新的 Module。
再回到 mainModule,更名為 app,並設定與另外兩個 Module 相依。
專案建立好後,整個結構長得像這樣:
├── app
│ ├── build.gradle.kts
│ └── src
│ ├── main
│ │ ├── kotlin
│ │ └── resources
│ └── test
│ ├── kotlin
│ └── resources
├── list
│ ├── build.gradle.kts
│ └── src
│ ├── main
│ │ ├── kotlin
│ │ └── resources
│ └── test
│ ├── kotlin
│ └── resources
├── utilities
│ ├── build.gradle.kts
│ └── src
│ ├── main
│ │ ├── kotlin
│ │ └── resources
│ └── test
│ ├── kotlin
│ └── resources
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── build.gradle.kts
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle.kts
從上面的結構比對起來,專案結構是類似的,每個子專案都有自己的 build.gradle.kts
及 src
資料夾。外層也有相同的 Gradle Wrapper、settings.gradle.kts
。唯一的差別在於,IntelliJ IDEA 會幫我們在外層放 build.gradle.kts
及 gradle.properties
。
打開 build.gradle.kts
觀察一下,會發現 IntelliJ IDEA 會幫我們針對全部的專案設定共享的 repositories
設定,這樣在子專案裡就可以省下重複宣告的工作:
allprojects {
repositories {
mavenCentral()
}
}
最後還想提一點,就是當我們是複數專案時,IntelliJ IDEA 的 Gradle 面板就會把各個子專案的 Gradle Tasks 以分資料夾的方式呈現,在使用的時候,要注意一下自己呼叫的是哪個子專案的任務。
而若是從終端機輸入指令的話,則要使用 :<project>:<task>
的組合來指定正確的任務全名。