Gradle私有子模块依赖嵌套目录公共子模块的优化方案咨询
问题
我在企业实习,团队的基础/common模块托管在GitHub开源仓库,私有模块部署在自建服务器,用Gradle构建并自研了构建插件。我常做模块版本迁移,需要将私有模块的远程依赖改为本地模块依赖,但公共模块嵌套在modules/common目录下,私有模块无法直接引用。
现有配置与结构
私有模块build.gradle
plugins { id 'com.company_name.app' } company_name { title "company_name :: module name" description "company_name module" } dependencies { api "com.company.apps:common-module-1:6.1.0" api "com.company.apps:common-module-2:6.1.0" }
项目目录结构
base app ├─build.gradle ├─settings.gradle ┊ └─modules ├─proprietary module │ └─build.gradle └─common ├─common module 1 │ └─build.gradle │ ├─common module 2 │ └─build.gradle │ ├─common module 3 │ └─build.gradle ┊ └─common module n └─build.gradle
Base app的build.gradle片段
dependencies { gradle.appModules.each { dir -> implementation project("modules:$dir.name") } }
settings.gradle动态加载模块代码
def modules = [] file("modules").traverse(type: groovy.io.FileType.DIRECTORIES, maxDepth: 1) { it -> if (new File(it, "build.gradle").exists()) { modules.add(it) } } gradle.ext.appModules = modules modules.each { dir -> include "modules:$dir.name" project("modules:$dir.name").projectDir = dir }
遇到的问题
当把私有模块依赖改为本地模块引用时:
dependencies { api project("modules:common-module-1") api project("modules:common-module-2") }
会出现无法找到或加载公共模块的错误。目前临时方案是修改Base app的build.gradle:
dependencies { gradle.appModules.each { dir -> if (dir.name.startsWith('common')) { implementation project("modules:common:$dir.name") } else { implementation project("modules:$dir.name") } } }
但每次克隆仓库都要改基础文件,想找更优方案,比如用Git忽略的文件简化工作。
解决方案
方案1:修改settings.gradle自动加载common子模块
调整settings.gradle的遍历逻辑,让它自动加载modules/common下的所有子模块,这样这些模块会被Gradle注册,私有模块就能直接引用。该方案可提交至团队主分支,一次性解决所有人的问题。
修改后的settings.gradle:
def modules = [] // 遍历modules下一级目录 file("modules").traverse(type: groovy.io.FileType.DIRECTORIES, maxDepth: 1) { it -> if (new File(it, "build.gradle").exists()) { modules.add(it) } // 如果是common目录,遍历其下的子模块并注册 if (it.name == "common") { file(it).traverse(type: groovy.io.FileType.DIRECTORIES, maxDepth: 1) { commonSub -> if (new File(commonSub, "build.gradle").exists()) { def modulePath = "modules:common:${commonSub.name}" include modulePath project(modulePath).projectDir = commonSub modules.add(commonSub) } } } } gradle.ext.appModules = modules // 处理非common的顶层模块 modules.each { dir -> if (dir.parentFile.name != "common") { def modulePath = "modules:${dir.name}" include modulePath project(modulePath).projectDir = dir } }
修改后,私有模块可直接用project("modules:common:common-module-1")引用本地公共模块,无需改动其他文件。
方案2:用Git忽略的属性文件切换依赖源
通过本地属性文件控制依赖类型,避免修改核心文件,适合个人本地调试场景。
- 在项目根目录创建
local.gradle.properties,并将该文件名加入.gitignore:
# 是否使用本地common模块 useLocalCommonModules=true
- 修改私有模块的build.gradle,根据属性动态切换依赖:
plugins { id 'com.company_name.app' } company_name { title "company_name :: module name" description "company_name module" } // 加载本地属性文件 def localProps = new Properties() def localPropsFile = file("../local.gradle.properties") if (localPropsFile.exists()) { localProps.load(localPropsFile.newDataInputStream()) } def useLocal = localProps.getProperty("useLocalCommonModules", "false").toBoolean() dependencies { if (useLocal) { api project("modules:common:common-module-1") api project("modules:common:common-module-2") } else { api "com.company.apps:common-module-1:6.1.0" api "com.company.apps:common-module-2:6.1.0" } }
- 配合方案1修改settings.gradle确保common子模块被加载。克隆仓库后,只需创建这个本地属性文件即可切换依赖源,无需改动核心文件。
方案3:添加Git忽略的本地构建脚本
创建本地构建脚本覆盖Base app的依赖逻辑,不修改核心文件,适合个人定制化需求。
- 在项目根目录创建
local-build.gradle,并将该文件名加入.gitignore:
// 覆盖Base app的依赖逻辑,正确识别common子模块路径 dependencies { gradle.appModules.each { dir -> def modulePath = dir.parentFile.name == "common" ? "modules:common:${dir.name}" : "modules:${dir.name}" implementation project(modulePath) } }
- 修改Base app的build.gradle,引入这个本地脚本(仅当文件存在时生效):
// 保留原有逻辑,优先加载本地脚本(如果存在) dependencies { gradle.appModules.each { dir -> implementation project("modules:$dir.name") } } def localBuildFile = file("local-build.gradle") if (localBuildFile.exists()) { apply from: localBuildFile }
克隆仓库后,只需创建这个本地脚本就能自动适配common子模块的依赖路径,无需改动核心文件。
内容的提问来源于stack exchange,提问作者JustAnotherDev
相关产品推荐
相关产品推荐

