Gradle 设置全局镜像源

复制 init.gradle.kts 文件到 Windows 的 %USERPROFILE%/.gradle 或者 Linux 的 ~/.gradle 目录下。也可以直接复制文末的代码为 init.gradle.kts


Gradle 不支持镜像源的直接设置,只能通过 maven() 方法设置一个新的 Maven 仓库地址。

在 init.gradle 中调用 maven() 会导致镜像仓库排在上游仓库之后,会导致Gradle 优先使用上游仓库。如果直接删除上游仓库又会出现新的问题。Maven 镜像源和上游仓库并不是完全实时同步的,可能会缺失某些文件,特别是一些刚发布的包。所以上游仓库必须保留并且需要排在镜像仓库之后。

在使用过程中发现阿里云的 Maven 镜像源仍然会出现找不到文件的错误。排查之后发现阿里云镜像源的某个包竟然只有 POM 文件而没有 JAR 文件。在这种情况下 Gradle 找到了 POM 文件就会仅使用阿里云镜像源,然后找不到 JAR 文件报错,而不会继续使用上游仓库。查阅 Gradle 文档之后,发现有个 artifactUrls() 方法可以设置 Maven 仓库的除 POM 文件之外的其他文件下载地址。这样就可以通过在镜像仓库中将上游仓库地址设置为Artifact URL解决这个问题。

普通的 Java 或 Kotlin 项目默认是在 build.gradle 里设置 Maven 仓库地址,所以在 init.gradle 里需要在 allprojects 代码块中设置镜像源。而 Android 项目默认都是在 settings.gradle 的 pluginManagementdependencyResolutionManagement 代码块中设置 Maven 仓库地址。仅在 allprojects 中设置镜像源没有用。所以还需要在 settingsEvaluated 代码块中进行设置。

一些旧的项目在添加 Google Maven 仓库时,直接使用 maven("https://maven.google.com") 而不使用 google() 方法。构建项目时会一直卡在 Building 的状态,并且没有任何提示。maven.google.com 这个域名在国内是 ping 不通的。而如果使用 google() 方法,Gradle 会使用 "https://dl.google.com/dl/android/maven2",这个链接在国内可以直连。所以需要将上游 Google 仓库的 "https://maven.google.com" 替换为 "https://dl.google.com/dl/android/maven2"。

解决一系列问题之后,最终的 init.gradle 完成了。Gradle 同时支持 Groovy DSL(.gradle) 和 Kotlin DSL(.gradle.kts)。我选择后者编写 init.gradle.kts。由于 Gradle 直接两种 DSL 语言的混用,所以如果之后构建 Groovy DSL 形式的 Gradle 项目,也不需要额外再编写 init.gradle。


// https://gist.github.com/mkckr0/97ec5b0d99feede4c19ee6f905d5e722  val repoMirrorMap = mapOf(     "https://repo.maven.apache.org/maven2" to "https://maven.aliyun.com/repository/central",     "https://dl.google.com/dl/android/maven2" to "https://maven.aliyun.com/repository/google",     "https://plugins.gradle.org/m2" to "https://maven.aliyun.com/repository/gradle-plugin",     "https://jcenter.bintray.com" to "https://maven.aliyun.com/repository/jcenter", ) val repoReplaceMap = mapOf(     "https://maven.google.com" to "https://dl.google.com/dl/android/maven2" )  fun RepositoryHandler.setMirrors() {     all {         if (this is MavenArtifactRepository && !name.endsWith("Origin")) {             val originName = name             var originUrl = url.toString().trimEnd('/')              // do replace             repoReplaceMap[originUrl]?.let { newUrl ->                 originUrl = newUrl                 setUrl(originUrl)             }              // do mirror             repoMirrorMap[originUrl]?.let { newUrl ->                 // replace into mirror repo                 setUrl(newUrl)                 // add origin repo to find missing jars                 artifactUrls(originUrl)                 // keep origin repo to find missing POM                 maven(originUrl) { name = "$originName Origin" }             }         }     }     printRepos() }  fun RepositoryHandler.printRepos() {     all {         if (this is MavenArtifactRepository) {             println("Maven Repo: name="$name", url=$url, artifacts=${artifactUrls}")         }     } }  settingsEvaluated {     pluginManagement {         repositories {             setMirrors()         }     }     dependencyResolutionManagement {         @Suppress("UnstableApiUsage")         repositories {             setMirrors()         }     } }  allprojects {     buildscript {         repositories {             setMirrors()         }     }     repositories {         setMirrors()     } } 

发表评论

评论已关闭。

相关文章