Android-脚本-Groovy-01-项目本地缓存依提取到本地Maven

65 阅读2分钟

用于将项目依赖从 Gradle 的本地缓存复制到本地 Maven 仓库(~/.m2/repository),从而实现依赖的本地 Maven 化共享。

  • (1) 项目根目录的build.gradle文件下,新增该任务
/**
 * 任务:exportDependenciesToMavenLocal
 * 功能:将Gradle缓存中的所有依赖导出到Maven本地仓库
 */
task exportDependenciesToMavenLocal {
    group = 'Build Setup'
    description = '将Gradle缓存中的所有依赖导出到Maven本地仓库'

    doLast {
        // 定义路径
        def gradleCache = new File(System.getProperty("user.home"), ".gradle/caches/modules-2/files-2.1")
        def mavenRepo = new File(System.getProperty("user.home"), ".m2/repository")

        // 检查Gradle缓存是否存在
        if (!gradleCache.exists()) {
            println "Gradle缓存目录不存在: ${gradleCache.absolutePath}"
            return
        }

        println "开始从 ${gradleCache.absolutePath} 导出到 ${mavenRepo.absolutePath}"

        // 计数器
        def copiedCount = 0
        def skippedCount = 0

        // 遍历Gradle缓存目录,按照group/artifact/version结构
        gradleCache.eachFileRecurse { file ->
            // 只处理文件,且是需要的类型
            if (file.isFile() && (file.name.endsWith('.jar') || file.name.endsWith('.aar') ||
                                 file.name.endsWith('.pom') || file.name.endsWith('.module'))) {

                try {
                    // 计算相对于缓存根目录的路径
                    def relativePath = gradleCache.toPath().relativize(file.toPath()).toString()
                    // 兼容Windows和Unix路径分隔符
                    def pathParts = relativePath.split("[/\\\\]")

                    // 确保路径至少包含group/artifact/version
                    if (pathParts.length >= 4) {
                        def group = pathParts[0]
                        def artifact = pathParts[1]
                        def version = pathParts[2]
                        def fileName = pathParts[pathParts.length - 1] // 最后一个是文件名

                        // 构建目标目录路径(Maven标准结构)
                        def groupPath = group.replace('.', '/')
                        def destDir = new File(mavenRepo, "${groupPath}/${artifact}/${version}")
                        destDir.mkdirs()

                        // 构建目标文件
                        def destFile = new File(destDir, fileName)

                        // 复制文件(如果目标文件不存在)
                        if (!destFile.exists()) {
                            file.withInputStream { input ->
                                destFile.withOutputStream { output ->
                                    output << input
                                }
                            }
                            println "已复制: ${file.path} -> ${destFile.path}"
                            copiedCount++
                        } else {
                            skippedCount++
                        }
                    }
                } catch (Exception e) {
                    println "处理文件时出错 ${file.path}: ${e.message}"
                }
            }
        }

        println "导出完成!"
        println "  复制文件数: ${copiedCount}"
        println "  跳过文件数: ${skippedCount}"
        println "Maven本地仓库位置: ${mavenRepo.absolutePath}"
    }
}

/**
 * 任务:exportProjectDependenciesToMavenLocal
 * 功能:仅导出项目实际使用的依赖到Maven本地仓库
 */
