Gradle
Table of Contents
1. Gradle 简介
Gradle is an open source build automation system that builds upon the concepts of Apache Ant and Apache Maven.
Gradle 不使用 XML 文件(Ant/Maven 均使用 XML 文件)来声明项目的配置,而是使用 domain-specific language (DSL),目前 Gradle 支持两种 DSL:
参考:
Gradle Website: https://gradle.org/
Gradle User Guide: https://docs.gradle.org/current/userguide/userguide.html
1.1. Gradle 项目的目录结构
Gradle 项目的目录结构如下:
├── .gradle (1) │ ├── 4.8 (2) │ ├── 4.9 (2) │ └── ⋮ ├── build (3) ├── gradle │ └── wrapper (4) ├── gradle.properties (5) ├── gradlew (6) ├── gradlew.bat (6) ├── settings.gradle.kts (7) ├── subproject-one (8) | └── build.gradle.kts (9) ├── subproject-two (8) | └── build.gradle.kts (9) └── ⋮
相关文件的说明如下:
(1) Project-specific cache directory generated by Gradle.
(2) Version-specific caches (e.g., to support incremental builds).
(3) The build directory of this project into which Gradle generates all build artifacts.
(4) Contains the JAR file and configuration of the Gradle Wrapper.
(5) Project-specific Gradle configuration properties.
(6) Scripts for executing builds using the Gradle Wrapper.
(7) The project’s settings file where the list of subprojects is defined.
(8) Usually, a project is organized into one or multiple subprojects.
(9) Each subproject has its own Gradle build script.
参考:https://docs.gradle.org/current/userguide/directory_layout.html#dir:project_root
1.1.1. 设置 proxy
如果想对所有的 gradle 项目设置代理,可以在 GRADLE_USER_HOME(为目录 “~/.gradle/”)下新建文件 gradle.properties,增加配置项:
systemProp.http.proxyHost=127.0.0.1 systemProp.http.proxyPort=10384 systemProp.https.proxyHost=127.0.0.1 systemProp.https.proxyPort=10384
如果只是对单个项目设置代理,则仅修改项目根目录中的 gradle.properties 文件即可。
参考:https://docs.gradle.org/current/userguide/networking.html
1.2. 实例:用 Gradle 编译 Java 程序
下面以一个简单的 Hello world 工程(你也可以使用命令 gradle init --type java-application
来自动生成 Hello world 工程)来介绍 Gradle 的基本使用。
这里假定你的工程源码已经存在(需要符合 Maven 的规范,也就是不同资源分别放在约定目录 src/main/java, src/main/resources, src/test/java and src/test/resources 等中),其目录结构和内容如下:
$ find /home/cig01/java-demo /home/cig01/java-demo /home/cig01/java-demo/src /home/cig01/java-demo/src/main /home/cig01/java-demo/src/main/java /home/cig01/java-demo/src/main/java/App.java $ cat ./src/main/java/App.java public class App { public static void main(String[] args) { System.out.println("Hello world"); } }
首先,在当前目录中新建文件 build.gradle
,其内容为:
apply plugin: 'java'
然后,执行 gradle build
命令即可开始编译。如:
$ gradle build :compileJava :processResources NO-SOURCE :classes :jar :assemble :compileTestJava NO-SOURCE :processTestResources NO-SOURCE :testClasses UP-TO-DATE :test NO-SOURCE :check UP-TO-DATE :build BUILD SUCCESSFUL Total time: 1.962 secs
编译完成后,会生成 jar 包“build/libs/java-demo.jar”(包的名字 java-demo 默认为当前目录名字)。测试运行如下:
$ java -cp build/libs/java-demo.jar App Hello world
说明:使用命令 gradle run
可更方便地执行编译后的程序。不过要求我们使用插件 application,且配置 mainClassName 为主程序类名。即把文件 build.gradle
修改为:
apply plugin: 'java' apply plugin: 'application' mainClassName = 'App'
这时,运行 gradle run
可执行程序 App。
$ gradle run :compileJava UP-TO-DATE :processResources NO-SOURCE :classes UP-TO-DATE :run Hello world BUILD SUCCESSFUL Total time: 1.846 secs
上面的输出中有很多是 gradle 的输出,查找程序 App 的输出(字符串“Hello world”)不方便。可以使用 -q
选项来禁止 gradle 输出,这样可更快捷地查看到程序 App 的输出。如:
$ gradle -q run Hello world
2. Gradle 基础
2.1. 构建的三个阶段(初始化/配置/执行)
Gradle 的构建过程可以分为下面三个阶段:
- Initialization
- Detects the settings.gradle(.kts) file.
- Creates a Settings instance.
- Evaluates the settings file to determine which projects (and included builds) make up the build.
- Creates a Project instance for every project.
- Detects the settings.gradle(.kts) file.
- Configuration
- Evaluates the build scripts, build.gradle(.kts), of every project participating in the build.
- Creates a task graph for requested tasks.
- Evaluates the build scripts, build.gradle(.kts), of every project participating in the build.
- Execution
- Schedules and executes the selected tasks.
- Dependencies between tasks determine execution order.
- Execution of tasks can occur in parallel.
- Schedules and executes the selected tasks.
参考:https://docs.gradle.org/current/userguide/build_lifecycle.html#sec:build_phases
2.2. settings.gradle 文件
2.3. build.gradle 文件
2.4. Task 介绍(gradle 命令行基本用法)
Gradle 中,Task 是不可分的最小工作单元,用于执行构建工作(比如编译、打包、生成 javadoc、发布等等)。
gradle 的命令行用法为: gradle [option...] [task...]
。比如 gradle compile test
就是执行任务 compile 和 test。
任务之间可以有依赖。比如下面的 build.gradle 文件中定义了如图 1 所示的任务依赖关系。
task compile { doLast { println 'compiling source' } } task compileTest(dependsOn: compile) { //这里设置了任务compileTest依赖于任务compile doLast { println 'compiling unit tests' } } task test(dependsOn: [compile, compileTest]) { //这里设置了任务test依赖于任务compile和compileTest doLast { println 'running unit tests' } } task dist(dependsOn: [compile, test]) { //这里设置了任务dist依赖于任务compile和test doLast { println 'building the distribution' } }
Figure 1: Task dependencies
任务之间有依赖于,先执行依赖。比如执行命令 gradle dist test
时,会依次执行任务 compile,compileTest,test,dist(每个任务最多会执行一次)。测试如下:
$ gradle dist test :compile compiling source :compileTest compiling unit tests :test running unit tests :dist building the distribution BUILD SUCCESSFUL Total time: 1 secs
每个任务最多执行一次。 如 gradle test test
和 gradle test
是相同的。
参考:https://docs.gradle.org/current/userguide/tutorial_gradle_command_line.html
2.4.1. 排除某个任务的执行(-x)
使用选项 -x
可以排除某个任务的执行。以图 1 中的任务为例, gradle dist -x test
会排除任务 test(及 test 的依赖)的执行:
$ gradle dist -x test :compile compiling source :dist building the distribution BUILD SUCCESSFUL Total time: 1 secs
2.4.2. 任务名的简写
只要不冲突,任务名可以简写。如下面 4 种用法效果相同:
gradle d gradle di gradle dis gradle dist
此外,如果任务名是 Camel case 形式,只要不冲突,对单词也可以进行简写。如下面 3 种用法效果相同:
gradle compileTest gradle compTest gradle cT
2.4.3. 强制重新执行任务(--rerun-tasks)
默认 gradle 是增量编译的,如果任务的输入文件没有修改就不会重新编译。可以通过指定选项 --rerun-tasks
来使 gradle 总是执行指定任务。
2.4.4. 查询任务列表(gradle tasks)
通过执行 gradle tasks
可以查询当前项目中所有的任务。
3. Gradle 插件简介
Gradle 的核心能做的事件非常少,所有有用特性(比如编译 Java 代码等)都由 Gradle 插件来提供。
一个 Gradle 插件能够:
(1) 在 Project 中添加新 Task;
(2) 为新加入的任务提供默认配置(如约定源文件默认位置);
(3) 加入新的属性;
(4) 为项目加入新的依赖。
对于简单的任务,你不用自己编写插件,Gradle 提供了一些 Standard plugins ,下面是它们的不完整列表:
Plugin Id | Automatically applies | Works with | Description |
---|---|---|---|
java | java-base | - | Adds Java compilation, testing and bundling capabilities to a project. |
groovy | java, groovy-base | - | Adds support for building Groovy projects. |
scala | java, scala-base | - | Adds support for building Scala projects. |
antlr | java | - | Adds support for generating parsers using Antlr. |
application | java, distribution | - | Adds tasks for running and bundling a Java project as a command-line application. |
ear | - | java | Adds support for building J2EE applications. |
jetty | war | - | Deploys your web application to a Jetty web container embedded in the build. |
osgi | java-base | java | Adds support for building OSGi bundles. |
war | java | - | Adds support for assembling web application WAR files. |
要使用插件(假设插件名为 foo),在文件 build.gradle
中使用 apply plugin: 'foo'
即可。
3.1. 插件 JavaPlugin(java)简介
JavaPlugin 是 Gradle 中非常基础的一个插件,在文件 build.gradle
中增加下面内容即可使用它。
apply plugin: 'java' // apply plugin: org.gradle.api.plugins.JavaPlugin // 和上一行相同 // apply plugin: JavaPlugin // 和上一行相同
JavaPlugin 增加了下面 Tasks 到你的工程中。
Task name | Depends on | Type | Description |
---|---|---|---|
compileJava |
All tasks which produce the compile classpath. This includes the jar task for project dependencies included in the compile configuration. | JavaCompile | Compiles production Java source files using javac. |
processResources |
- | Copy | Copies production resources into the production resources directory. |
classes |
The compileJava task and the processResources task. Some plugins add additional compilation tasks. | Task | Assembles the production classes and resources directories. |
compileTestJava |
compile, plus all tasks which produce the test compile classpath. | JavaCompile | Compiles test Java source files using javac. |
processTestResources |
- | Copy | Copies test resources into the test resources directory. |
testClasses |
compileTestJava task and processTestResources task. Some plugins add additional test compilation tasks. | Task | Assembles the test classes and resources directories. |
jar |
compile | Jar | Assembles the JAR file |
javadoc |
compile | Javadoc | Generates API documentation for the production Java source, using Javadoc |
test |
compile, compileTest, plus all tasks which produce the test runtime classpath. | Test | Runs the unit tests using JUnit or TestNG. |
uploadArchives |
The tasks which produce the artifacts in the archives configuration, including jar. | Upload | Uploads artifacts in the archives configuration, including the JAR file. |
clean |
- | Delete | Deletes the project build directory. |
cleanTaskName |
- | Delete | Deletes files created by specified task. cleanJar will delete the JAR file created by the jar task, and cleanTest will delete the test results created by the test task. |
JavaPlugin 默认使用下面的工程结构:
Directory | Meaning |
---|---|
src/main/java | Production Java source |
src/main/resources | Production resources |
src/test/java | Test Java source |
src/test/resources | Test resources |
src/sourceSet/java | Java source for the given source set |
src/sourceSet/resources | Resources for the given source set |
参考:https://docs.gradle.org/current/userguide/java_plugin.html
3.1.1. 实例:修改工程默认结构
如果你的 java 源码在“scr/java”中,而不是默认的“src/main/java”中,你可以在文件 build.gradle
增加下面配置:
sourceSets { main { java { srcDirs = ['src/java'] } } }
4. Dependency Management
Maven repository 中的库都可以引入到 Gradle 中。在项目的 build.gradle 文件中配置即可。下面是一个简单例子:
apply plugin: 'java' repositories { mavenCentral() } dependencies { compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final' testCompile group: 'junit', name: 'junit', version: '4.+' }
参考:https://docs.gradle.org/current/userguide/artifact_dependencies_tutorial.html
5. Tips
5.1. 指定 Java 环境
如果编译项目时要显式地指定 Java 环境,可以采用下面任一种方法。
方法 1、在 gradle.properties 中指定:
org.gradle.java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home
方法 2、在运行时指定:
./gradlew build -Dorg.gradle.java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home
参考:https://stackoverflow.com/questions/18487406/how-do-i-tell-gradle-to-use-specific-jdk-version