这是一份非常详细、实用、通俗易懂、权威且全面的 Gradle 全面指南。
目录
- Gradle 是什么?为什么选择 Gradle?
- 1.1 构建工具的概念
- 1.2 Gradle 的核心优势
- 1.3 Gradle vs Maven vs Ant
- Gradle 基础概念
- 2.1 安装与配置
- 2.1.1 安装 SDKMAN! (推荐)
- 2.1.2 手动安装
- 2.1.3 环境变量配置 (
GRADLE_HOME,PATH) - 2.1.4 验证安装 (
gradle -v)
- 2.2 项目结构 (约定优于配置)
- 2.2.1
settings.gradle(.kts)文件 - 2.2.2
build.gradle(.kts)文件 - 2.2.3 源集目录 (
src/main,src/test)
- 2.2.1
- 2.3 Gradle Wrapper (
gradlew,gradlew.bat)- 2.3.1 是什么?为什么重要?
- 2.3.2 生成 Wrapper (
gradle wrapper) - 2.3.3 使用 Wrapper (
./gradlew <task>)
- 2.4 任务 (
Task)- 2.4.1 任务定义 (
task/tasks.register) - 2.4.2 任务类型 (
Copy,Delete,JavaCompile,Exec等) - 2.4.3 任务配置 (闭包 /
doFirst,doLast) - 2.4.4 任务依赖 (
dependsOn) - 2.4.5 任务输入输出 (
inputs,outputs)
- 2.4.1 任务定义 (
- 2.5 依赖管理 (
Dependencies)- 2.5.1 依赖仓库 (
repositories) - 2.5.2 依赖声明 (
dependencies) - 2.5.3 依赖配置 (
implementation,api,compileOnly,runtimeOnly,testImplementation等) - 2.5.4 依赖版本管理 (
versions.toml, 变量) - 2.5.5 依赖冲突解决
- 2.5.1 依赖仓库 (
- 2.6 插件 (
Plugins)- 2.6.1 核心插件 (
java,application,war) - 2.6.2 社区插件 (
com.android.application,org.springframework.boot) - 2.6.3 插件应用 (
plugins {}/apply plugin:) - 2.6.4 插件配置 (闭包)
- 2.6.1 核心插件 (
- 2.7 构建生命周期 (
Build Lifecycle)- 2.7.1 初始化阶段 (
settings.gradle) - 2.7.2 配置阶段 (
build.gradle) - 2.7.3 执行阶段 (
gradle <task>)
- 2.7.1 初始化阶段 (
- 2.1 安装与配置
- Gradle 脚本编写 (DSL)
- 3.1 Groovy DSL vs Kotlin DSL (KTS)
- 3.2 基本语法 (变量、方法、闭包)
- 3.3 项目与任务 API (
project,task) - 3.4 依赖管理 API (
dependencies,configurations) - 3.5 扩展属性 (
ext,extra) - 3.6 多项目构建 (
include,project) - 3.7 增量构建 (
up-to-date检查) - 3.8 构建缓存 (本地、远程)
- 3.9 编写自定义任务类型
- 3.10 编写自定义插件
- 3.10.1 插件 ID (
gradlePlugin) - 3.10.2 插件实现类 (
Plugin) - 3.10.3 扩展对象 (
Extension) - 3.10.4 发布到本地或仓库
- 3.10.1 插件 ID (
- Gradle 最佳实践
- 4.1 优先使用 Kotlin DSL (KTS)
- 4.2 充分利用 Gradle Wrapper
- 4.3 保持构建脚本简洁、可读
- 4.4 使用明确的依赖配置
- 4.5 管理依赖版本 (使用
versions.toml或extra属性) - 4.6 编写可缓存的任务 (定义
inputs/outputs) - 4.7 利用构建缓存
- 4.8 使用
buildSrc或composite builds管理插件和共享逻辑 - 4.9 编写测试
- 4.10 性能调优 (
--profile,--scan,--dry-run) - 4.11 安全性 (
dependency verification)
- Gradle 与 IDE 集成
- 5.1 IntelliJ IDEA / Android Studio
- 5.1.1 导入 Gradle 项目
- 5.1.2 运行 Gradle 任务
- 5.1.3 调试构建脚本
- 5.2 Eclipse
- 5.2.1 Buildship 插件
- 5.2.2 导入和运行
- 5.1 IntelliJ IDEA / Android Studio
- Gradle 高级主题
- 6.1 响应式 API (Provider, Property)
- 6.2 惰性配置 (Lazy Configuration)
- 6.3 配置缓存 (Configuration Cache)
- 6.4 自定义源集 (Source Sets)
- 6.5 构建变体 (Variants - Android, Native)
- 6.6 构建扫描 (
--scan) - 6.7 持续集成集成 (Jenkins, GitLab CI, GitHub Actions)
- 6.8 发布工件到仓库 (
maven-publish,ivy-publish)
- 完整实战案例
- 案例 1:构建一个简单的 Java 应用程序
- 7.1.1 项目结构与设置
- 7.1.2
build.gradle.kts详解 (应用application插件) - 7.1.3 定义主类
- 7.1.4 添加依赖 (JUnit)
- 7.1.5 编写测试
- 7.1.6 运行任务 (
run,test,jar,distZip) - 7.1.7 完整可运行代码
- 案例 2:构建一个多模块项目 (Java Library + Web Application)
- 7.2.1 项目结构 (
settings.gradle.kts) - 7.2.2
core模块 (Java Library) - 7.2.3
web模块 (War Application, 依赖core) - 7.2.4 共享依赖版本管理 (
gradle.properties或buildSrc) - 7.2.5 定义根项目任务 (
build,clean) - 7.2.6 完整可运行代码
- 7.2.1 项目结构 (
- 案例 3:编写一个自定义 Gradle 插件 (Kotlin)
- 7.3.1 创建插件项目 (
build.gradle.kts应用java-gradle-plugin) - 7.3.2 定义插件 ID (
gradlePlugin) - 7.3.3 实现插件逻辑 (
GenerateVersionFilePlugin) - 7.3.4 定义扩展 (
VersionExtension) - 7.3.5 创建自定义任务 (
GenerateVersionFileTask) - 7.3.6 在插件中注册任务
- 7.3.7 发布到本地 Maven 仓库 (
maven-publish) - 7.3.8 在另一个项目中应用自定义插件
- 7.3.9 完整可运行代码
- 7.3.1 创建插件项目 (
- 案例 1:构建一个简单的 Java 应用程序
- 总结与资源
- 8.1 Gradle 官方文档
- 8.2 Gradle 社区论坛
- 8.3 书籍推荐
- 8.4 持续学习
1. Gradle 是什么?为什么选择 Gradle?
1.1 构建工具的概念 想象一下你开发软件的过程:你需要编译源代码、运行测试、打包成可部署的格式(如 JAR, WAR, APK)、管理项目依赖的第三方库、生成文档、部署到服务器等等。手动完成这些步骤不仅繁琐、容易出错,而且在大型项目或多人协作时几乎不可能高效完成。
构建工具(Build Tool)就是用来自动化这些重复性开发任务的软件。它们允许你通过编写脚本(通常是基于特定领域语言 DSL)来定义构建过程。当你运行构建命令时,工具会按照脚本的指示,按顺序执行编译、测试、打包等一系列操作,最终生成所需的软件产物。
1.2 Gradle 的核心优势 Gradle 是一个开源的、功能强大的构建自动化工具。它结合了之前工具(如 Apache Ant 和 Maven)的优点,并引入了许多创新的特性:
- 灵活性 (Flexibility): Gradle 不强制使用固定的项目结构或约定。它提供了一个通用的核心模型,允许你通过 DSL 或 API 精确地定义几乎任何类型的构建过程。你可以轻松定制任务逻辑。
- 基于约定 (Convention over Configuration): 虽然灵活,但 Gradle 为常见项目类型(如 Java, Android)提供了智能的默认设置和约定(如源文件位置)。你可以轻松开始,并在需要时覆盖约定。
- 高性能 (Performance): Gradle 采用了多项优化技术:
- 增量构建 (Incremental Builds): Gradle 跟踪任务的输入和输出。如果输入没有变化且输出存在,任务会被标记为
UP-TO-DATE并跳过执行。只执行必要的任务。 - 构建缓存 (Build Cache): Gradle 可以缓存任务的输出(本地或远程)。当另一个构建(可能在另一台机器上)需要相同的输出时,可以直接从缓存中获取,避免重复计算。
- 并行执行 (Parallel Execution): Gradle 可以在有依赖关系的任务之间并行执行独立的任务链。
- 配置缓存 (Configuration Cache - 实验性/稳定中): Gradle 可以缓存构建脚本的配置结果。对于后续构建,如果脚本没有变化,它可以跳过配置阶段直接进入执行阶段,大幅提升构建速度。
- 增量构建 (Incremental Builds): Gradle 跟踪任务的输入和输出。如果输入没有变化且输出存在,任务会被标记为
- 强大的依赖管理 (Dependency Management): Gradle 内置了强大的依赖管理引擎。它支持从 Maven, Ivy 等仓库下载库文件,并能精确处理传递依赖和解决冲突。依赖配置(如
implementation,api) 提供了清晰的依赖作用域控制。 - 可扩展性 (Extensibility): 你可以轻松编写自己的 Gradle 插件和任务类型来扩展功能。庞大的社区提供了成千上万的插件,覆盖了从 Android 开发到文档生成的广泛领域。
- 多语言支持 (Multi-Language): Gradle 最初主要服务于 JVM 生态(Java, Kotlin, Groovy, Scala),但现在也支持构建 C++, Python, Android, iOS 等多种平台和语言的项目。
- 现代 DSL (DSL): Gradle 提供了两种主要的 DSL:Groovy DSL (语法简洁,动态类型)和 Kotlin DSL(静态类型,IDE 支持更好,类型安全)。Kotlin DSL 正成为官方推荐和社区偏好的选择。
- Gradle Wrapper: 这是一个确保项目使用特定 Gradle 版本运行的工具,解决了开发者和 CI 服务器环境配置不一致的问题。
1.3 Gradle vs Maven vs Ant
- Apache Ant: 最早的流行构建工具之一。它基于 XML 配置,使用 目标(target) 和 任务(task)。Ant 非常灵活,但缺乏依赖管理(需配合 Ivy)和项目结构约定,大型项目配置可能变得冗长复杂。
- Apache Maven: 引入了 约定优于配置 和强大的 依赖管理 ,使用 项目对象模型(POM) XML 文件。Maven 的生命周期和插件机制提供了标准化。然而,其 XML 配置有时显得冗长,自定义复杂逻辑相对困难,扩展性不如 Gradle。
- Gradle: 融合了 Ant 的灵活性和 Maven 的约定/依赖管理优势。它使用更简洁、表达能力更强的 Groovy/Kotlin DSL。增量构建、缓存机制使其性能优异。其插件模型极其强大且易于扩展。Gradle 正在成为许多领域(尤其是 Android、Kotlin 生态)的事实标准。
总结: Gradle 凭借其灵活性、高性能、强大的依赖管理、优秀的扩展性以及现代化的 DSL,成为了当今构建工具领域的领先者。
2. Gradle 基础概念
2.1 安装与配置
2.1.1 安装 SDKMAN! (推荐) SDKMAN! 是一个管理多个 SDK 版本的工具,非常适合安装和管理 Gradle。
bash
# 安装 SDKMAN!
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
# 列出可用的 Gradle 版本
sdk list gradle
# 安装特定版本的 Gradle (例如 8.5)
sdk install gradle 8.5
# 设置默认版本
sdk default gradle 8.5
2.1.2 手动安装
- 访问 Gradle 官网下载页面。
- 下载你需要的版本(通常是完整的二进制分发版,如
gradle-8.5-bin.zip)。 - 解压下载的文件到你选择的目录(例如
/opt/gradle或C:\Gradle)。
2.1.3 环境变量配置 (GRADLE_HOME, PATH)
-
Linux/macOS:
bash# 编辑 ~/.bashrc 或 ~/.zshrc export GRADLE_HOME=/path/to/gradle # 例如 /opt/gradle/gradle-8.5 export PATH=$PATH:$GRADLE_HOME/bin # 使配置生效 source ~/.bashrc # 或 source ~/.zshrc -
Windows:
- 右键点击"此电脑" -> "属性" -> "高级系统设置" -> "环境变量"。
- 在"系统变量"下,点击"新建":
- 变量名:
GRADLE_HOME - 变量值:Gradle 解压目录(例如
C:\Gradle\gradle-8.5)
- 变量名:
- 在"系统变量"中找到
Path变量,点击"编辑"。 - 点击"新建",添加
%GRADLE_HOME%\bin。 - 点击"确定"保存所有更改。
2.1.4 验证安装 (gradle -v) 打开一个新的终端/命令提示符窗口,运行:
bash
gradle -v
如果安装成功,你将看到 Gradle 的版本信息、Groovy 版本、Kotlin DSL 版本、JVM 信息等。
2.2 项目结构 (约定优于配置) 一个标准的 Gradle 项目通常包含以下文件和目录:
my-project/
├── build.gradle(.kts) # 主构建脚本 (Groovy 或 Kotlin)
├── settings.gradle(.kts) # 项目设置脚本 (定义项目名称、包含的子模块)
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar # Wrapper 核心 JAR
│ └── gradle-wrapper.properties # Wrapper 配置 (指定 Gradle 版本)
├── gradlew # Unix/Linux Wrapper 脚本
├── gradlew.bat # Windows Wrapper 脚本
└── src/
├── main/ # 主源代码
│ ├── java/ # Java 主源码
│ ├── kotlin/ # Kotlin 主源码
│ ├── resources/ # 主资源文件 (配置文件、图片等)
│ └── webapp/ # Web 应用资源 (可选, 如 WAR 项目)
└── test/ # 测试源代码
├── java/ # Java 测试源码
├── kotlin/ # Kotlin 测试源码
└── resources/ # 测试资源文件
settings.gradle(.kts)文件: 这是构建过程的入口点。它定义了哪些项目参与此次构建(对于单项目构建,它通常只定义根项目名称;对于多项目构建,它使用include或includeBuild来包含子项目或组合构建)。build.gradle(.kts)文件: 这是项目的主要构建脚本。它应用插件、配置项目、定义任务、声明依赖等。- 源集目录 (
src/main,src/test): 这些是 Gradle 为 Java 和许多其他插件定义的默认源代码位置。你可以根据需要配置自定义源集。
2.3 Gradle Wrapper (gradlew, gradlew.bat)
2.3.1 是什么?为什么重要? Gradle Wrapper(简称 Wrapper)是 Gradle 项目的一部分。它由几个文件组成:
gradlew(Unix shell script)gradlew.bat(Windows batch script)gradle/wrapper/gradle-wrapper.jar(Wrapper 的 JAR 文件)gradle/wrapper/gradle-wrapper.properties(配置文件,指定使用哪个 Gradle 版本)
重要性:
- 版本一致性: 确保项目使用的 Gradle 版本被固定下来。无论开发者本地安装了哪个 Gradle 版本,或者 CI 服务器上安装了哪个版本,项目都将使用 Wrapper 配置中指定的特定版本进行构建。避免了"在我机器上是好的"问题。
- 零安装: 新加入项目的开发者不需要手动安装 Gradle。只需检出代码仓库,运行 Wrapper 脚本 (
./gradlew或gradlew.bat),Wrapper 会自动下载并安装指定版本的 Gradle(如果尚未安装)。
2.3.2 生成 Wrapper (gradle wrapper) 在项目根目录下,运行:
bash
gradle wrapper --gradle-version 8.5 --distribution-type bin
--gradle-version: 指定你希望 Wrapper 使用的 Gradle 版本。--distribution-type:bin(只包含运行时) 或all(包含源码和文档)。通常bin足够。 运行此命令后,项目中会增加gradlew,gradlew.bat,gradle/wrapper/目录及其内容。
2.3.3 使用 Wrapper (./gradlew <task>)
-
在 Linux/macOS 终端中:
bash./gradlew clean build -
在 Windows 命令提示符或 PowerShell 中:
bashgradlew.bat clean build(在 PowerShell 中,你可能需要
.\gradlew.bat或配置执行策略Set-ExecutionPolicy RemoteSigned -Scope CurrentUser)
2.4 任务 (Task) 任务是 Gradle 构建工作的基本单元。每个任务代表构建过程中的一个原子操作,例如编译一些类、复制文件、运行测试、打包 JAR 等。
2.4.1 任务定义 (task / tasks.register) 在构建脚本中定义任务:
-
Groovy DSL:
groovytask myTask { // 旧方式 (仍可用) group = 'Custom' // 可选,任务分组 description = 'This is my custom task' // 可选,任务描述 doLast { // 任务执行时的动作 println 'Hello from myTask!' } } tasks.register('myNewTask') { // 推荐方式 (惰性注册) group = 'Custom' description = 'This is my new task' doLast { println 'Hello from myNewTask!' } } -
Kotlin DSL (KTS):
kotlin// tasks 是 TaskContainer tasks.register("myTask") { // 使用 register (惰性注册) group = "Custom" description = "This is my custom task" doLast { // 任务执行时的动作 println("Hello from myTask!") } } // 旧方式 (不推荐, 因为会在配置阶段立即执行闭包) tasks.create("myOldTask") { doLast { println("Hello from myOldTask!") } }
惰性注册 (register) vs 立即创建 (create/旧 task): register 方法在配置阶段只注册任务,其配置闭包会在任务真正需要执行时才被计算(惰性求值)。这有助于提高配置性能,尤其是在任务数量多或配置复杂时。create 和旧的 task 语法会在配置阶段立即执行闭包。
2.4.2 任务类型 (Copy, Delete, JavaCompile, Exec 等) Gradle 提供了许多预定义的任务类型,封装了常见操作。使用类型可以带来额外的类型安全性和便利的方法:
kotlin
// Kotlin DSL
tasks.register<Copy>("copyFiles") {
from("src/main/resources") // 源目录
into("build/output") // 目标目录
include("*.properties") // 包含的文件模式
}
tasks.register<Delete>("cleanOutput") {
delete("build/output")
}
tasks.register<Exec>("runScript") {
commandLine("python", "myscript.py")
}
2.4.3 任务配置 (闭包 / doFirst, doLast) 任务可以配置其属性,并定义在任务执行时要执行的动作。
- 配置闭包: 在任务注册或创建时提供的闭包主要用于配置任务的属性(如
group,description,inputs,outputs)和添加动作。 - 动作 (
doFirst,doLast): 这些方法用于定义任务执行时实际要做的事情。doLast中的动作会在任务执行阶段最后执行(最常见)。doFirst中的动作会在任务执行阶段最先执行。一个任务可以有多个doFirst和doLast动作,它们按添加顺序执行。
kotlin
tasks.register("complexTask") {
// 配置阶段:设置属性
val message = "Result: "
outputs.dir("build/results")
// 执行阶段:添加动作
doFirst {
println("Starting complexTask...")
}
doLast {
val result = calculateResult() // 假设的函数
println("$message $result")
file("build/results/out.txt").writeText(result.toString())
}
}
2.4.4 任务依赖 (dependsOn) 任务通常不是孤立的,它们之间存在依赖关系。例如,编译任务 (compileJava) 需要在测试任务 (test) 之前运行,因为测试需要编译好的类文件。
kotlin
tasks.register("taskB") {
dependsOn("taskA") // taskB 依赖于 taskA
doLast {
println("TaskB runs after TaskA")
}
}
tasks.register("taskA") {
doLast {
println("TaskA")
}
}
运行 gradle taskB 会先执行 taskA,再执行 taskB。依赖可以是任务名称、任务对象或任务集合。
2.4.5 任务输入输出 (inputs, outputs) 这是 Gradle 实现增量构建和缓存的核心机制。任务应该声明其输入(任务执行所依赖的东西)和输出(任务执行产生的东西)。
- 输入 (
inputs): 可以是文件、目录、属性值。如果输入没有变化,且输出存在,则任务被认为是UP-TO-DATE并被跳过。 - 输出 (
outputs): 通常是任务生成的文件或目录。Gradle 根据输出文件的时间戳和内容来检查任务是否需要重新运行。
kotlin
tasks.register<ProcessTemplates>("processTemplates") {
// 输入:模板文件和模板引擎版本
inputs.files(fileTree("src/main/templates"))
inputs.property("engineVersion", "1.2.3")
// 输出:处理后的文件目录
outputs.dir("build/processed")
// ... 任务实现逻辑 ...
}
定义明确的输入输出是编写高效、可缓存任务的关键。
2.5 依赖管理 (Dependencies) 现代软件项目几乎都依赖外部库。Gradle 提供了强大的机制来声明、解析和管理这些依赖。
2.5.1 依赖仓库 (repositories) 依赖仓库是存放库文件(JAR, AAR, POM 等)的地方。Gradle 需要知道从哪里下载这些库。
kotlin
repositories {
mavenCentral() // 最常用的公共 Maven 仓库
// Maven Local (本地 Maven 仓库 ~/.m2/repository)
mavenLocal()
// 其他公共仓库
maven {
url = uri("https://repo.spring.io/milestone")
}
// 公司私有仓库 (需要认证时)
maven {
url = uri("https://mycompany.com/repo")
credentials {
username = "user"
password = "pass"
}
}
// Ivy 仓库
ivy {
url = uri("https://myivy.com/repo")
patternLayout {
artifact("[organisation]/[module]/[revision]/[type]/[artifact].[ext]")
}
}
}
2.5.2 依赖声明 (dependencies) 在 dependencies {} 块中声明项目所需的依赖。
kotlin
dependencies {
// 声明一个依赖 (implementation 是配置名称)
implementation("org.springframework.boot:spring-boot-starter-web:3.1.0")
// 简写形式 group:artifact:version
implementation("com.google.guava:guava:31.1-jre")
// 依赖本地文件
implementation(files("libs/my-local-lib.jar"))
// 依赖其他项目 (多项目构建中)
implementation(project(":core-module"))
}
2.5.3 依赖配置 (implementation, api, compileOnly, runtimeOnly, testImplementation 等) 依赖配置定义了依赖的作用域和可见性。它们决定了:
- 依赖在哪些类路径上可用(编译、运行时、测试)。
- 依赖是否会被传递给依赖于当前项目的其他项目(传递性)。 常见的配置(由 Java 插件提供):
implementation: 编译和运行时需要,但不会 暴露给使用此项目的其他项目。推荐用于绝大多数依赖。 避免不必要的传递依赖泄露。api: 编译和运行时需要,并且会暴露给使用此项目的其他项目。用于那些构成项目公共 API 一部分的依赖。compileOnly: 只在编译时需要,运行时不需要。常用于注解处理器等。runtimeOnly: 只在运行时需要,编译时不需要。testImplementation: 只在测试的编译和运行时需要。testCompileOnly: 只在测试的编译时需要。testRuntimeOnly: 只在测试的运行时需要。 Android 插件等还会提供更多特定配置。
2.5.4 依赖版本管理 (versions.toml, 变量) 为了集中管理依赖版本,避免在多个地方重复版本号:
-
使用
extra属性或变量 (Groovy):groovyext { springBootVersion = "3.1.0" guavaVersion = "31.1-jre" } dependencies { implementation "org.springframework.boot:spring-boot-starter-web:$springBootVersion" implementation "com.google.guava:guava:$guavaVersion" } -
使用 Kotlin DSL 的
val(KTS):kotlinval springBootVersion by extra("3.1.0") val guavaVersion by extra("31.1-jre") dependencies { implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion") implementation("com.google.guava:guava:$guavaVersion") } -
使用
libs.versions.toml(官方推荐 - Catalog): Gradle 7.0+ 引入了版本目录 (Version Catalog)。-
在
gradle目录下创建libs.versions.toml文件:toml[versions] spring-boot = "3.1.0" guava = "31.1-jre" [libraries] spring-boot-starter-web = { group = "org.springframework.boot", name = "spring-boot-starter-web", version.ref = "spring-boot" } guava = { group = "com.google.guava", name = "guava", version.ref = "guava" } -
在
build.gradle.kts中使用:kotlindependencies { implementation(libs.spring.boot.starter.web) // 类型安全访问器 implementation(libs.guava) }
版本目录提供了更好的集中管理、类型安全和 IDE 支持。
-
2.5.5 依赖冲突解决 当多个依赖(直接或传递)引用了同一个库的不同版本时,就会发生依赖冲突。Gradle 默认会选择最新版本。你可以:
-
查看依赖树:
gradle dependencies或gradle :module:dependencies。 -
强制指定版本:
kotlinconfigurations.all { resolutionStrategy { force("com.google.guava:guava:31.1-jre") // 强制使用此版本 } } -
排除特定依赖:
kotlindependencies { implementation("org.apache.logging.log4j:log4j-core:2.17.2") { exclude(group = "com.fasterxml.jackson.core") // 排除特定 group // exclude(group: "com.fasterxml.jackson.core", module: "jackson-databind") } } -
使用
dependencyInsight:gradle dependencyInsight --dependency guava帮助分析特定依赖的来源。
2.6 插件 (Plugins) 插件是 Gradle 扩展其核心功能的主要方式。它们可以:
- 添加新的任务类型(如
JavaCompile,Test)。 - 配置项目的默认约定(如源集位置)。
- 添加新的依赖配置。
- 集成其他工具。
2.6.1 核心插件 (java, application, war) Gradle 自带了许多核心插件:
java: 提供 Java 项目的基本构建能力(编译、测试、打包 JAR)。application: 构建可执行的 Java 应用程序(包含run任务和分发任务)。war: 构建 Web 应用程序 (WAR) 文件。maven-publish,ivy-publish: 发布项目到 Maven 或 Ivy 仓库。java-library: 比java插件更适合构建供其他项目使用的库(区分api和implementation)。
2.6.2 社区插件 (com.android.application, org.springframework.boot) 庞大的社区提供了海量插件:
com.android.application,com.android.library: 用于构建 Android 应用和库。org.springframework.boot: 简化 Spring Boot 项目的构建。org.jetbrains.kotlin.jvm,org.jetbrains.kotlin.android: 用于 Kotlin JVM 和 Android 开发。org.asciidoctor.jvm.convert: 转换 Asciidoc 文档。- 等等。可以在 Gradle 插件门户 查找。
2.6.3 插件应用 (plugins {} / apply plugin:) 应用插件有两种主要方式:
-
plugins {}块 (推荐): 使用插件 ID。对于核心插件或已发布到 Gradle Plugin Portal 的插件。kotlinplugins { id("java") // 核心插件 id("org.springframework.boot") version "3.1.0" // 社区插件 (需指定版本) id("com.android.application") version "8.1.0" // Android 插件 }这种方式简洁,且 Gradle 能高效处理。
-
apply plugin:(旧方式): 通常在脚本底部使用。对于二进制插件(通过文件路径应用)或旧项目。kotlinapply(plugin = "java") // 或者 apply { plugin("java") }
2.6.4 插件配置 (闭包) 许多插件提供了配置块,可以在构建脚本中设置插件的行为:
kotlin
plugins {
id("java")
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17)) // 设置 Java 工具链版本
}
}
// Spring Boot 插件配置
springBoot {
mainClass.set("com.example.Application") // 设置主类
}
// Android 插件配置 (简化示例)
android {
compileSdk = 33
defaultConfig {
applicationId = "com.example.myapp"
minSdk = 24
targetSdk = 33
versionCode = 1
versionName = "1.0"
}
}
2.7 构建生命周期 (Build Lifecycle) Gradle 构建过程分为三个清晰的阶段:
-
初始化阶段 (Initialization):
- 解析
settings.gradle(.kts)文件。 - 确定哪些项目将参与构建(单项目或多项目)。
- 为每个项目创建
Project实例。 - 执行
settings.gradle(.kts)中的逻辑。
- 解析
-
配置阶段 (Configuration):
- 按需解析项目的
build.gradle(.kts)文件(对于多项目,按依赖关系顺序)。 - 执行构建脚本中的语句(除了任务动作
doLast/doFirst中的代码)。 - 注册任务、配置任务(设置
dependsOn,inputs,outputs等)、应用插件、声明依赖等。 - 注意: 在配置阶段执行的代码应尽量轻量,避免耗时操作(如网络请求、大量文件操作)。这些操作应放在任务动作中(执行阶段)。
- 按需解析项目的
-
执行阶段 (Execution):
- Gradle 确定需要执行的任务(根据命令行参数和任务依赖关系图)。
- 按顺序执行这些任务(考虑依赖关系,并行执行独立任务链)。
- 对于每个任务,执行其
doFirst和doLast动作块中的代码。 - 在此阶段进行实际工作(编译、复制、运行测试等)。
理解生命周期对于编写高效、正确的构建脚本至关重要。例如,在配置阶段读取文件内容通常是个坏主意,因为它会在每次构建时发生(即使任务不需要运行)。应将这些操作移到任务动作中。
3. Gradle 脚本编写 (DSL) Gradle 提供了两种主要的 DSL:Groovy DSL 和 Kotlin DSL (KTS)。本节重点介绍 Kotlin DSL,因为它是官方推荐且日益普及的选择。
3.1 Groovy DSL vs Kotlin DSL (KTS)
- Groovy DSL:
- 语法灵活、简洁(动态类型、闭包、可选括号/分号)。
- 学习曲线相对平缓(对于熟悉 Java/Groovy 的开发者)。
- 历史更悠久,文档和社区资源丰富。
- 动态特性可能导致运行时错误(如拼写错误)。
- IDE 支持(自动补全、导航)不如 KTS 好。
- Kotlin DSL (KTS):
- 静态类型,提供更好的类型安全性和编译时检查。
- 更优秀的 IDE 支持(在 IntelliJ IDEA 中几乎完美)。
- 语法与 Kotlin 一致,对于 Kotlin 开发者更熟悉。
- 构建脚本更易于重构和维护。
- 官方推荐,代表了 Gradle 的未来方向。
- 早期版本性能可能略逊于 Groovy,但现在差距很小。 推荐: 新项目优先选择 Kotlin DSL (KTS)。
3.2 基本语法 (变量、方法、闭包) Kotlin DSL 本质就是 Kotlin 代码,使用了 Gradle 的特定类型和扩展函数。
kotlin
// 变量
val projectVersion = "1.0.0" // 顶层变量 (只读)
var buildCounter by extra(0) // 使用 extra 属性 (可读写)
// 方法 (函数)
fun String.toUpperCaseCustom(): String = this.toUpperCase() // 扩展函数
tasks.register("printVersion") {
doLast {
println("Project Version: $projectVersion")
println("Build Counter: ${extra["buildCounter"]}") // 访问 extra
println("Uppercase: ${"hello".toUpperCaseCustom()}")
}
}
闭包在 Gradle DSL 中非常常见,用于配置对象(任务、依赖、扩展等)。在 KTS 中,它们对应于 lambda 表达式或 SAM 转换。
kotlin
repositories {
mavenCentral() // 这是一个配置闭包 (lambda) 作用于 repositories 对象
}
tasks.register<Copy>("myCopy") {
from("src") // 配置闭包作用于 Copy 任务实例
into("dest")
include("*.txt")
}
3.3 项目与任务 API (project, task)
-
project: 代表当前构建脚本对应的项目。它是构建脚本的默认接收者(this)。你可以使用它来访问项目属性、配置、任务等。kotlinprintln("Project name: ${project.name}") println("Project directory: ${project.projectDir}") -
tasks: 是TaskContainer类型的对象,用于注册、查找和配置任务。kotlinval compileTask = tasks.getByName("compileJava") // 获取任务 tasks.named("test") { // 配置一个已存在的任务 useJUnitPlatform() }
3.4 依赖管理 API (dependencies, configurations)
-
dependencies: 用于声明依赖的块。kotlindependencies { implementation("org.example:lib:1.0") testImplementation("junit:junit:4.13.2") } -
configurations: 代表依赖配置的容器。你可以访问或修改配置。kotlinconfigurations { // 创建一个新的配置 create("myCustomConfiguration") // 配置现有的配置 "implementation" { resolutionStrategy { failOnVersionConflict() // 版本冲突时报错 } } }
3.5 扩展属性 (ext, extra) 用于在项目或任务上存储自定义属性。
-
项目级 (旧
ext/ 新extra):kotlin// 旧方式 (Groovy 风格, 在 KTS 中可用但类型不安全) project.ext["customProperty"] = "value" // 新方式 (KTS 推荐) extra["customProperty"] = "value" // 使用委托属性 (更优雅) val myProp by extra("initialValue") -
任务级:
kotlintasks.register("myTask") { extra["taskSpecific"] = 42 // 任务实例上的额外属性 }
3.6 多项目构建 (include, project) 用于构建包含多个子模块的项目。
-
settings.gradle.kts:kotlinrootProject.name = "my-multi-project" // 设置根项目名称 include(":core") // 包含子项目 'core' (位于根目录下的 'core' 文件夹) include(":web", ":utils") // 包含多个子项目 includeBuild("plugins") // 包含一个组合构建 (位于 'plugins' 文件夹) -
子项目配置 (
build.gradle.kts):kotlin// 在子项目 'core' 的 build.gradle.kts 中 plugins { `java-library` // 核心插件 } dependencies { // 'core' 项目依赖 implementation("org.apache.commons:commons-lang3:3.12.0") } -
项目间依赖:
kotlin// 在 'web' 项目的 build.gradle.kts 中 dependencies { implementation(project(":core")) // 依赖 'core' 项目 } -
根项目配置 (
build.gradle.kts): 可以定义所有子项目的公共配置。kotlin// 在根项目的 build.gradle.kts 中 subprojects { // 配置所有子项目 apply(plugin = "java") repositories { mavenCentral() } dependencies { testImplementation("junit:junit:4.13.2") } } allprojects { // 配置根项目和所有子项目 group = "com.example" version = "1.0.0" }
3.7 增量构建 (up-to-date 检查) 如前所述 (2.4.5),任务通过声明 inputs 和 outputs 来支持增量构建。Gradle 计算这些属性的哈希值(或检查时间戳)。如果输入输出没有变化,任务就是 UP-TO-DATE 的。
3.8 构建缓存 (本地、远程) 构建缓存存储任务输出,以便在后续构建(可能在不同机器上)中重用。
-
本地缓存: 默认启用,存储在
~/.gradle/caches(用户主目录)。 -
远程缓存: 需要配置(如使用 HTTP 或 S3 后端)。团队共享远程缓存可以显著加速 CI 构建和开发者之间的构建。
kotlin// 启用构建缓存 (通常默认启用) buildCache { local { enabled = true } remote<HttpBuildCache> { url = uri("https://mycache.example.com/cache/") credentials { username = "build-user" password = "secret" } } }
任务需要正确声明 outputs 才能被缓存。
3.9 编写自定义任务类型 当预定义任务类型不能满足需求时,可以创建自定义任务类型。
kotlin
// 在 build.gradle.kts 中或 buildSrc/src/main/kotlin 中
abstract class GenerateMarkdownReport : DefaultTask() {
@get:InputFiles // 标记为输入
abstract val inputFiles: ConfigurableFileCollection
@get:OutputDirectory // 标记为输出
abstract val outputDir: DirectoryProperty
@TaskAction // 任务执行的动作
fun generate() {
val outputDirFile = outputDir.get().asFile
outputDirFile.mkdirs()
// ... 处理 inputFiles 生成 Markdown 报告到 outputDir ...
logger.lifecycle("Generated report in ${outputDirFile.absolutePath}")
}
}
// 使用自定义任务类型
tasks.register<GenerateMarkdownReport>("genReport") {
inputFiles.from(fileTree("src/docs"))
outputDir.set(layout.buildDirectory.dir("reports/markdown"))
}
3.10 编写自定义插件 插件封装了可重用的构建逻辑、任务类型和配置。 3.10.1 插件 ID (gradlePlugin) 每个插件都有一个唯一的 ID。 3.10.2 插件实现类 (Plugin<Project>)
kotlin
// 在 buildSrc/src/main/kotlin 或独立插件项目中
import org.gradle.api.Plugin
import org.gradle.api.Project
class MyCustomPlugin : Plugin<Project> {
override fun apply(project: Project) {
// 插件被应用时的逻辑
project.tasks.register("helloPlugin") {
doLast {
println("Hello from MyCustomPlugin!")
}
}
// 可以添加扩展、配置项目、应用其他插件等
}
}
3.10.3 扩展对象 (Extension) 插件可以提供配置选项给用户。
kotlin
abstract class MyPluginExtension(project: Project) {
abstract val message: Property<String> // 使用响应式 API
init {
message.convention("Default Message") // 设置默认值
}
}
class MyCustomPlugin : Plugin<Project> {
override fun apply(project: Project) {
// 创建扩展
val extension = project.extensions.create("myPluginSettings", MyPluginExtension::class.java)
project.tasks.register("printMessage") {
doLast {
println(extension.message.get()) // 使用扩展中的值
}
}
}
}
在构建脚本中配置:
kotlin
plugins {
id("com.example.myplugin") // 假设 ID 是 com.example.myplugin
}
myPluginSettings {
message = "Custom Message from build script"
}
3.10.4 发布到本地或仓库 为了在其他项目中使用,插件需要打包并发布。
-
使用
java-gradle-plugin:kotlin// 在插件项目的 build.gradle.kts 中 plugins { `java-gradle-plugin` `maven-publish` // 用于发布 } gradlePlugin { plugins { create("myPlugin") { // 定义插件 id = "com.example.myplugin" // 插件 ID implementationClass = "com.example.MyCustomPlugin" // 实现类 } } } publishing { repositories { maven { url = uri(layout.buildDirectory.dir("repo")) // 发布到本地目录 // 或发布到远程仓库 // url = uri("https://myrepo.com/releases") // credentials { ... } } } }运行
gradle publish发布插件。
4. Gradle 最佳实践 遵循这些实践可以创建更高效、可维护和可靠的构建。
-
4.1 优先使用 Kotlin DSL (KTS): 利用其类型安全和 IDE 优势。
-
4.2 充分利用 Gradle Wrapper: 确保构建版本一致性。
-
4.3 保持构建脚本简洁、可读: 避免在配置阶段做繁重工作。将复杂逻辑封装在自定义任务类型或插件中。使用注释。
-
4.4 使用明确的依赖配置: 优先使用
implementation而不是旧的不推荐配置 (compile)。正确使用api和implementation控制传递性。 -
4.5 管理依赖版本: 使用
libs.versions.toml或extra属性集中管理版本号。 -
4.6 编写可缓存的任务: 始终为任务定义清晰的
inputs和outputs。确保任务动作是纯函数(输出只由输入决定)。 -
4.7 利用构建缓存: 在团队环境和 CI 中启用并配置远程构建缓存。
-
4.8 使用
buildSrc或composite builds管理插件和共享逻辑:buildSrc: 一个特殊的子项目,其代码会被编译并自动添加到所有其他项目的类路径中。非常适合存放自定义任务类型、插件(仅限项目内部使用)、工具类等。位于项目根目录下的buildSrc文件夹。composite builds: 允许你将一个独立的 Gradle 项目(通常是一个插件项目)包含到另一个构建中,就像它是该项目的一部分一样。使用includeBuild("path/to/plugin-project")在settings.gradle中声明。
-
4.9 编写测试: 为复杂的自定义任务类型和插件编写单元测试或集成测试(使用 Gradle TestKit)。
-
4.10 性能调优:
--profile: 生成构建性能报告 (gradlew build --profile)。--scan: 上传构建扫描到 scans.gradle.com 进行详细分析 (gradlew build --scan)。--dry-run: 模拟任务执行而不实际运行 (gradlew build --dry-run)。- 减少配置时间:避免在配置阶段执行耗时操作。使用惰性 API (
Provider,Property) 和任务惰性注册 (tasks.register)。 - 优化依赖解析:使用固定的依赖版本,避免动态版本 (
+)。使用dependencyLocking。
-
4.11 安全性 (
dependency verification): 启用 Gradle 的依赖验证功能,防止使用被篡改的依赖。配置信任的密钥。kotlin// settings.gradle.kts dependencyVerification { verifyDependencies = true // 启用验证 // 配置模式... }
5. Gradle 与 IDE 集成 Gradle 与主流 IDE 集成紧密。
5.1 IntelliJ IDEA / Android Studio
- 5.1.1 导入 Gradle 项目:
File>New>Project from Existing Sources...选择项目目录下的build.gradle.kts或settings.gradle.kts。选择 "Gradle" 作为模型。 - 5.1.2 运行 Gradle 任务:
- Gradle Tool Window: 在右侧边栏或
View>Tool Windows>Gradle打开。它会列出所有项目和任务。双击任务即可运行。 - Run Configurations: 可以创建自定义运行配置来执行特定任务或命令。
- Gradle Tool Window: 在右侧边栏或
- 5.1.3 调试构建脚本: 在任务名称或构建脚本代码行设置断点。右键点击任务或脚本,选择
Debug 'taskName'或Debug 'build.gradle.kts'。调试器会在执行阶段命中断点。
5.2 Eclipse
- 5.2.1 Buildship 插件: Eclipse 通过 Buildship 插件提供 Gradle 支持。安装此插件 (
Help>Eclipse Marketplace搜索 "Buildship")。 - 5.2.2 导入和运行:
File>Import...>Gradle>Existing Gradle Project。- 指定项目根目录。
- Eclipse 会导入项目并创建相应的项目结构。
- 可以在
Gradle Tasks视图(Window>Show View>Other...>Gradle>Gradle Tasks)中查看和运行任务。
6. Gradle 高级主题 这些主题涉及 Gradle 更深层次的功能和现代 API。
-
6.1 响应式 API (Provider, Property): Gradle 提供了
Provider<T>和Property<T>接口,用于表示值可能尚未计算出来的属性。它们支持惰性求值和值链(变换)。这是编写现代、高效插件和任务的关键。kotlinabstract class MyTask : DefaultTask() { @get:Input abstract val inputFile: RegularFileProperty // Property<RegularFile> @get:OutputFile abstract val outputFile: RegularFileProperty @TaskAction fun run() { val input = inputFile.get().asFile.readText() val processed = process(input) // 处理输入 outputFile.get().asFile.writeText(processed) } } -
6.2 惰性配置 (Lazy Configuration): 利用响应式 API 和任务惰性注册,尽可能推迟配置的计算,直到真正需要时。这可以显著减少大型项目的配置时间。
-
6.3 配置缓存 (Configuration Cache): 这是一个实验性(但正在趋于稳定)的功能。它缓存构建脚本配置阶段的结果。对于后续构建,如果构建脚本、环境等没有变化,Gradle 可以直接从缓存中恢复配置状态,跳过整个配置阶段,直接进入执行阶段。这能带来巨大的性能提升,尤其是在配置复杂的项目中。启用:
bashgradle --configuration-cache ... # 每次运行指定或在
gradle.properties中:propertiesorg.gradle.unsafe.configuration-cache=true # 全局启用注意:配置缓存对构建脚本的编写有更严格的要求(例如,限制某些外部状态访问)。
-
6.4 自定义源集 (Source Sets): 对于非标准项目结构或需要额外源集(如集成测试),可以自定义源集。
kotlinsourceSets { create("integrationTest") { java.srcDir("src/integrationTest/java") resources.srcDir("src/integrationTest/resources") compileClasspath += sourceSets.main.get().output + configurations.testRuntimeClasspath runtimeClasspath += output + compileClasspath } } tasks.register<Test>("integrationTest") { description = "Runs integration tests." group = "verification" testClassesDirs = sourceSets["integrationTest"].output.classesDirs classpath = sourceSets["integrationTest"].runtimeClasspath shouldRunAfter("test") } -
6.5 构建变体 (Variants - Android, Native): Android Gradle Plugin (AGP) 和 Gradle 的 Native 插件利用变体维度(如
buildType- debug/release,productFlavor- free/paid,abi- x86/arm64)来构建同一个应用的不同变体。配置管理变体特定的代码、资源和依赖。 -
6.6 构建扫描 (
--scan): 如前所述,构建扫描提供了构建的深度洞察,帮助诊断性能问题、依赖问题等。上传到 scans.gradle.com。 -
6.7 持续集成集成: Gradle 与所有主流 CI 系统(Jenkins, GitLab CI, GitHub Actions, TeamCity, CircleCI 等)无缝集成。通常只需在 CI 配置中调用
./gradlew build或更具体的任务。利用缓存、并行化和构建扫描优化 CI 构建。 -
6.8 发布工件到仓库: 使用
maven-publish或ivy-publish插件将项目生成的构件(JAR, WAR, POM 等)发布到 Maven 或 Ivy 仓库。kotlinplugins { `maven-publish` } publishing { publications { create<MavenPublication>("myLibrary") { from(components["java"]) // 发布 Java 组件 (JAR + POM) artifactId = "my-lib" // 可选,覆盖默认 artifactId versionMapping { // 处理依赖版本 // ... } } } repositories { maven { name = "myRepo" url = uri(layout.buildDirectory.dir("repo")) // 本地 // url = uri("https://myrepo.com/releases") // 远程 // credentials { ... } } } }运行
gradle publish发布。
7. 完整实战案例
案例 1:构建一个简单的 Java 应用程序
7.1.1 项目结构与设置
hello-gradle/
├── build.gradle.kts
├── settings.gradle.kts
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ └── App.java
│ └── resources/
└── test/
├── java/
│ └── com/
│ └── example/
│ └── AppTest.java
└── resources/
settings.gradle.kts:
kotlin
rootProject.name = "hello-gradle" // 设置项目名称
build.gradle.kts:
kotlin
plugins {
application // 应用 application 插件 (提供 run, distZip 等任务)
}
application {
mainClass.set("com.example.App") // 设置主类
}
repositories {
mavenCentral() // 使用 Maven 中央仓库
}
dependencies {
implementation("com.google.guava:guava:31.1-jre") // 示例依赖
testImplementation("junit:junit:4.13.2") // 测试依赖
}
tasks.named<Test>("test") { // 配置测试任务
useJUnitPlatform() // 使用 JUnit Platform (支持 JUnit 4, 5 等)
}
src/main/java/com/example/App.java:
java
package com.example;
import com.google.common.base.Joiner;
public class App {
public static void main(String[] args) {
String message = Joiner.on(", ").join("Hello", "Gradle", "World!");
System.out.println(message);
}
}
src/test/java/com/example/AppTest.java:
java
package com.example;
import org.junit.Test;
import static org.junit.Assert.*;
public class AppTest {
@Test
public void testAppHasMessage() {
App app = new App();
assertNotNull(app); // 简单示例测试
}
}
7.1.6 运行任务
- 运行应用程序:
./gradlew run(会输出Hello, Gradle, World!) - 运行测试:
./gradlew test(报告测试通过) - 构建 JAR:
./gradlew jar(JAR 文件在build/libs/hello-gradle.jar) - 构建分发 ZIP:
./gradlew distZip(包含 JAR 和启动脚本的 ZIP 在build/distributions/)
案例 2:构建一个多模块项目 (Java Library + Web Application)
7.2.1 项目结构 (settings.gradle.kts)
multi-module/
├── build.gradle.kts
├── settings.gradle.kts
├── core/ (Java Library)
│ ├── build.gradle.kts
│ └── src/...
├── web/ (Web Application)
│ ├── build.gradle.kts
│ └── src/...
└── buildSrc/ (共享逻辑 - 可选)
└── src/main/kotlin/...
settings.gradle.kts:
kotlin
rootProject.name = "multi-module-project"
include(":core", ":web") // 包含 core 和 web 子项目
build.gradle.kts (根项目):
kotlin
// 配置所有子项目的公共设置
subprojects {
apply(plugin = "java") // 所有子项目都是 Java 项目
repositories {
mavenCentral()
}
dependencies {
testImplementation("junit:junit:4.13.2")
}
// 设置 Java 版本
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
}
// 也可以配置特定项目
project(":web") {
apply(plugin = "war") // 只为 web 项目应用 war 插件
}
core/build.gradle.kts:
kotlin
plugins {
`java-library` // 更适合库项目的插件
}
dependencies {
// core 项目依赖
implementation("org.apache.commons:commons-lang3:3.12.0")
}
// ... core 项目其他配置 ...
web/build.gradle.kts:
kotlin
plugins {
war // 应用 war 插件 (已由根项目应用)
}
dependencies {
implementation(project(":core")) // 依赖 core 模块
implementation("javax.servlet:javax.servlet-api:4.0.1") // Servlet API
// ... web 项目其他依赖 ...
}
// ... web 项目其他配置 (如设置 contextPath) ...
7.2.5 定义根项目任务 根项目的 build 任务会依赖所有子项目的 build 任务。clean 同理。 运行 ./gradlew build 会构建所有子项目。运行 ./gradlew :core:build 只构建 core 模块。
案例 3:编写一个自定义 Gradle 插件 (Kotlin)
我们将创建一个插件,它添加一个任务来生成一个包含项目版本信息的文本文件。
7.3.1 创建插件项目 项目结构:
version-plugin/ (独立插件项目)
├── build.gradle.kts
├── settings.gradle.kts
└── src/
└── main/
└── kotlin/
└── com/
└── example/
└── versionplugin/
├── VersionExtension.kt
├── GenerateVersionFilePlugin.kt
└── GenerateVersionFileTask.kt
settings.gradle.kts:
kotlin
rootProject.name = "version-plugin"
build.gradle.kts:
kotlin
plugins {
`java-gradle-plugin` // 用于开发 Gradle 插件
`maven-publish` // 用于发布插件
`kotlin-dsl` // 使用 Kotlin DSL 编写插件
}
repositories {
mavenCentral()
}
dependencies {
implementation(gradleApi()) // 引入 Gradle API
testImplementation("junit:junit:4.13.2")
}
gradlePlugin {
plugins {
create("versionPlugin") { // 定义插件
id = "com.example.versionplugin" // 插件 ID
implementationClass = "com.example.versionplugin.GenerateVersionFilePlugin" // 实现类
}
}
}
publishing {
repositories {
maven {
url = uri(layout.buildDirectory.dir("repo")) // 发布到本地目录
}
}
}
src/main/kotlin/com/example/versionplugin/VersionExtension.kt:
kotlin
package com.example.versionplugin
import org.gradle.api.provider.Property
abstract class VersionExtension {
abstract val outputDir: Property<String> // 输出目录 (相对于项目目录)
init {
outputDir.convention("build/version-info") // 默认值
}
}
src/main/kotlin/com/example/versionplugin/GenerateVersionFileTask.kt:
kotlin
package com.example.versionplugin
import org.gradle.api.DefaultTask
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
import java.io.File
abstract class GenerateVersionFileTask : DefaultTask() {
@get:Input
abstract val projectVersion: Property<String> // 项目版本 (来自 Project)
@get:OutputDirectory
abstract val outputDir: DirectoryProperty // 输出目录
@TaskAction
fun generate() {
val outputDirFile = outputDir.get().asFile
outputDirFile.mkdirs()
val versionFile = File(outputDirFile, "version.txt")
versionFile.writeText("Project Version: ${projectVersion.get()}\n")
logger.lifecycle("Generated version file at: ${versionFile.absolutePath}")
}
}
src/main/kotlin/com/example/versionplugin/GenerateVersionFilePlugin.kt:
kotlin
package com.example.versionplugin
import org.gradle.api.Plugin
import org.gradle.api.Project
class GenerateVersionFilePlugin : Plugin<Project> {
override fun apply(project: Project) {
// 1. 创建扩展对象
val extension = project.extensions.create("versionInfo", VersionExtension::class.java)
// 2. 注册自定义任务
project.tasks.register("generateVersionFile", GenerateVersionFileTask::class.java) {
group = "Versioning"
description = "Generates a file with the project version information"
projectVersion.set(project.provider { project.version.toString() }) // 使用 Project 的 version
outputDir.set(project.layout.projectDirectory.dir(extension.outputDir)) // 使用扩展中的配置
}
}
}
7.3.7 发布到本地 Maven 仓库 在插件项目根目录运行:
bash
./gradlew publish
插件将被发布到 build/repo 目录。
7.3.8 在另一个项目中应用自定义插件 创建一个新的消费者项目。 consumer-project/build.gradle.kts:
kotlin
plugins {
id("com.example.versionplugin") version "1.0.0" // 应用插件 (假设版本是 1.0.0)
}
// 配置插件扩展
versionInfo {
outputDir = "custom-output" // 覆盖默认输出目录
}
// 依赖本地 Maven 仓库 (包含插件)
repositories {
maven {
url = uri("/path/to/version-plugin/build/repo") // 指向插件发布目录
}
}
consumer-project/settings.gradle.kts:
kotlin
rootProject.name = "consumer-project"
7.3.9 运行任务 在消费者项目中运行:
bash
./gradlew generateVersionFile
任务将运行,并在 custom-output/version.txt 文件中写入项目版本信息。
8. 总结与资源
- 8.1 Gradle 官方文档: https://docs.gradle.org/ (最权威、最全面的资源)
- 8.2 Gradle 社区论坛: https://discuss.gradle.org/ (提问和交流)
- 8.3 书籍推荐:
- Gradle in Action (Manning)
- Building and Testing with Gradle (O'Reilly)
- 8.4 持续学习: Gradle 是一个活跃发展的项目。关注官方博客、Release Notes 和社区动态,学习新特性和最佳实践。
这份指南涵盖了 Gradle 的核心概念、使用方法和高级主题,并提供了可直接运行的实战案例。希望它能帮助你掌握 Gradle,构建更高效、可靠的软件项目!