写点什么

gradle 中的 build script 详解

发布于: 2021 年 02 月 13 日

简介

build.gradle 是 gradle 中非常重要的一个文件,因为它描述了 gradle 中可以运行的任务,今天本文将会带大家体验一下如何创建一个 build.gradle 文件和如何编写其中的内容。

project 和 task

gradle 是一个构建工具,所谓构建工具就是通过既定的各种规则,将原代码或者原文件通过一定的 task 处理过后,打包生成目标文件的步骤。

所以我们在 gradle 中有两个非常重要的概念,分别是项目和任务。

每一个 gradle 的构建任务可以包含一个或者多个项目,项目可以有多种类型,比如是一个 web 项目或者一个 java lib 项目等。为了实现 project 要完成的目标,需要定义一个个的 task 来辅助完成目标。

task 主要用来执行特定的任务,比如编译 class 文件,打包成 jar,生成 javadoc 等等。

一个例子

接下来我们使用一个具体的例子来讲解一下,gradle 到底是怎么用的。

首先我们创建一个新的 project 目录:

$ mkdir gradle-test$ cd gradle-test
复制代码

gradle 提供了一个 init 方法,来方便的创建 gradle 项目的骨架,我们用下看:

gradle initStarting a Gradle Daemon (subsequent builds will be faster)
Select type of project to generate: 1: basic 2: application 3: library 4: Gradle pluginEnter selection (default: basic) [1..4] 2
Select implementation language: 1: C++ 2: Groovy 3: Java 4: Kotlin 5: Scala 6: SwiftEnter selection (default: Java) [1..6] 3
Split functionality across multiple subprojects?: 1: no - only one application project 2: yes - application and library projectsEnter selection (default: no - only one application project) [1..2] 1
Select build script DSL: 1: Groovy 2: KotlinEnter selection (default: Groovy) [1..2] 1
Select test framework: 1: JUnit 4 2: TestNG 3: Spock 4: JUnit JupiterEnter selection (default: JUnit 4) [1..4] 1
Project name (default: gradle-test):Source package (default: gradle.test):
> Task :initGet more help with your project: https://docs.gradle.org/6.7/samples/sample_building_java_applications.html
BUILD SUCCESSFUL in 45s2 actionable tasks: 2 executed
复制代码

按照你的需要,经过一系列的选择之后,就可以生成一个基本的 gradle 项目了。

我们看下生成的文件和目录:

.├── app│   ├── build.gradle│   └── src│       ├── main│       │   ├── java│       │   │   └── gradle│       │   │       └── test│       │   │           └── App.java│       │   └── resources│       └── test│           ├── java│           │   └── gradle│           │       └── test│           │           └── AppTest.java│           └── resources├── gradle│   └── wrapper│       ├── gradle-wrapper.jar│       └── gradle-wrapper.properties├── gradlew├── gradlew.bat└── settings.gradle
14 directories, 8 files
复制代码

其中 gradle-wrapper 是帮你自动设置和安装 gradle 的工具,同时它还提供了 gradlew 和 gradlew.bat 这两个执行文件,用来执行 gradle 的任务。

我们主要看其中的两个配置文件,settings.gradle 和 build.gradle。

settings.gradle 中配置的是 gradle 中要 build 的项目信息:

rootProject.name = 'gradle-test'include('app')
复制代码

上面的例子中,rootProject.name 指定了项目的名字,include(‘app’)表示需要引入一个叫做 app 的子项目,这个子项目中包含着实际的要打包的内容。

再看一下 app 中的 build.gradle 文件:

