Gradle-wrapper 的学习笔记

前言

Gradle Wrapper 这个东西其实困扰了我很久,对这个东西一直没搞懂,只知道使用 gradlew 这个命令就可以实现 gradle 的功能,但是实际为什么要这样去操作呢?我还是一知半解的,今天花了点时间大概弄明白了为什么会有 Gradle Wrapper 的存在。

我们去百度搜索 gradle wrapper 相关博客时,一般都是这样说, gradle wrapper 可以在用户没有安装 gradle 的情况下去帮用户去下载 gradle ,然后使用 gradlew 就可以操作 gradle 进行项目的构建了。

然后,我还是没有搞明白。

gradle wrapper 组成&作用

一般情况下,我们使用 AndroidStudio 新建一个工程之后,都会以下几个文件

── gradle
 ── wrapper
 		── gradle-wrapper.jar
 		── gradle-wrapper.properties
── gradlew
── gradlew.bat

它们的作用如下:

  • gradlew 是 shell 脚本(Linux/Mac OS),是一个可执行文件,操作 gradle 命令(windows 是 gradlew.bat)

  • gradle-wrapper.properties 对 gradle 配置,例如 gradle 下载的地址等

  • gradle-wrapper.jar 内部都是用 class 字节码

gradlew 下载 gradle 的源代码就写在这里哦,底层是使用 java 的 HttpURLConnection 实现的,有兴趣可以去浏览一下

上面几个文件是 Andorid 开发者最最熟悉的了,但是一问 wrapper 是干嘛用的又不清楚~

到底 wrapper 是什么东西,我只知道新建一个 Android 工程 AS 就自动帮我创建了这些文件,我根本就不需要去搭理它。

然后我打开官方文档,看看 gradle wrapper 的描述

https://docs.gradle.org/current/userguide/gradle_wrapper.html#sec:adding_wrapper

按照文档的描述主要有以下几个步骤

外链图片转存失败

gradle wrapper 的操作流程

假如有一个用户 A 他的电脑装了 Gradle 并且用 Gradle 来构建 Android 项目,为了方便其它组员开发(统一 gradle 版本号),他通过 Gradle 命令生成了 gradle wrapper ,然后通过 git 将刚才生成的 gradle wrapper 上传到版本库进行管理。

接下来另一个组员 B 他的电脑没有安装 Gradle ,但是呢,他又要去构建这个项目怎么办?这时 gradle wrapper 就起作用了, B 用户git pull 代码之后,他无需去安装 Gradle ,只需要通过 ./gradlew build来构建即可。

这种情况是不是很常见?

接下来,来模拟一下这个流程

