Gradle Build Cache引发的Task缓存编译问题

目录
  • 前言
  • 基础知识
  • Cacheable tasks
  • TaskOutput
  • 有趣的编译问题
    • 问题分析
  • 最后

前言

前一阵子公司内部卷了一篇文章大家有兴趣的可以看下,大概把我们编译优化的原理介绍了下,当然其中还有些技术细节相关的并没有写。

哔哩哔哩Android编译优化。

基础知识

Gradle 构建缓存是一种缓存机制,旨在通过重用其他构建产生的输出来节省时间。构建缓存通过存储(本地或远程)构建输出并允许构建在确定输入没有更改时从缓存中获取这些输出来工作,从而避免了重新生成它们的昂贵工作。

使用构建缓存的第一个功能是任务输出缓存。本质上,任务输出缓存利用了与最新检查相同的智能,当先前的本地构建已经产生一组任务输出时,Gradle 使用它来避免工作。但是,任务输出缓存不仅限于同一工作区中的先前构建,而是允许 Gradle 重用本地机器上任何位置的任何早期构建的任务输出。当使用共享构建缓存进行任务输出缓存时,这甚至可以跨开发人员机器和构建代理工作。

除了任务之外,工件转换还可以利用构建缓存并重用其输出,类似于任务输出缓存。

以上内容摘自gradle官方文档,链接如下

我简单的翻译下给各位大佬,在本地存在build cache的情况下,gradle task会基于当前的输入来作为缓存的key值,如果输入内容没有发生变更,则意味着本Task可以被跳过,另外这个不同于增量编译。

又可以偷下官方的图片了。举个栗子,JavaCompiler task的输入的java文件和上一次编译的一样,则意味着该任务可以使用原来编译输出作为编译产物。

Cacheable tasks

任务类型需要使用 @CacheableTask 注释选择加入任务输出缓存。 请注意,@CacheableTask 不被子类继承。 默认情况下,自定义任务类型不可缓存。

官方有说明什么情况下会使用编译缓存,首先我们的Task要被定义成@CacheableTask

另外对于Task内部的输入和输出也需要打上@TaskInputs@TaskOutputs注解。这样才能保证当前的Task具备了编译缓存的能力。

所以想要写一个能具备缓存能力的Task也是比较复杂的。这也就是为什么Android后面会开始推动Artifacts的使用了,让开发尽量可以少关心输入输出相关的逻辑。

我们升级适配完AGP 7.0 | 杂谈

那么相对的,没有定义@CacheableTask的则认为是内有编译缓存的任务。

TaskOutput

在上述这种被跳过的任务哦,一般都会有在Task编译完成之后带上一些特殊的标识符。

  • (no label) or EXECUTED 任务正常执行了。
  • UP-TO-DATE 任务输出没有变更。
  • 输入输出均没有发生变更。
  • 任务执行了,但是任务告诉gradle输出并未发生变更。
  • 任务没有执行和一些依赖项,但所有依赖项都是最新的、已跳过或来自缓存。
  • 任务没有执行也没有依赖。
  • FROM-CACHE 任务的输出可以从之前的执行中找到。任务已从构建缓存恢复输出。
  • SKIPPED 该任务没有被执行。任务已明确从命令行中排除。
  • NO-SOURCE 当前无需执行该任务。输入内容并没有源文件,比如.java

简单的来说,除了第一种情况以外,其他的都是任务被跳过。

有趣的编译问题

好了,有了前置的知识储备的情况下,我们就可以展开说一下我们最近碰到的一个奇怪的问题了。

我们有个protobuf编译的仓库,专门负责将pb文件转化成java或者kotlin。然后会把这些生成的文件移动到另外两个模块进行打包,最后删除生成的所有类文件。然后再去执行javacompiler task。

这个模块出现了一个二次编译的问题。第一次打包protobuf模块的时候编译是正常的,然后当二次编译该模块的情况下,该模块就会出现类丢失的问题。

问题分析

这个问题分析起来就比较简单。在二次编译的情况下呢,因为输入的内容并没有发生变更,所以触发了Gradle Task相关的缓存,然后所有的pb文件转化成java kt的过程就被跳过了。但是呢后续的copy task因为本身不具备缓存能力,所以他还是会执行一次cv的任务。但是原来生成的java和kt已经被删除了。这个时候他就会把空的文件夹进行一次覆盖操作。之后就导致了原来的java和kt文件全部丢失的问题。