plugins {    // Apply the application plugin to add support for building a CLI application in Java.    id 'application'}
repositories { // Use JCenter for resolving dependencies. jcenter()}
dependencies { // Use JUnit test framework. testImplementation 'junit:junit:4.13'
// This dependency is used by the application. implementation 'com.google.guava:guava:29.0-jre'}
application { // Define the main class for the application. mainClass = 'gradle.test.App'}
复制代码

很简单,指定了插件,仓库地址,依赖包和应用程序的 main class 路径。

一切准备好之后,我们就可以进行构建和运行了。

有两种方式来运行,一种方式就是使用系统自带的 gradle 命令,一种方式就是使用刚刚 gradle 为你生成的 gradlew。

gradle run
> Configure project :appRepository {repo.url} replaced byREPOSITORY_URL .
> Task :app:runHello World!
复制代码


gradle build
> Configure project :appRepository {repo.url} replaced byREPOSITORY_URL .
BUILD SUCCESSFUL in 2s7 actionable tasks: 6 executed, 1 up-to-date
复制代码

你还可以带上 –scan 参数将 build 上传到 gradle scan 中,得到更加详细的构建分析:

./gradlew build --scan
BUILD SUCCESSFUL in 0s7 actionable tasks: 7 executed
Publishing a build scan to scans.gradle.com requires accepting the Gradle Terms of Service defined at https://gradle.com/terms-of-service.Do you accept these terms? [yes, no] yes
Gradle Terms of Service accepted.
Publishing build scan...https://gradle.com/s/5u4w3gxeurtd2
复制代码

task 详细讲解

上面的例子中,我们使用的都是 gradle 默认的 tasks,并没有看到自定义 task 的使用,接下来我们将会探讨一下,如何在 build.gradle 编写自己的 task。

这里我们使用的 groovy 来编写 build.gradle,所以我们可以像运行代码一样来运行它。

task 脚本

先创建一个非常简单的 task:

task hello {    doLast {        println 'Hello www.flydean.com!'    }}
复制代码

上面定义了一个名叫 hello 的 task,并且会在执行最后输出 “Hello www.flydean.com!”。

我们这样运行:

gradle -q helloHello www.flydean.com!
复制代码

-q 的意思是悄悄的执行,将会忽略 gradle 自身的 log 信息。我们把要执行的 task 名字写在 gradle 后面就可以了。

如果你熟悉 ant 命令的话,可以看到 gradle 的 task 和 ant 很类似,不过更加的强大。

因为是 groovy 脚本,所以我们可以在其中执行代码:

task upper {    doLast {        String someString = 'www.flydean.com'        println "Original: someString"        println "Upper case:{someString.toUpperCase()}"    }}
复制代码

运行结果:

> gradle -q upperOriginal: www.flydean.comUpper case: WWW.FLYDEAN.COM
复制代码

或者执行 times 操作:

task count {    doLast {        4.times { print "$it " }    }}
复制代码


> gradle -q count0 1 2 3
复制代码

task 依赖

gradle 中的一个 task 可以依赖其他的 task:

task hello {    doLast {        println 'Hello www.flydean.com!'    }}task intro {    dependsOn hello    doLast {        println "I'm flydean"    }}
复制代码

上面两个 task 的顺序是无关的,可以依赖的写在前面,被依赖的写在后面,或者反过来都成立。

动态 task

除了静态的 task 之外,我们还可以通过代码来动态创建 task:

4.times { counter ->    task "taskcounter" {        doLast {            println "I'm task numbercounter"        }    }}
复制代码


> gradle -q task1I'm task number 1
复制代码

我们还可以将 task 看做成为一个对象,调用 gradle 的 api 进行操作:

4.times { counter ->    task "taskcounter" {        doLast {            println "I'm task numbercounter"        }    }}task0.dependsOn task2, task3
复制代码

上面的例子中,我们调用 API 手动创建了 task 之间的依赖关系:

> gradle -q task0I'm task number 2I'm task number 3I'm task number 0
复制代码

还可以 task 之间的属性调用:

task myTask {    ext.myProperty = "www.flydean.com"}
task printTaskProperties { doLast { println myTask.myProperty }}
复制代码

默认 task

如果不想每次都在调用 gradle 命令的时候手动指定某个具体的 task 名字,我们可以使用 defaultTasks:

defaultTasks 'clean', 'run'
task clean { doLast { println 'Default Cleaning!' }}
task run { doLast { println 'Default Running!' }}
task other { doLast { println "I'm not a default task!" }}
复制代码

上面的代码执行 gradle 和 gradle clean run 是相当的。

build script 的外部依赖

既然 build script 可以用 groovy 代码来编写,那么如果我们想要在 build script 中使用外部的 jar 包怎么办呢?

这个时候,我们可以将外部依赖放到 buildscript()方法中,后面的 task 就可以使用引入的依赖了:

import org.apache.commons.codec.binary.Base64
buildscript { repositories { mavenCentral() } dependencies { classpath group: 'commons-codec', name: 'commons-codec', version: '1.2' }}
task encode { doLast { def byte[] encodedString = new Base64().encode('hello world\n'.getBytes()) println new String(encodedString) }}
复制代码

上面的例子中,encode 使用了一个外部的依赖包 Base64,这个依赖包是在 buildscript 方法中引入的。

本文已收录于 http://www.flydean.com/gradle-build-script/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!


发布于: 2021 年 02 月 13 日阅读数: 64
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
gradle中的build script详解