Gradle Build Cache引發的Task緩存編譯問題
前言
前一陣子公司內部卷瞭一篇文章大傢有興趣的可以看下,大概把我們編譯優化的原理介紹瞭下,當然其中還有些技術細節相關的並沒有寫。
嗶哩嗶哩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緩存的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- Kotlin與Java的區別詳解
- 一款Android APK的結構構成解析
- Android開發gradle拉取依賴的加速配置
- Android開發升級AGP7.0後的一些適配方法技巧
- gradle和maven有哪些區別