Gradle学习(十)——构建缓存

原创 2018年01月02日 17:45:27

转载请注明出处:/lastsweetop/article/details/78954076

简介

Gradle的构建缓存是一种缓存机制,目的是为了通过重用上一次构建的输出来节省构建时间。构建缓存机制把构建的输出存储在本地或者远程,当确认本次构建的输入没有改变那么它将会使用构建的缓存作为输出。

构建缓存的第一个功能是任务输出缓存,任务输出和up-to-date检查本质上一样的原理,不同的是up-to-date检查仅仅局限于相同的工作空间,而任务输出缓存可以使用本机的任何地方的的构建,当任务输出缓存使用共享的构建缓存时,还可以运行在不同机器之间。

启用构建缓存

默认情况下,构建缓存是没有启用的,有两种方法可以启用构建缓存:

  • 构建的命令行下增加--build-cache选项,但要注意只是本次生效。
  • gradle.properties文件中设置org.gradle.caching=true,这样就可以每次生效,除非命令行下带了--no-build-cache选项

任务输出缓存

除了增量构建外,Gradle还能通过重用任务的输出来节省构建时间,任务输出不仅可以在同一台电脑的不同构建之间重用,还可以通过构建缓存在不同电脑之间重用。

有个典型的用例,用户公司内部有个由定期的持续集成产生的构建缓存,开发者或者其他持续集成带来可以从这个构建缓存实体去拉取缓存实体。我们期望所有的开发者都没有权利去填充构建缓存,每个持续集成也需要在clean任务之后才可以填充构建缓存。

如果想要任务输出缓存更好的工作,最好和增量构建插件一起使用,例如连续执行两次构建,所有任务的输出应该是UP-TO-DATE,如果想获得更快的构建,只有任务输出缓存是远远不够的。

示例

我们用带有java插件的java工程来演示,首先第一次执行命令gradle --build-cache compileJava,输出如下:

Build cache is an incubating feature.

BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

为了不用到增量构建,先来清除一下gradle clean,输出如下:

Build cache is an incubating feature.

BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

然后重复第一步gradle --build-cache assemble,输出如下:

Build cache is an incubating feature.

BUILD SUCCESSFUL in 1s
2 actionable tasks: 1 executed, 1 from cache

可以看到只执行了一个任务,还有一个任务是来自于缓存,由于新版gradle的控制台输出,无法看到更详细的信息,但在scan或者IDE下可以看到从缓存中取的是compileJava任务,因为assemble对应的jar任务没有缓存,只有执行。即使再次clean,重新执行一次第三步结果也是一样,因为jar任务并不会被缓存。

可缓存的任务

一旦任务可以描述所有的输入输出,那么gradle就可以基于任务的输入来计算一个构建缓存的key来唯一确定输出,这个key可以被用于请求构建缓存中之前的输出,也可以把新的输出填充到构建缓存中,如果之前的构建已经被其他人填充,比如其他的持续集成服务器或者其他开发者,你就没必要再进行一次构建。

下面以up-to-date检查相同的方式来为任务生成构建缓存key:

  • 任务的类型和classpath
  • 输出属性的名字
  • 自定义任务类型注解属性的名字和值
  • 用DSL通过TaskInputs增加的属性的名字和值
  • Gradle的distribution,buildSrc和plugins的classpath
  • 影响任务执行的构建脚本的内容

任务类型需要通过增加@CacheableTask注解来选择是否填充到构建缓存中,@CacheableTask是不能被继承的,自定义任务默认不能被缓存。

内置的可缓存任务

下面是一些内置的可缓存的任务

  • java工具链:JavaCompile,Javadoc
  • groovy工具链:GroovyCompile,Groovydoc
  • scala工具链:ScalaCompile,Scaladoc
  • Testing:Test
  • 代码质量任务:Checkstyle,CodeNarc,FindBugs,JDepend,Pmd
  • Jacoco:JacocoMerge,JacocoReport
  • 其他任务:ValidateTaskProperties,WriteProperties

native编译缓存

native编译工具链也可以缓存,将org.gradle.caching.native设置为true就可启用,比如CCompile和CppCompile

不可缓存的任务

所有其他的任务当前都是不可缓存的,未来可能提供其他语言或者其他领域的支持。还有一些任务,比如copy或者jar,仅仅是复制文件从一个地方到另一个地方,做成可缓存的也没多大意义。没有产生输出或者动作的任务也没有意义做成可缓存。

声明任务输入和输出

一个可以缓存的任务有完整的输入输出图很重要,以便构建的结果可以被其他地方安全的重用。

缺少任务输入可能引起不正确的缓存命中,因为两次构建拥有相同的构建缓存key而导致不同的输出结果被相同的对待。如果gradle不能万钻的捕获给定任务的所有输出,缺失构建输出也会导致构建失败。错误的定义输入也会导致无法命中缓存,比如输入中包含了不稳定的数据或者绝对路径。

为了保证输入输出被正确的定义,可以考虑集成测试,比如TestKit,它可以检查相同的输入是否会产生相同的输出,并且可以为任务捕获所有的输出文件,还要确定任务的输入是可复位的,比如在不同的构建目录下可以重用构建缓存。

配置构建缓存

