iT邦幫忙

2021 iThome 鐵人賽

DAY 16
2
Software Development

Gradle 通靈術系列 第 16

第十六天:複數專案架構

之前在看別人的 JVM 專案時,有時會發現數個不同的 Module 原始碼卻都指向同一個 Repository,這才發現原來 Gradle 支援複數專案架構。也就是說在一個 Repository 裡可以指定不同子資料夾放置不同的子專案,而 Gradle 在建置專案的時候,會依照這樣的專案架構輸出多個結果,並發佈到不同的 Module 名稱底下。

若大家還記得在我們一開始學習 Gradle 的 init 指令時,也曾經被詢問過是否要建立多個子專案。今天我們就來看一下 Gradle 是如何產生出複數專案架構的?另外也同場加映一下,看類似的複數專案架構要怎麼在 IntelliJ IDEA 裡新增?

使用 Gradle 指令建立複數專案架構

首先開啟終端機,先建立一個測試用的資料夾,並切換成工作目錄,接著執行 $ 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

在這個結構裡 applistutilities 各自代表 Application、Library、Utilities 專案,這些資料夾都有類似的結構,都有自己的 build.gradle.ktssrc 資料夾裡都有標準的 Module 結構,一個 main、一個 test 資料夾,裡面各自有 kotlinresources 資料夾。而在最外層則是共享 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 建立複數專案架構

接著我們用 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.ktssrc 資料夾。外層也有相同的 Gradle Wrapper、settings.gradle.kts。唯一的差別在於,IntelliJ IDEA 會幫我們在外層放 build.gradle.ktsgradle.properties

打開 build.gradle.kts 觀察一下,會發現 IntelliJ IDEA 會幫我們針對全部的專案設定共享的 repositories 設定,這樣在子專案裡就可以省下重複宣告的工作:

allprojects {
    repositories {
        mavenCentral()
    }
}

最後還想提一點,就是當我們是複數專案時,IntelliJ IDEA 的 Gradle 面板就會把各個子專案的 Gradle Tasks 以分資料夾的方式呈現,在使用的時候,要注意一下自己呼叫的是哪個子專案的任務。

而若是從終端機輸入指令的話,則要使用 :<project>:<task> 的組合來指定正確的任務全名。


上一篇
第十五天:初探 Gradle properties
下一篇
第十七天:該用 implementation 還是 compile?
系列文
Gradle 通靈術24
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言