前言

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

哔哩哔哩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缓存的资料请关注Devmax其它相关文章!

Gradle Build Cache引发的Task缓存编译问题的更多相关文章

  1. ios – Xcode 5持续集成CodeSign失败

    嗨,您好.我正在尝试使用xcode5和OSXServer为我的iOS应用程序配置持续集成.我将证书和p12添加到系统KeyChain,我还将配置文件复制到配置文件的服务器文件夹.集成失败,日志显示错误消息短消息:Command/usr/bin/codesignFailedwithexitcode1完整信息:CodeSign/Library/Server/Xcode/Data/BotRuns/Cac

  2. ios – Swift 2.0 – Google Analytics事件构建器错误 – NSMutableDictionary无法转换为[NSObject:AnyObject]

    完美地使用Swift1.2代码:错误:任何的想法?解决方法你错了你的事件.这是正确的方法和一种方法.将事件跟踪器初始化为NSObject在发送方法中将NSObject转换为Anyobject.

  3. ios – 如何存档包含自定义框架的应用程序?

    我有一个我创建的xcode框架项目,我可以编译成一个myframework.framework文件.编译之后,我将这个框架拖到我应用程序的Frameworks项目文件夹中,然后利用框架中的类,将适当的import语句添加到需要它的任何类;这允许我的应用程序成功编译与在框架中定义的类的引用.要使应用程序成功部署到我的设备,我还将我的自定义框架添加到我的目标的“嵌入式二进制文件”部分.有了这一切,我可

  4. ios – 1个用于体系结构x86_64的重复符号

    我不确定我做错了什么.我将项目文件夹移动到另一个文件夹,并将备份文件夹复制到桌面.我试图打开备份项目并构建,我收到了链接器错误.所以我决定删除备份文件夹并将项目文件夹移回桌面.我不能再编译并收到以下错误.没有派生数据文件夹还是一样1.我打开了DerivedData文件夹并删除了其中的所有内容2.我删除了所有模拟器中的所有项目3.我重新启动了xCode,Clean和build还是一样将项目添加到Gi

  5. ios – 链接错误/ Build / Products / Debug-iphonesimulator文件未找到

    我有Xcode的问题,不断给我一个链接器错误,它不构建项目.以下是我得到的错误ld:filenotfound:/Users/someuser/Library/Developer/Xcode/DerivedData/MAR-akbwbarcniqxytctbebckkelkbxs/Build/Products/Debug-iphonesimulator/MAR.app/MARclang:error:

  6. iOS 64位兼容性

    我的构建设置如下所示:我的部署目标是iOS6.0.我只需要确认该应用程序是64位兼容的,我都是iOS新手,不久前接管了一个相当大的项目,所以我宁愿要求100%肯定.只是为了使事情变得更清楚,你如何确保iOS应用程序是64位兼容的?

  7. xcode – 苹果LLVM编译3.1错误

    只需更新Xcode到4.3,现在我无法建立我的应用程序.我收到这个错误:有人有这个问题吗?

  8. RubyMotion Build:错误!找不到名为`(?-mix:iOS Team Provisioning Profile)’的配置配置文件

    我正在尝试构建一个简单的RubyMotion应用程序,以便我可以在我的iPhone上传输.我执行了rakebuild:device关于这个错误的任何想法?你应该做这个:InordertosuccessfullyrunaRubyMotionapponanon-jailbrokeniPhone3GSIhadto:DeletealloftheexpiredprovisioningprofilesintheMacOSXKeychainAccessapp.Yeah,mypastislitteredwithmanyr

  9. ios – Apple Mach-O Linker&Ditto Error – Xcode 8

    解决方法>退出Xcode>重新启动系统>选择Xcode–>优先.这将打开一个弹出窗口.选择“位置”.在位置中,您将看到“派生数据”.点击路径旁边的箭头图标.这将打开一个包含“派生数据”的文件夹,将其删除.>清洁产品并运行

  10. xcode – 在Mac上使用OpenGL ES功能

    我试图将opengl绘制到2d空间,并且正在执行以下操作,但它不会编译:我已经包含了OpenGL.framework框架,编译器跟踪说明如下.我已经没有关于如何解决它的想法.我的目标是目前的桌面应用程序,但我的目标是最终制作一个iPhone应用程序.解决方法你有没有包含适当的标题?在Mac上,这些是可能在iPhone上他们是另外,如果我没弄错的话,glOrthof()是特定于OpenGL-ES的.您可能需要在Mac上使用glOrtho().

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部