这是一份非常详细、实用、通俗易懂、权威且全面的 Gradle 全面指南。
目录
- 1.1 构建工具的概念
- 1.2 Gradle 的核心优势
- 1.3 Gradle vs Maven vs Ant
- 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.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.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.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.7 构建生命周期 (Build Lifecycle)
- 2.7.1 初始化阶段 (settings.gradle)
- 2.7.2 配置阶段 (build.gradle)
- 2.7.3 执行阶段 (gradle <task>)
- 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 发布到本地或仓库
- 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)
- 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 导入和运行
- 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 完整可运行代码
- 案例 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 完整可运行代码
- 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 可以缓存构建脚本的配置结果。对于后续构建,如果脚本没有变化,它可以跳过配置阶段直接进入执行阶段,大幅提升构建速度。
- 强大的依赖管理 (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。
# 安装 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 手动安装
2.1.3 环境变量配置 (GRADLE_HOME, PATH)
- Linux/macOS: # 编辑 ~/.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) 打开一个新的终端/命令提示符窗口,运行:
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) 在项目根目录下,运行:
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 终端中: ./gradlew clean build
- 在 Windows 命令提示符或 PowerShell 中: gradlew.bat clean build
(在 PowerShell 中,你可能需要 .\\gradlew.bat 或配置执行策略 Set-ExecutionPolicy RemoteSigned -Scope CurrentUser)
2.4 任务 (Task) 任务是 Gradle 构建工作的基本单元。每个任务代表构建过程中的一个原子操作,例如编译一些类、复制文件、运行测试、打包 JAR 等。
2.4.1 任务定义 (task / tasks.register) 在构建脚本中定义任务:
- Groovy DSL: task 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): // 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 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 动作,它们按添加顺序执行。
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) 之前运行,因为测试需要编译好的类文件。
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 根据输出文件的时间戳和内容来检查任务是否需要重新运行。
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 需要知道从哪里下载这些库。
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 {} 块中声明项目所需的依赖。
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): ext {
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): val 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 文件: [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 中使用: dependencies {
implementation(libs.spring.boot.starter.web) // 类型安全访问器
implementation(libs.guava)
}
版本目录提供了更好的集中管理、类型安全和 IDE 支持。
2.5.5 依赖冲突解决 当多个依赖(直接或传递)引用了同一个库的不同版本时,就会发生依赖冲突。Gradle 默认会选择最新版本。你可以:
- 查看依赖树: gradle dependencies 或 gradle :module:dependencies。
- 强制指定版本: configurations.all {
resolutionStrategy {
force("com.google.guava:guava:31.1-jre") // 强制使用此版本
}
} - 排除特定依赖: dependencies {
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:) 应用插件有两种主要方式:
id("java") // 核心插件
id("org.springframework.boot") version "3.1.0" // 社区插件 (需指定版本)
id("com.android.application") version "8.1.0" // Android 插件
}
这种方式简洁,且 Gradle 能高效处理。
// 或者
apply {
plugin("java")
}
2.6.4 插件配置 (闭包) 许多插件提供了配置块,可以在构建脚本中设置插件的行为:
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 的特定类型和扩展函数。
// 变量
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 转换。
repositories {
mavenCentral() // 这是一个配置闭包 (lambda) 作用于 repositories 对象
}
tasks.register<Copy>("myCopy") {
from("src") // 配置闭包作用于 Copy 任务实例
into("dest")
include("*.txt")
}
3.3 项目与任务 API (project, task)
- project: 代表当前构建脚本对应的项目。它是构建脚本的默认接收者(this)。你可以使用它来访问项目属性、配置、任务等。 println("Project name: ${project.name}")
println("Project directory: ${project.projectDir}") - tasks: 是 TaskContainer 类型的对象,用于注册、查找和配置任务。 val compileTask = tasks.getByName("compileJava") // 获取任务
tasks.named("test") { // 配置一个已存在的任务
useJUnitPlatform()
}
3.4 依赖管理 API (dependencies, configurations)
- dependencies: 用于声明依赖的块。 dependencies {
implementation("org.example:lib:1.0")
testImplementation("junit:junit:4.13.2")
} - configurations: 代表依赖配置的容器。你可以访问或修改配置。 configurations {
// 创建一个新的配置
create("myCustomConfiguration")
// 配置现有的配置
"implementation" {
resolutionStrategy {
failOnVersionConflict() // 版本冲突时报错
}
}
}
3.5 扩展属性 (ext, extra) 用于在项目或任务上存储自定义属性。
- 项目级 (旧 ext / 新 extra): // 旧方式 (Groovy 风格, 在 KTS 中可用但类型不安全)
project.ext["customProperty"] = "value"
// 新方式 (KTS 推荐)
extra["customProperty"] = "value"
// 使用委托属性 (更优雅)
val myProp by extra("initialValue") - 任务级: tasks.register("myTask") {
extra["taskSpecific"] = 42 // 任务实例上的额外属性
}
3.6 多项目构建 (include, project) 用于构建包含多个子模块的项目。
- settings.gradle.kts: rootProject.name = "my-multi-project" // 设置根项目名称
include(":core") // 包含子项目 'core' (位于根目录下的 'core' 文件夹)
include(":web", ":utils") // 包含多个子项目
includeBuild("plugins") // 包含一个组合构建 (位于 'plugins' 文件夹) - 子项目配置 (build.gradle.kts): // 在子项目 'core' 的 build.gradle.kts 中
plugins {
`java-library` // 核心插件
}dependencies {
// 'core' 项目依赖
implementation("org.apache.commons:commons-lang3:3.12.0")
} - 项目间依赖: // 在 'web' 项目的 build.gradle.kts 中
dependencies {
implementation(project(":core")) // 依赖 'core' 项目
} - 根项目配置 (build.gradle.kts): 可以定义所有子项目的公共配置。 // 在根项目的 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 构建和开发者之间的构建。 // 启用构建缓存 (通常默认启用)
buildCache {
local {
enabled = true
}
remote<HttpBuildCache> {
url = uri("https://mycache.example.com/cache/")
credentials {
username = "build-user"
password = "secret"
}
}
}
任务需要正确声明 outputs 才能被缓存。
3.9 编写自定义任务类型 当预定义任务类型不能满足需求时,可以创建自定义任务类型。
// 在 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>)
// 在 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) 插件可以提供配置选项给用户。
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()) // 使用扩展中的值
}
}
}
}
在构建脚本中配置:
plugins {
id("com.example.myplugin") // 假设 ID 是 com.example.myplugin
}
myPluginSettings {
message = "Custom Message from build script"
}
3.10.4 发布到本地或仓库 为了在其他项目中使用,插件需要打包并发布。
- 使用 java-gradle-plugin: // 在插件项目的 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 的依赖验证功能,防止使用被篡改的依赖。配置信任的密钥。 // 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: 可以创建自定义运行配置来执行特定任务或命令。
- 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> 接口,用于表示值可能尚未计算出来的属性。它们支持惰性求值和值链(变换)。这是编写现代、高效插件和任务的关键。 abstract 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 可以直接从缓存中恢复配置状态,跳过整个配置阶段,直接进入执行阶段。这能带来巨大的性能提升,尤其是在配置复杂的项目中。启用: gradle –configuration-cache … # 每次运行指定
或在 gradle.properties 中: org.gradle.unsafe.configuration-cache=true # 全局启用
注意:配置缓存对构建脚本的编写有更严格的要求(例如,限制某些外部状态访问)。 - 6.4 自定义源集 (Source Sets): 对于非标准项目结构或需要额外源集(如集成测试),可以自定义源集。 sourceSets {
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 仓库。 plugins {
`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:
rootProject.name = "hello-gradle" // 设置项目名称
build.gradle.kts:
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:
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:
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:
rootProject.name = "multi-module-project"
include(":core", ":web") // 包含 core 和 web 子项目
build.gradle.kts (根项目):
// 配置所有子项目的公共设置
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:
plugins {
`java-library` // 更适合库项目的插件
}
dependencies {
// core 项目依赖
implementation("org.apache.commons:commons-lang3:3.12.0")
}
// … core 项目其他配置 …
web/build.gradle.kts:
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:
rootProject.name = "version-plugin"
build.gradle.kts:
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:
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:
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:
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 仓库 在插件项目根目录运行:
./gradlew publish
插件将被发布到 build/repo 目录。
7.3.8 在另一个项目中应用自定义插件 创建一个新的消费者项目。 consumer-project/build.gradle.kts:
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:
rootProject.name = "consumer-project"
7.3.9 运行任务 在消费者项目中运行:
./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,构建更高效、可靠的软件项目!

