gradle cache目錄(.gradle)剖析


https://zhuanlan.zhihu.com/p/26473930

gradle下載后會對文件路徑進行修飾,本文給出反向解析,把文件路徑修改為原始路徑的辦法。

之所以研究這個,本來的目的是為了讓Gradle支持離線編譯,但是由於Gradle目錄組織的缺陷,如.gradle/caches/modules-2/metadata-2.23(metadata-xx跟使用的gradle版本有關)目錄下module-artifacts.bin等bin文件中存的是本機的絕對路徑,導致就算將.gradle拷貝給另一台機器,還是需要聯網驗證。

將gradle的jcenter重定向的方法見我的另一篇文章:[android]gradle下載加速 - 知乎專欄,例如阿里雲的jcenter是Index of /repositories/jcenter

我在內網中搭建了jcenter倉庫。然而我不想搭建一個大而全的jcenter的倉庫,搭建大而全的倉庫可以使用nexus來搭建,阿里雲也是那么搭的,由於公司的網絡需要上網認證,時不時會斷一下,所以我的做法是通過利用.gradle目錄來創建jcenter倉庫。

下面先介紹.gradle目錄的組織。

1 .gradle頂級目錄

目錄| 功能

caches | gradle緩存目錄

daemon | daemon日志目錄

native | gradle平台相關目錄

wrapper | gradle-wrapper下載目錄

2 caches目錄

目錄 | 功能

2.14.1 | gradle程序的腳本(gradle程序版本)

3.2.1 | gradle程序的腳本(gradle程序版本)

jars-1 | ?

jars-2 | ?

modules-2 | 下載緩存目錄

2.1 caches/modules-2目錄

目錄 | 功能

files-2.1 | gradle下載的jar/aar目錄

metadata-2.16 | gradle-2.14.1的描述文件?

metadata-2.23 | gradle-3.2.1的描述文件?

2.1.1 files-2.1的目錄組織(jar/aar都下載到這里)

${org}/${package}/${version}/${shanum1}/${package-version}.pom
${org}/${package}/${version}/${shanum2}/${package-version}.jar

例如:

#jcenter上jar的路徑 https://jcenter.bintray.com/com/android/tools/lint/lint-api/25.1.3/lint-api-25.1.3.jar #對應的緩存目錄為 .gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.3/${shasum1}/lint-api-25.1.3.jar #看下這個目錄下有什么? ~ find .gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.3/ -type f #除了jar包還有pom,用於描述jar。 .gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.3/14c6a94811fb8114a61b8f3ab29214f9466b5c59/lint-api-25.1.3.jar .gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.3/c4844e26d84dd1f450f90d89d7e2d2d09f52760/lint-api-25.1.3.pom #看下jar的shasum ~ shasum .gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.3/14c6a94811fb8114a61b8f3ab29214f9466b5c59/lint-api-25.1.3.jar 14c6a94811fb8114a61b8f3ab29214f9466b5c59 .gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.3/14c6a94811fb8114a61b8f3ab29214f9466b5c59/lint-api-25.1.3.jar #即目錄名。 

注意:創建jcenter時,對於jar包,可以沒有pom,但是如果使用aar,則必須有pom,所以最好是每個版本都有個pom。因為pom中也描述了依賴關系。

3 daemon目錄(無需離線)

用於存放gradle daemon的運行日志。按gradle程序版本存放。

目錄 | 功能

2.14.1 | gradle-2.14.1運行的日志

3.2.1 | gradle-3.2.1運行的日志

4 native目錄(無需離線)

用於存放平台相關(Win/Linux/Mac)的庫。

目錄 | 功能

19 | gradle-2.14.1對應的lib目錄,按平台存放,如osx-amd64

21 | gradle-3.2.1對應的lib目錄,按平台存放,如osx-amd64

jansi | ?

5 wrapper目錄

用於存放gradle-wrapper下載gradle的zip包和解壓后的文件夾。 
wrapper的目錄規則是 
wrapper/dists/gradle-2.14.1-all/${base36}/gradle-2.14.1-all.zip 
wrapper/dists/gradle-2.14.1-all/${base36}/gradle-2.14.1-all.zip.lck 
wrapper/dists/gradle-2.14.1-all/${base36}/gradle-2.14.1-all.zip.ok

