首頁 > 軟體

Gradle Build Cache引發的Task快取編譯問題

2022-06-22 22:00:12

前言

前一陣子公司內部捲了一篇文章大家有興趣的可以看下,大概把我們編譯優化的原理介紹了下,當然其中還有些技術細節相關的並沒有寫。

嗶哩嗶哩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快取的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com