用户A开始操作

  • 创建一个文件件 GradleDemo(假设为用户 A 要开发的 Android 项目
mkdir GradleDemo
cd GradleDemo
  • 在终端执行 wrapper 这个任务,生成 gradle wrapper
gradle wrapper --gradle-version 4.4 --distribution-type all
  • 生成的内容如下
── gradle
 ── wrapper
 		── gradle-wrapper.jar
 		── gradle-wrapper.properties
── gradlew
── gradlew.bat

  • 将以上文件通过 git 上传

用户B开始操作

  • 从 git 中拉下用户 A 上传到的代码

  • 操作 gradlew 命令

对于第二点,操作 gradlew 命令(例如: ./gradlew -v),它会有以下几个步骤:

Step 1. 从 gradle 服务器下载 distributions

首先它会检测本地是否有对应 gradle 版本,没有的话就去下载

那去哪里下载呢? 下面的 distributionUrl就是 distributions 的下载地址,这里指定了要下载的版本为 4.4 ,类型为 all

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

那你肯定会问,all 表示什么,其实通过 Step3 你就知道,all 表示下载的内容包括了 doc,sample,gradle源代码gradle class 编译文件等,

如果你不需要那么多,那你可以将 all 修改为 bin

第一次执行 命令时,它会去下载你配置的 gradle 版本,可能需要翻墙…从下面的日志可以看到,下载的内容会解压到保存到本地目录了


➜ gradle ./gradlew -v

Downloading https://services.gradle.org/distributions/gradle-4.4-all.zip

.......................................................................................................................................................................................................................................................................................

//在这里解压下载回来的 gradle
Unzipping /Users/liaowj/.gradle/wrapper/dists/gradle-4.4-all/4mxuau4c77thx8zlvtz4xiez7/gradle-4.4-all.zip to /Users/liaowj/.gradle/wrapper/dists/gradle-4.4-all/4mxuau4c77thx8zlvtz4xiez7
Set executable permissions for: /Users/liaowj/.gradle/wrapper/dists/gradle-4.4-all/4mxuau4c77thx8zlvtz4xiez7/gradle-4.4/bin/gradle  
  
 
------------------------------------------------------------

Gradle 4.4

------------------------------------------------------------
Build time: 2017-12-06 09:05:06 UTC
Revision: cf7821a6f79f8e2a598df21780e3ff7ce8db2b82
Groovy: 2.4.12
Ant: Apache Ant(TM) version 1.9.9 compiled on February 2 2017
JVM: 1.8.0_111 (Oracle Corporation 25.111-b14)
OS: Mac OS X 10.14 x86_64

Step 2. 保存起来,并且解压 gradle,保存到 Gradle User Home 中,一般是在 $USER_HOME/.gradle/wrapper/dists

例如我笔记本保存 gradle 的路径如下:

/Users/liaowj/.gradle/wrapper/dists/gradle-4.4-all/4mxuau4c77thx8zlvtz4xiez7/gradle-4.4
  • step 3. 然后就可以愉快地使用 gradlew 了

gradle 组成

好了,来看看下载回来的gradle 文件吧~

使用 gradlew 去下载 gradle 之后是一个 zip 包,并且它会帮你解压~

下面就是 gradle-4.4-all.zip 解压的内容了

gradle-4.4-all.zip 解压

解压内容如下:

gradle-4.4

	bin gradle 可执行文件

	docs 当前 gradle 版本相关的文档都在这~

	lib 里面问很多 jar 包,这些 jar 包都是 gradle 编译好的 class 代码

	samples 是一些 gradle 的示例

	src gradle 的源码就在这里啦

	... 还有其它...

GRADLE_HOME&GRADLE_USER_HOME

你是不是被这两个东西是不是困扰的许久呢?

看了上面的分析后,gradlew 操作的第一步会将 gradle 下载到指定的目录下

但是我们会有疑问,这个目录能不能我们开发者来指定呢?

先来看看默认的存储目录:

/Users/liaowj/.gradle/wrapper/dists/

我记得 gradlew 是根据 gradle-wrapper.properties 配置文件来决定去哪里下载 gradle 的,那按道理应该会告诉 gradlew 下载之后保存到哪里吧?

#Sat Aug 24 13:13:34 CST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

推敲:从上面的配置信息再结合默认的存储目录可以看出,gradle 下载的路径其实就是

distributionBase/distributionPath 
也等价于 GRADLE_USER_HOME/wrapper/dists

那就可以推出 GRADLE_USER_HOME 就是 /Users/liaowj/.gradle/

不信?那从代码来验证一下:

在 build.gradle 中写如下代码:

project.getGradle().gradleHomeDir
project.getGradle().gradleUserHomeDir

执行以下命令:

➜  GradleDemo ./gradlew clean
Starting a Gradle Daemon (subsequent builds will be faster)
<-----
> Configure project : 
/Users/liaowj/.gradle/wrapper/dists/gradle-4.4-all/9br9xq1tocpiv8o6njlyu5op1/gradle-4.4
/Users/liaowj/.gradle

那意思就说,我们只要手动去修改 GRADLE_USER_HOME 这个值,那么就可以修改 gradle 的存储目录咯~

那如何去修改呢?跟进去源码可以发现, gradleUserHome 是通过读取环境变量"GRADLE_USER_HOME"来设置

gradleUserHome = System.getenv("GRADLE_USER_HOME");

GRADLE_USER_HOME

所以我们只需要在环境变量中去设置 GRADLE_USER_HOME 就好了

打开vim ~/.bash_profile添加以下配置信息(我在 Mac OS 平台哈~)

GRADLE_USER_HOME=~/Document/.gradle
export GRADLE_USER_HOME

然后我们来验证一下

从下面的输出日志来看,我们已经修改成功了,我们将 /Users/liaowj/.gradle 修改为了 /Users/liaowj/Document/.gradle

➜  GradleDemo ./gradlew clean
Starting a Gradle Daemon (subsequent builds will be faster)
<-----

//因为从新配置了新的存储目录,这里会去下载gradle....

> Configure project : 
/Users/liaowj/Document/.gradle/wrapper/dists/gradle-4.4-all/9br9xq1tocpiv8o6njlyu5op1/gradle-4.4
/Users/liaowj/Document/.gradle

对了,上面的输出日志中,还有一个 project.getGradle().gradleHomeDir 这个又是干嘛的?

这个呢,其实就是你实际下载回来的 gradle 的实际目录了,例如我们工程中 wrapper 中配置的是 4.4 版本那么它的路径如下

/Users/liaowj/Document/.gradle/wrapper/dists/gradle-4.4-all/9br9xq1tocpiv8o6njlyu5op1/gradle-4.4

在这里插入图片描述

那另一个工程中配置的是 3.5 版本那么它的路径如下:

/Users/liaowj/Document/.gradle/wrapper/dists/gradle-3.5-all/9br9xq1tocpiv8o6njlyu5op1/gradle-3.5

也就是说,/Users/liaowj/Document/.gradle 是固定的,后面的就是根据 gradle-wrapper 中的配置然后存储在不同的文件夹下了。

所以从这里就看出为什么 Gradle 官方推荐我们使用 gradle wrapper 去构建工程项目了吧~

Gradle 版本和插件版本

classpath 'com.android.tools.build:gradle:3.4.2'

我之前一直没搞明白这两者的关系,到底哪个插件版本对应使用哪个 Gradle 版本呢?

下面是在 Android Gradle Plugin官网 看到的,日后不懂哪个版本对哪个版本就看看这个吧~

Gradle版本与插件版本对应表

Gradle Plugin 简单理解就是将一些公共的功能抽取出来成为插件,增强复用性,插件是基于 gradle 语言去开发的,之所以出现插件版本不匹配对应的 gradle 版本就是因为这个插件使用该 Gradle 版本不具备的 api ,那么你要去升级到对应的版本了,具体就看看上面的表格。

有个 bug, 记录一下~

有一天,我在控制台输入以下命令,它报错了

> gradle build
* What went wrong:

A problem occurred evaluating root project 'GradleDemo'.

> Could not find method google() for arguments [] on repository container of type org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler.



* Try:

Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

上面这个这个错误,想必你应该遇过吧~

stackoverflow 可以找到答案,这个错误是你使用的 gradle 版本低于 Gradle 4.x+,所以就会有这个问题呀。

但是我的 gradle-wrapper.properties 是已经是使用了 4.4 版本了啊,为啥还…

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStoreath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

那问题的根源在哪里?

问题是出现在我在本地的环境变量中配置了 gradle ,并且版本号为 gradle-3.5。

GRADLE_HOME=/Users/liaowj/Library/Android/gradle/gradle-3.5
export PATH=$PATH:$GRADLE_HOME/bin

所以我在终端使用 gradle build的时候使用的是 gradle-3.5 版本,而不是在项目工程下的gradle-wrapper配置的那个版本号。

其实要验证这个问题也很简单,只要执行 gradle -v 就知道当前的 gradle 版本了

➜ GradleDemo gradle -v
------------------------------------------------------------
Gradle 3.5
------------------------------------------------------------

所以,你需要用 gradlew 去构建,那你如果不想修改环境变量,那么你就要去使用

./gradlew build

通过 gradlew 才是真正去用的是 gradle-wrapper 的指定的版本号。

➜ GradleDemo ./gradlew -v
------------------------------------------------------------
Gradle 4.4
------------------------------------------------------------

结论:在工程项目中,尽量使用 gradlew 来构建(Gradle 官方就是这样推荐的~),这样它会跟你项目配置的版本会是一样的,如果你跟我一样项目用的版本跟环境变量配置的 gradle 版本不一样的话就会这种问题啦~

本文是笔者学习之后的总结,方便日后查看学习,有任何不对的地方请指正。

记录于 2019年8月24号

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值