如何在 Gradle 中将单项目构建转换为多项目构建
当你的 Gradle 项目不断增长时,你可能希望将其拆分成多个子项目,以提高模块化、可维护性和并行执行能力。
本指南解释了如何将单项目构建转换为多项目构建。
为什么使用多项目构建?
单项目构建在一个 build.gradle(.kts)
文件中管理所有源代码和依赖项。
相比之下,多项目构建包含:
-
一个根项目,其中包含共享配置和依赖项,定义在
settings.gradle(.kts)
文件中。 -
多个子项目,每个子项目都有自己的
build.gradle(.kts)
文件、依赖项和任务。
步骤 1:项目结构
让我们从一个典型的单项目设置开始,这个设置由 gradle init
命令创建
root
├── settings.gradle(.kts) (1)
└── app (2)
├── build.gradle(.kts)
└── src/
1 | 定义根项目设置 |
2 | 单个应用模块 |
或者,你的单项目可能看起来像这样
app (root) (1)
├── build.gradle(.kts)
├── settings.gradle(.kts)
└── src/
1 | 项目根目录,同时也是应用模块 |
如果你的项目是这样的结构,在开始之前,请将 app 文件夹嵌套在一个新的 root 文件夹内。 |
将其转换为多项目构建后,结构将看起来像这样
root
├── settings.gradle(.kts) (1)
├── app (2)
│ ├── build.gradle(.kts)
│ └── src/
└── library (3)
├── build.gradle(.kts)
└── src/
1 | 定义子项目 |
2 | 原始的应用模块,现在是一个子项目 |
3 | 一个新的库模块 |
步骤 2:创建一个或多个新的子项目
现在你可以在 root
目录中创建额外的项目目录。它们都将成为根项目的子项目。
为了继续我们的例子,我们创建一个名为 library
的新子项目
cd root
mkdir library
确保原始项目 (app
) 与新的 library
子项目处于同一级别
root
├── app (1)
│ └── some files
└── library (2)
1 | 原始应用模块 |
2 | 新创建的子项目 |
将源文件移动到相应的文件夹中。
在我们的例子中,可重用代码被移动到 library
子项目
root
├── app (1)
│ └── src/
└── library (2)
└── src/
1 | 应用模块,包含其自身的源代码 |
2 | 新的库模块,用于存储可重用代码 |
步骤 3:更新 settings.gradle(.kts)
确保 settings.gradle(.kts)
位于根目录
root
├── settings.gradle(.kts) (1)
├── app (2)
│ └── src/
└── library (3)
└── src/
1 | 整个构建的单个设置文件 |
2 | 应用模块 |
3 | 新的库模块 |
修改 settings.gradle(.kts)
文件以包含新的子项目。
在我们的例子中,我们将 library
添加到 include
中
rootProject.name = "root"
include("app", "library")
rootProject.name = "root"
include("app", "library")
不应该有其他设置文件.
步骤 4:为每个子项目创建 build.gradle(.kts)
文件
每个子项目必须有自己的 build.gradle(.kts)
文件
root
├── settings.gradle(.kts) (1)
├── app (2)
│ ├── build.gradle(.kts) (3)
│ └── src/
└── library (4)
├── build.gradle(.kts) (5)
└── src/
1 | 定义子项目 |
2 | 应用子项目 |
3 | 定义 app 构建 |
4 | 库子项目 |
5 | 定义 library 构建 |
app
的构建文件应该与原始构建文件非常相似。它包含构建 app
子项目所需的所有依赖项和配置。
现在,它还依赖于 library
子项目
plugins {
application
id("org.jetbrains.kotlin.plugin.serialization") // Now the plugin is applied
}
repositories {
mavenCentral()
}
dependencies {
implementation("com.google.guava:guava:33.3.1-jre")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
implementation(project(":library")) // Uses the library module
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
application {
mainClass = "org.example.App"
}
plugins {
id('application')
id("org.jetbrains.kotlin.plugin.serialization") // Now the plugin is applied
}
repositories {
mavenCentral()
}
dependencies {
implementation("com.google.guava:guava:33.3.1-jre")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
implementation(project(":library")) // Uses the library module
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
application {
mainClass = "org.example.App"
}
library
的构建文件应该是新的。它包含构建 library
子项目所需的所有依赖项和配置。
plugins {
id("java-library")
id("org.jetbrains.kotlin.plugin.serialization") // Now the plugin is applied
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.apache.commons:commons-lang3:3.17.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
}
plugins {
id("java-library")
id("org.jetbrains.kotlin.plugin.serialization") // Now the plugin is applied
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.apache.commons:commons-lang3:3.17.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
}
步骤 5:修改或删除根项目的 build.gradle(.kts)
根项目中的构建文件是可选的
root
├── settings.gradle(.kts) (1)
├── build.gradle(.kts) (2)
├── app (3)
│ ├── build.gradle(.kts)
│ └── src/
└── library (4)
├── build.gradle(.kts)
└── src/
1 | 定义子项目 |
2 | 可选(用于共享配置) |
3 | 应用模块 |
4 | 新的库模块 |
如果你需要配置共享仓库和设置,可以使用根项目的 build.gradle(.kts)
文件。
plugins {
id("org.jetbrains.kotlin.plugin.serialization") version "1.9.21" apply false
}
subprojects {
repositories {
mavenCentral()
}
}
plugins {
id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.21' apply false
}
subprojects {
repositories {
mavenCentral()
}
}
你可以回顾一下名为 org.jetbrains.kotlin.plugin.serialization
的第三方常用插件是如何在每个构建文件中应用的。
然而,共享逻辑应该使用约定插件 (convention plugins)来处理,而不是使用根构建文件。
总结
这个过程可以无限重复以添加更多子项目
root
├── settings.gradle(.kts) (1)
├── app (2)
│ ├── build.gradle(.kts)
│ └── src/
├── library-a (3)
│ ├── build.gradle(.kts)
│ └── src/
├── library-b (4)
│ ├── build.gradle(.kts)
│ └── src/
└── library-c (5)
├── build.gradle(.kts)
└── src/
1 | 定义子项目 |
2 | 应用模块 |
3 | 一个共享库模块 |
4 | 另一个库模块 |
5 | 又一个库模块 |
通过遵循这些步骤,你可以模块化你的项目,提高可维护性,并实现并行执行。
如果你想让你的某个库成为一个独立的构建,你应该考虑使用复合构建 (Composite Builds)(即 included builds)。