这就是一个很有趣的build cache导致的奇形怪状的问题,因为上一个任务具备了编译缓存,之后跳过了编译直接用了原来的output输出。但是呢下一个任务非缓存的,所以必然还是会执行拷贝任务。

至于解决方案我就不写了,感觉大家应该没啥兴趣。

最后

重要的事情再说一遍,前一阵子在公司内部卷了一篇文章大家有兴趣的可以看下,大概把我们编译优化的原理介绍了下,当然其中还有些技术细节相关的并没有写。

https://www.jb51.net/article/252481.htm

以上就是Gradle Build Cache引发的Task缓存编译问题的详细内容,更多关于Gradle Build Cache编译Task缓存的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android Gradle同步优化详解

    目录 动态修改gradle配置 hook agp ProjectsServices 方法签名检查是否存在support包 年初开始我们就开始了关于Gradle Sync阶段的优化.之前和大家都简单的介绍过工程相关的背景情况了,我们大概有400+的Module,然后一次的同步时间就非常的慢,我们迫切的需要对这个问题进行优化.大部分工作都是和团队内的同学一起完成的,我也只出了一点点力而已. 这次写文章真的很倒霉,之前忘了保存导致要重新开始写了.如果不是白嫖了掘金的端午礼盒,拿人手短啊,我已经打算鸽了

  • gradle使用maven-publish发布jar包上传到私有maven配置

    目录 一.添加插件 二.添加如下配置 三.执行以下命令进行上传 四.遇见的问题 一.添加插件 apply plugin: 'maven-publish' 二.添加如下配置 //打包源码 task sourceJar(type: Jar) { from sourceSets.main.allJava } publishing { publications { maven(MavenPublication) { //指定group/artifact/version信息,可以不填.默认使用项目grou

  • Gradle构建基本的Web项目结构

    目录 一.环境要求 二.创建应用结构 三.添加Gradle脚本 四.编写Servlet 五.添加请求页面和JSP页面 六.添加gretty插件,以便于直接运行程序 补充.切换Servlet容器及更多配置 一.环境要求 一个好用的IDE编辑工具 Java环境(>=8) Gradle构建工具(>=4.10.3) 二.创建应用结构 gradle使用war插件来进行java web项目构建,war插件继承了Java 插件并添加了对web应用程序的支持.默认情况下,使用src/main/webapp目录

  • Nexus3x创建私有仓库并使用gradle上传jar包

    目录 一.创建私有仓库 二.将私有仓库添加到maven-public库中 三.使用Gradle上传jar包到私有仓库示例 一.创建私有仓库 1.打开Nexus首页并登录,进入设置界面,点击创建 2.选择maven2 hosted类型的仓库 3.输入创建的仓库的名称,如果允许重复部署,可以将下方的Disable redeploy更改为Allow Redeploy 二.将私有仓库添加到maven-public库中 1.打开maven-public的设置界面 2.将我们创建的库添加到maven-pub

  • Android项目中gradle的执行流程

    目录 gradle文件执行流程 自定义gradle文件的导入方法 gradle中定义的变量如何被java代码使用 gradle文件执行流程 做过Android开发的同学都知道 ,Android项目中存在三个gradle文件,那你是否知道他们的执行流程呢?请看下面这张图: 为了验证结论 的正确性,我们采用输出字符串的验证方式: 输出结果如下: 自定义gradle文件的导入方法 上面所阐述的三个 gradle 文件是由系统来管理的,那我们能创建gradle文件吗?答案是肯定的. 那我们创建的 gra

  • Android Studio 中Gradle配置sonarqube插件(推荐)

    目录 一,使用公共Maven仓库: 二,使用私有Maven仓库: Sonarqube作为一个很实用的静态代码分析工具,在很多项目中都使用.Android自然也不例外.这里就分享下使用Android Studio时如何在Gradle里配置Sonarqube. 以下分别就使用公共maven仓库和私有maven仓库两种情况来简单说明下: 一,使用公共Maven仓库: 这个比较简单. 打开gradle sonarqube插件官方网址:https://plugins.gradle.org/plugin/o

  • Gradle Build Cache引发的Task缓存编译问题

    目录 前言 基础知识 Cacheable tasks TaskOutput 有趣的编译问题 问题分析 最后 前言 前一阵子公司内部卷了一篇文章大家有兴趣的可以看下,大概把我们编译优化的原理介绍了下,当然其中还有些技术细节相关的并没有写. 哔哩哔哩Android编译优化. 基础知识 Gradle 构建缓存是一种缓存机制,旨在通过重用其他构建产生的输出来节省时间.构建缓存通过存储(本地或远程)构建输出并允许构建在确定输入没有更改时从缓存中获取这些输出来工作,从而避免了重新生成它们的昂贵工作. 使用构

  • Android Gradle Build Error:Some file crunching failed, see logs for details的快速解决方法

    错误日志:Error:java.lang.RuntimeException: Some file crunching failed, see logs for details Log: FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:mergeDebugResources'. > Error: java.lang.RuntimeException: Crunch

  • Android Gradle Build Error:Some file crunching failed, see logs for details解决办法

    Android Gradle Build Error:Some file crunching failed, see logs for details解决办法 错误日志:Error:java.lang.RuntimeException: Some file crunching failed, see logs for details Log: FAILURE: Build failed with an exception. * What went wrong: Execution failed

  • android studio 一直卡在Gradle:Build Running的几种解决办法

    在使用AS开发安卓应用程序的时候经常会遇到Gradle build running一直在运行甚至卡死的情况,解决方法如下: 方法1: 1.在C:\User\<用户名>\.gradle 目录下新建一个gradle.properties文件,并在里面添加一行:org.gradle.daemon=true 2.打开AS,在Settings中设置Gradle的工作模式为offline,如下图: 这样就可以解决一直在running的问题了 方法2: 找到路径C:\Users\admin\.gradle\

  • spring boot+spring cache实现两级缓存(redis+caffeine)

    spring boot中集成了spring cache,并有多种缓存方式的实现,如:Redis.Caffeine.JCache.EhCache等等.但如果只用一种缓存,要么会有较大的网络消耗(如Redis),要么就是内存占用太大(如Caffeine这种应用内存缓存).在很多场景下,可以结合起来实现一.二级缓存的方式,能够很大程度提高应用的处理效率. 内容说明: 缓存.两级缓存 spring cache:主要包含spring cache定义的接口方法说明和注解中的属性说明 spring boot

  • AndroidStudio3.6的卸载安装,Gradle持续下载/Gradle Build失败等问题

    因为某些原因,重装了AS,重装过程中在Gradle Build上遇到了很多问题,最后发现是下载被墙的问题,没有配置镜像.所以做此总结~ 1. 安装卸载AndroidStudio 1.1 卸载: 步骤一:在安装目录下找到install文件运行卸载,或者采用第三方软件(安全管家)进行卸载. 步骤二:在C:\Users\Administrator 下删除 \.AndroidStudio3.X,\.gradle,\.android文件. 1.2 安装 步骤一:官网下载:https://developer

  • Spring项目中使用Cache Redis实现数据缓存

    目录 Spring项目中实现数据缓存 一.Spring Cache + Redis 介绍 二.项目中集成 1. 引入依赖 2. 添加 redis 配置类 3. 配置文件增加 redis 配置 4. 启动安装好的 redis 三.Spring Cache 常用注解介绍 1. @Cacheable 2. @CachePut 3. @CacheEvict 四.功能里实现缓存操作 查询操作 导入操作 Spring项目中实现数据缓存 有时候我们为了提高查询速度,会使用缓存,但是并不是所有数据都适合放到缓存

  • vue项目 npm run build 打包项目防止浏览器缓存的操作方法

    在vue.config.js配置 推荐方法1: const Timestamp = new Date().getTime() module.exports = { ...... configureWebpack: config => { config.output.filename = `js/[name].${Timestamp}.js` config.output.chunkFilename = `js/[name].${Timestamp}.js` }, ...... css: { ...

  • Spring Cache手动清理Redis缓存

    这篇文章主要介绍了Spring Cache手动清理Redis缓存,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 注册cacheRedisTemplate 将 cache 的 RedisTemplate 注册为Bean @Bean(name = "cacheRedisTemplate") public RedisTemplate cacheRedisTemplate(@Qualifier("jedisConnectionFac

  • Gradle build 报错:Received status code 400 from server

    全部错误是这样的: Could not GET 'https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.1.2/gradle-3.1.2.pom'. Received status code 400 from server: Bad Request. 遇到这个错了以后,我先后做了以下尝试: 手动下载确认链接无误. 查询400 code,意思大概是客户端请求语法问题或者参数有问题.这样就很有可能是代理出问题

随机推荐