其中base36的規則為:

從gradle-wrapper的jar包中提取的Java代碼如下:

import java.math.BigInteger; import java.security.MessageDigest; public class Hash { public static void main(String[] args) { try { MessageDigest messageDigest = MessageDigest.getInstance("MD5"); byte[] bytes = args[0].getBytes(); messageDigest.update(bytes); String str = new BigInteger(1, messageDigest.digest()).toString(36); System.out.println(str); } catch (Exception e) { throw new RuntimeException("Could not hash input string.", e); } } } 

c++跟java代碼見

6. 使用.gradle/caches/modules-2創建jcenter的方法

以下是mirror.sh,我把它放在.gradle目錄下。運行腳本會在.gradle目錄下生成jcenter目錄。把它移走或直接把jcenter目錄加入http服務器即可。

目前我的做法是在本地使用gradle編譯一次,然后把gradle下載下來的jar/aar/pom全部提交到版本管理,然后由持續集成去拉版本庫上的.gradle目錄,然后生成jcenter提供給內網編譯服務器。

#!/bin/bash #use .gradle/caches/modules-2/files-2.1/ to create jcenter SHPATH=$(cd "$(dirname "$0")"; pwd) DIR="${SHPATH}/caches/modules-2/files-2.1/" DIR_LENGTH=${#DIR} if [ `uname` = "Darwin" ]; then #mac will add "/" DIR_LENGTH=$((DIR_LENGTH+1)) fi rm -rf ${SHPATH}/jcenter/* find ${DIR} -type f | grep -Ev "DS_Store" | while read line do SRC=${line} URL=${line:${DIR_LENGTH}} ORG=${URL%%/*} URL=${URL#*/} MODULE=${URL%%/*} URL=${URL#*/} REVISION=${URL%%/*} URL=${URL#*/} SHA1=${URL%%/*} URL=${URL#*/} FILE=${URL} #echo "ORG=$ORG, MODULE=$MODULE, REVISION=$REVISION, SHA1=$SHA1, FILE=$FILE" DST=${SHPATH}/jcenter/${ORG//.//}/${MODULE}/${REVISION}/${FILE} echo "$DST" mkdir -p `dirname ${DST}` if [ ! -f ${DST} ]; then cp -a ${SRC} ${DST} fi done 

另外,上面提到aar有可能會因為缺失pom導致無法使用,我還寫了一個腳本,也是放在.gradle目錄下,用於修復aar問題。本地運行時,可以只運行這個腳本,因為它會順路執行上面的腳本。

以下是fix_aar_cache.sh的內容:

#!/bin/bash SHPATH=$(cd "$(dirname "$0")"; pwd) SRC_DIR=${SHPATH}/jcenter CACHE_DIR="${SHPATH}/caches/modules-2/files-2.1/" ${SHPATH}/mirror.sh > /dev/null DIR_LENGTH=${#SRC_DIR} if [ `uname` = "Darwin" ]; then #mac will add "/" DIR_LENGTH=$((DIR_LENGTH+1)) fi find ${SRC_DIR} -name "*.aar" | while read line do SRC=${line} LOCAL_POM=${SRC/.aar/.pom} if [ -f ${LOCAL_POM} ]; then continue fi echo "$LOCAL_POM not found" URL=${line:${DIR_LENGTH}} URL=${URL/.aar/.pom} REMOTE_POM=http://maven.aliyun.com/nexus/content/repositories/jcenter/${URL} REMOTE_POM_SHA1=${REMOTE_POM}.sha1 SHA1=`wget -q -O- ${REMOTE_POM_SHA1}` SHA1=${SHA1:2} #remove additional \r\n echo $SHA1 #reverse to get it FILE=${URL##*/} URL=${URL%/*} REVISION=${URL##*/} URL=${URL%/*} MODULE=${URL##*/} URL=${URL%/*} ORG=${URL} echo "ORG=$ORG, MODULE=$MODULE, REVISION=$REVISION, FILE=$FILE" #org /->. DST=${CACHE_DIR}/${ORG//\//\.}/${MODULE}/${REVISION}/${SHA1}/${FILE} echo "$DST" mkdir -p `dirname ${DST}` if [ ! -f ${DST} ]; then wget -O ${DST} ${REMOTE_POM} fi done


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM