本文主要介绍 Gradle 的一些基础知识与原理。
本文主要包括以下内容:
Gradle 的前世今生
前世
1. 构建工具的进化:Ant, Maven, Gradle
今生
1. Gradle 到底是什么?
2. Gradle Wrapper 是什么?
3. AGP 到底是什么?
4. gradle.properties 是什么?
5. settings.gradle 是什么?
6. build.gradle 是什么?
7. Gradle 生命周期是怎样的?
8. build.gradle 配置详解。
首先来回答一个问题吧:什么是 Gradle
呢?我理解的话,就是一 “构建(build)” 项目的工具,常见的使用场景的呢,就是咱们编写的 Java
代码、C++
代码和资源文件经过编译、链接等操作,最终打包成一个 apk
。
下面咱们先来了解一下,什么是构建工具,它又是怎么衍化的。
一、构建工具的进化:ant, maven, gradle
我们要写一个 Java
程序,一般的步骤也就是编译,测试,打包。这个构建的过程,如果文件比较少,我们可以手动使用 java, javac, jar
命令去做这些事情。但当工程越来越大,文件越来越多,这个事情就不是那么地令人开心了。因为这些命令往往都是很机械的操作。但是我们可以把机械的东西交给机器去做。
这时,构建工具就应运而生了。
1. Apache Ant
在 linux
上,有一个工具叫 make
。我们可以通过编写 Makefile
来执行工程的构建。windows
上相应的工具是 nmake
。这个工具写起来比较罗嗦,所以从早期,Java
的构建就没有选择它,而是 Apach
基金组织新建的一个叫做 Ant
的构建项目工具。Ant
的思想和 makefile
比较像。定义一个任务,规定它的依赖,然后就可以通过 Ant
来执行这个任务了。我们通过例子看一下。下面列出一个 Ant
工具所使用的 build.xml
:
可以看到 Ant
的构建脚本还是比较清楚的。Ant
定义了五个任务:init, compile, build, test, clean
,每个任务做什么都定义清楚了。打包之前要先编译,所以通过 depends
来指定依赖的路径。如果在命令行里执行 ant build
,那就会先执行compile
,而 compile
又依赖于 init
,所以就会先执行 init
。看起来很合理,对吧?有了这个东西以后,我们只要一条命令:
ant test
就可以执行编程,打包,测试了。为开发者带来了很大的便利。
其实在 Android Studio
出来之前,我们在 eclipse
中也有构建项目的概念,当时用的就是 Ant
,google
给我们集成到 SDK
中了,我们当初之所以能把一大堆 Java
代码和图片打包成一个 apk
主要靠它。
但是 Ant
有一个很致命的缺陷,那就是没办法管理依赖。我们一个工程,要使用很多第三方工具,不同的工具,不同的版本。每次打包都要自己手动去把正确的版本拷到 lib
下面去,不用说,这个工作既枯燥还特别容易出错。为了解决这个问题,我们来看 Maven
如何完成同样的工作。
2. Apache Maven
Maven
最核心的改进就在于提出仓库这个概念,它抛弃了 Ant
中通过 target
定义任务的做法。我们可以把所有依赖的包,都放到仓库里去,在我们的工程管理文件里,标明我们需要什么什么包,什么什么版本。在构建的时候,Maven
就自动帮我们把这些包打到我的包里来了。我们再也不用操心着自己去管理几十上百个 jar
文件了。
Maven
提出,要给每个包都标上坐标,这样,便于在仓库里进行查找。所以,使用 Maven
构建和发布的包都会按照这个约定定义自己的坐标。例如:
pom.xml
[html] view
plaincopy
4.0.0
com.technologyconversations
java-build-tools
jar
1.0
junit
junit
4.11
org.hamcrest
hamcrest-all
1.3
org.apache.maven.plugins
maven-compiler-plugin
2.3.2
上面,定义了用到包的坐标是 junit:junit:4.11
,而我的工程要依赖 junit:junit:4.10
。那么 maven
就会自动去帮我把 junit
打包进来。如果我本地没有 junit
,maven
还会帮我去网上下载。下载的地方就是远程仓库,我们可以通过 repository
标签来指定远程仓库。
通过执行下面的命令来运行 maven goal
生成 jar
文件。
mvn package
主要的区别在于 Maven
不需要指定执行的操作。没有创建 task
,而是设置了一些参数(有哪些依赖,用哪些插件…)。Ant
和 Maven
的 xml
文件都会随时间而变大,为了说明这一点,我们加入 CheckStyle,FindBugs
和 PMD
插件来进行静态检查,三者是 Java
项目中使用很普遍的的工具。我们希望将所有静态检查的执行以及单元测试一起作为一个单独的目标验证。当然我们还应该指定自定义的 checkstyle
配置文件的路径并且确保错误时能够提示。更新后的 Maven
代码如下:
pom.xml
[plain] view
plaincopy
org.apache.maven.plugins
maven-checkstyle-plugin
2.12.1
config/checkstyle/checkstyle.xml
true
true
check
org.codehaus.mojo
findbugs-maven-plugin
2.5.4
check
org.apache.maven.plugins
maven-pmd-plugin
3.1
check
通过执行下面的命令来运行 maven goal
,包括单元测试,静态检查,如 CheckStyle,FindBugs 和 PMD
。
mvn verify
我们需要写很多 xml
来进行基本的常用的任务。在实际项目中有更多的依赖和 task
,Maven
的 pom.xml
很容易就有成百上千行的配置。
既然有缺点,那肯定也有优点,Maven
的主要优点是引入了生命周期的概念。这个问题我们暂时先放一下。
Maven
已经很好了,可以满足绝大多数工程的构建。那为什么我们还需要新的构建工具呢?依赖管理不能很好地处理相同库文件不同版本之间的冲突;xml
作为配置文件的格式有严格的结构层次和标准,定制化目标很困难;因为 Maven
主要聚焦于依赖管理,实际上用 Maven
很难写出复杂、定制化的构建脚本,甚至不如 Ant
;用xml
写的配置文件会变得越来越大,越来越笨重。在大型项目中,它经常什么“特别的”事还没干就有几百行代码。基于这些原因,我们来看今天的主要内容 Gradle
。
3. Gradle Build Tool
随着时间的推移,开发人员对拥有和使用 DSL(Domain Specific Languages )
越来越感兴趣——简单地说,这将允许他们使用为特定领域定制的语言来解决特定领域中的问题。
Gradle
采用了这种方法,它使用的是基于 Groovy
或 Kotlin
的 DSL
。这导致了更小的配置文件和更少的混乱,因为该语言是专门为解决特定领域的问题而设计的。按照惯例,Gradle
的配置文件在 Groovy
中称为 build.Gradle
,在Kotlin
中称为 build.Gradle.kts
。注意,Kotlin
在自动完成和错误检测方面提供了比 Groovy
更好的IDE支持。
而且,Gradle
并不是另起炉灶,它基于 Groovy
语言,并充分地使用了 Maven
的现有资源。继承了 Maven
中仓库,坐标,依赖这些核心概念。文件的布局也和 Maven
相同。但同时,它又继承了 Ant
中 target
的概念,我们又可以重新定义自己的任务了(gradle
中叫做 task
)。
简单点,Gradle
是一个依赖管理和构建自动化工具。
我们来体验一下,新建一个空目录,在命令行,执行
gradle init --type java-library
可以看到新创建了一个工程,工程根目录下,主要看这几项:
build.gradle gradle settings.gradle src
我们看一下,build.gradle
的内容:
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java Library project to get you started.
* For more details take a look at the Java Libraries chapter in the Gradle
* User Manual available at https://docs.gradle.org/6.5/userguide/java_library_plugin.html
*/
plugins {
// Apply the java-library plugin to add support for Java Library
id 'java-library'
}
repositories {
// Use jcenter for resolving dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
dependencies {
// This dependency is exported to consumers, that is to say found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:29.0-jre'
// Use JUnit test framework
testImplementation 'junit:junit:4.13'
}
内容很简单,引入了 java
插件,指定仓库,指定依赖。可以看到依赖的设定相比起 xml
的写法,变得大大简化了。
使用 Gradle
,任务又变成了核心概念了。我们就来体验一下任务。
在 build.gradle
里添加这样的任务:
task hello {
println 'welcome to gradle';
}
然后在命令行执行
gradle -q hello
注:-q 参数。用来控制 Gradle 的日志级别,可以保证只输出我们需要的内容。
就可以看见打印一行 "welcome to gradle"
。在使用 maven
构建的时候,如果想临时对某一个构建任务加一点 log
,会是个非常困难的事情 。但在 Gradle
里,就变得非常简单,因为 gradle
的背后其实是 groovy
这个编程语言在起作用。为了验证这一点,我们再改一下:
task hello {
3.times {
println 'welcome to gradle';
}
}
然后执行 gradle -q hello
,就可以看到连续打印了三行。使用脚本语言进行构建,这几乎给了我们任何的能力,我们可以在构建的时候做任何的事情,甚至你可以直接让 Gradle
帮你做表达式求值。
接下来,我们来认识一下 Gradle
。
二.、Gradle 基础知识与原理
Gradle 基础知识与原理2
最后,参考链接:
Ant 、Maven和Gradle的比较
构建工具的进化:ant, maven, gradle