你可以在settings.gradle中的Settings.buildCache(org.gradle.api.Action)代码块中来配置构建缓存

Gradle支持本地和远程构建缓存,它们可以分别配置。如果两者都是启用的,Gradle则会先去找本地的构建缓存,如果找不到再会去找远程的构建缓存。如果远程的构建缓存找到了,它就会在本地缓存中也存一份,下次本地的就会找到了。Gradle可以把构建输出push到任意构建缓存中,BuildCache.isPush()也会被设置成true。

默认情况下,本地构建缓存的push是启用的,远程的构建缓存的push是禁用的。本地构建缓存可以通过DirectoryBuildCache来进行预设值,默认push是启用的。远程构建缓存可以通过设置BuildCacheConfiguration.remote(java.lang.Class)来指定构建缓存的类型。

内置的本地构建缓存

内置的本地构建缓存DirectoryBuildCache,用一个目录来存储构建缓存的artifacts。默认情况下,他是放在用户的Gradle目录中,但是它的位置是可以配置的。

Gradle会定期的清除本地构建缓存使它减少到配置的大小,这意味着本地构建缓存可以在下一次清理前会大于配置的大小.

配置示例如下:

buildCache {
    local(DirectoryBuildCache) {
        directory = new File(rootDir, '.build-cache')
        targetSizeInMB = 1024
    }
}

远程的构建缓存

配置很容易:

buildCache {
    remote(HttpBuildCache) {
        url = 'https://example.com:8123/cache/'
    }
}

但是搭建远程构建缓存服务器需要企业版,暂时就不聊了,你懂得。。。。。。。。。。

版权声明:本文为博主原创文章,未经博主允许不得转载。

钱柜娱乐开户 Studio更改Gradle缓存目录所引发的各种奇葩问题

gradle cache文件过大的纠结AS运用gradle构建app项目,其中必然会缓存各种文件,如编译的各类class,依赖的各种jar包,那这个缓存文件放在哪里呢? 默认位置:C:\Users(...
  • pigdreams
  • pigdreams
  • 2017年07月02日 00:20
  • 2299

钱柜娱乐开户 Studio 和 gradle 修改缓存文件夹路径

参考:/qiujuer/article/details/44160127 /qiujuer/article/detai...
  • xx326664162
  • xx326664162
  • 2016年07月25日 18:28
  • 9048

【FAQ】命令行如何刷新gradle依赖缓存?

【问题描述】 最近 gradle 在下载 maven 私服上的 aar 快照的时候,突然提示下载不了 xxx.jar。可是 maven 私服上只有 aar 包,并没有 jar 包。 【原因分析】 第一...
  • cuiaamay
  • cuiaamay
  • 2016年10月12日 15:11
  • 13284

Gradle学习(十五)——增量构建

任何构建工具最重要的一个功能就是防止做重复工作。例如对于编译进程来说,如果已经执行了一次编译,那么就不需要再进行第二次,除非发生了一些会影响输出的操作,比如源代码改了或者输出被删掉了,编译会消耗很多时...
  • kwame211
  • kwame211
  • 2018年01月11日 09:17
  • 43

Gradle学习系列之四——增量式构建

在本系列的上篇文章中,我们讲到了如何读懂Gradle的语法,在本篇文章中,我们将讲到增量式地构建项目。     请通过以下方式下载本系列文章的Github示例代码: git clon...
  • caomiao2006
  • caomiao2006
  • 2016年04月24日 17:18
  • 425

Gradle学习系列之四——增量式构建

如果我们将Gradle的Task看作一个黑盒子,那么我们便可以抽象出输入和输出的概念,一个Task对输入进行操作,然后产生输出。比如,在使用java插件编译源代码时,输入即为Java源文件,输出则为c...
  • lg831229
  • lg831229
  • 2014年04月10日 08:37
  • 555

Gradle学习系列之四——增量式构建

请通过以下方式下载本系列文章的Github示例代码: git clone https://github.com/davenkin/gradle-learning.git     ...
  • leiyong0326
  • leiyong0326
  • 2015年06月04日 17:19
  • 361

Gradle学习系列之八——构建多个Project

在本系列的上篇文章中,我们讲到了Gradle的依赖管理,在本篇文章中,我们将讲到如何构建多个Project。     请通过以下方式下载本系列文章的Github示例代码: git clone...
  • Guofengpu
  • Guofengpu
  • 2016年05月20日 11:19
  • 352

Gradle学习(十五)——增量构建

Up-to-date检查(AKA增量构建)任何构建工具最重要的一个功能就是防止做重复工作。例如对于编译进程来说,如果已经执行了一次编译,那么就不需要再进行第二次,除非发生了一些会影响输出的操作,比如源...
  • lastsweetop
  • lastsweetop
  • 2018年01月10日 16:35
  • 3266

Gradle学习(十一)——构建脚本基础知识

Gradle的所有都是基于两个基础概念:项目和任务每个Gradle构建是由一个或者多个项目构成的,项目表示什么取决于你用Gradle做什么。比如,项目可以表示jar库或者web程序。它也可以表示由其他...
  • lastsweetop
  • lastsweetop
  • 2018年01月03日 16:26
  • 678
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Gradle学习(十)——构建缓存
举报原因:
原因补充:

(最多只允许输入30个字)