task exportProjectDependenciesToMavenLocal {
    group = 'Build Setup'
    description = '仅导出项目实际使用的依赖到Maven本地仓库'

    doLast {
        def gradleCache = new File(System.getProperty("user.home"), ".gradle/caches/modules-2/files-2.1")
        def mavenRepo = new File(System.getProperty("user.home"), ".m2/repository")

        if (!gradleCache.exists()) {
            println "Gradle缓存目录不存在: ${gradleCache.absolutePath}"
            return
        }

        println "开始导出项目依赖到 ${mavenRepo.absolutePath}"

        def copiedCount = 0
        def skippedCount = 0

        // 收集项目中使用的所有依赖
        def usedDependencies = [:]

        allprojects { project ->
            project.configurations.matching { it.canBeResolved }.all { configuration ->
                try {
                    configuration.resolvedConfiguration.lenientConfiguration.artifacts.each { artifact ->
                        def component = artifact.id.componentIdentifier
                        if (component.class.name == 'org.gradle.api.artifacts.ModuleComponentIdentifier') {
                            def key = "${component.group}:${component.module}:${component.version}"
                            usedDependencies[key] = [
                                group: component.group,
                                module: component.module,
                                version: component.version,
                                file: artifact.file
                            ]
                        }
                    }
                } catch (Exception e) {
                    println "处理配置 ${configuration.name} 时出错: ${e.message}"
                }
            }
        }

        // 导出收集到的依赖
        usedDependencies.each { key, dep ->
            try {
                // 复制主要构件文件
                if (dep.file.exists()) {
                    def groupPath = dep.group.replace('.', '/')
                    def destDir = new File(mavenRepo, "${groupPath}/${dep.module}/${dep.version}")
                    destDir.mkdirs()

                    def destFile = new File(destDir, "${dep.module}-${dep.version}.${dep.file.extension}")
                    if (!destFile.exists()) {
                        dep.file.withInputStream { input ->
                            destFile.withOutputStream { output ->
                                output << input
                            }
                        }
                        println "已复制构件: ${destFile.path}"
                        copiedCount++
                    } else {
                        skippedCount++
                    }
                }

                // 查找并复制对应的POM和Module文件
                def componentCacheDir = new File(gradleCache, "${dep.group}/${dep.module}/${dep.version}")
                if (componentCacheDir.exists()) {
                    componentCacheDir.eachFile { cacheFile ->
                        def fileName = cacheFile.name
                        if (fileName.endsWith(".pom") || fileName.endsWith(".module")) {
                            def groupPath = dep.group.replace('.', '/')
                            def destDir = new File(mavenRepo, "${groupPath}/${dep.module}/${dep.version}")
                            destDir.mkdirs()

                            def destFile = new File(destDir, fileName)
                            if (!destFile.exists()) {
                                cacheFile.withInputStream { input ->
                                    destFile.withOutputStream { output ->
                                        output << input
                                    }
                                }
                                println "已复制元数据: ${destFile.path}"
                                copiedCount++
                            } else {
                                skippedCount++
                            }
                        }
                    }
                }
            } catch (Exception e) {
                println "导出依赖 ${key} 时出错: ${e.message}"
            }
        }

        println "项目依赖导出完成!"
        println "  复制文件数: ${copiedCount}"
        println "  跳过文件数: ${skippedCount}"
        println "总共处理依赖数: ${usedDependencies.size()}"
    }
}

task exportUnifiedDependencyTree {
    group = "help"
    description = "汇总全项目依赖并导出到根目录文件"

    doLast {
        // 定义输出文件路径:项目根目录下的 all_dependencies.txt
        def outputFile = new File(rootProject.projectDir, "all_dependencies.txt")
        def unifiedDependencies = [:]

        // 1. 收集所有子模块的顶层依赖并去重
        subprojects { subproject ->
            def config = subproject.configurations.findByName('releaseRuntimeClasspath') ?:
                    subproject.configurations.findByName('runtimeClasspath')

            if (config && config.canBeResolved) {
                try {
                    config.resolvedConfiguration.firstLevelModuleDependencies.each { dep ->
                        def key = "${dep.moduleGroup}:${dep.moduleName}"
                        // 如果存在重复库,保留版本号最新的(此处为简单逻辑)
                        if (!unifiedDependencies.containsKey(key)) {
                            unifiedDependencies[key] = dep
                        }
                    }
                } catch (Exception ignored) { }
            }
        }

        // 2. 写入文件
        outputFile.withWriter('UTF-8') { writer ->
            writer.println "=".center(60, "=")
            writer.println "全项目统一依赖报告 (已去重)".center(60)
            writer.println "生成时间: ${new Date().format('yyyy-MM-dd HH:mm:ss')}".center(60)
            writer.println "=".center(60, "=")
            writer.println ""

            if (unifiedDependencies.isEmpty()) {
                writer.println "未发现可解析的依赖。"
            } else {
                def visited = [] as Set
                unifiedDependencies.values().each { dep ->
                    writeDepToFile(dep, 0, visited, writer)
                }
            }
            writer.println "\n" + "=".center(60, "=")
            writer.println "报告结束".center(60)
        }

        println "✅ 依赖树已成功导出至: ${outputFile.absolutePath}"
    }
}

// 递归写入函数
def writeDepToFile(dep, level, visited, writer) {
    def indent = level == 0 ? "" : "  " * level + "└── "
    def depId = "${dep.moduleGroup}:${dep.moduleName}:${dep.moduleVersion}"

    // 处理循环依赖
    if (visited.contains(depId)) {
        writer.println "${indent}${depId} (*)"
        return
    }
    visited.add(depId)

    writer.println "${indent}${depId}"

    dep.children.each { child ->
        writeDepToFile(child, level + 1, visited, writer)
    }
}

  • (2) 项目根目录下,执行命令,进行迁移
 ./gradlew exportDependenciesToMavenLocal 
  • (3) 如果本地缓存不全,可执行下面命令刷新缓存
 ./gradlew build --refresh-dependencies  
  • (4)使用本地maven依赖,来编译项目
 repositories {

      /*  mavenLocal {
            metadataSources {
                mavenPom()
                artifact() // 允许没有 pom 的情况,直接用 jar/aar
            }
        }*/
        mavenLocal()
    }
  • (5)如果还有不全的依赖,可在阿里maven库下载复制到本地maven

仓库服务