不修改settings.gradle添加Gradle项目依赖方法及当前依赖问题分析
问题背景
我拥有一组应用程序及依赖库,结构如下(每个模块均包含src/目录与build.gradle文件):
appa/ appb/ libx/ liby/ libz/
当前各模块build.gradle中的依赖声明如下:
appa/build.gradle:compile "com.asdf:libx:1.0" compile "com.asdf:liby:1.0"appb/build.gradle:compile "com.asdf:liby:1.0"liby/build.gradle:compile "com.asdf:libz:1.0"
现咨询两个技术问题:
- 如何在不修改
settings.gradle文件的情况下添加Gradle项目依赖? - 当前这种依赖声明方式存在什么问题?
问题1:不修改settings.gradle添加Gradle项目依赖
其实Gradle的核心逻辑里,settings.gradle是用来把本地模块纳入构建生命周期的关键配置——如果不在这里声明子项目,Gradle根本不知道这些本地模块的存在,所以严格来说没法直接声明“本地项目依赖”。不过有两个实用的变通方案可以绕开修改根目录的settings.gradle:
复合构建(Composite Builds)——官方推荐方案
这是最优雅的解决方式,不需要改动主项目的任何配置,只需要在构建时通过命令行参数引入本地模块,或者在模块的配置里做依赖替换。举个例子,如果你想让appa使用本地的libx和liby,只需要运行:gradle :appa:build --include-build ../libx --include-build ../libyGradle会自动识别本地模块的坐标,把远程依赖
com.asdf:libx:1.0替换成本地的libx项目,同时还会自动处理传递依赖(比如liby依赖的libz也会自动关联本地版本)。你也可以把这些配置写到一个单独的settings.gradle文件里,或者在模块的build.gradle里通过dependencySubstitution来固定替换规则,避免每次都输命令行参数。文件依赖引用本地构建产物
先手动构建本地模块(比如执行../libx/gradle build得到jar包),然后在appa/build.gradle里直接引用这个jar文件:compile files('../libx/build/libs/libx-1.0.jar')但这种方式非常繁琐,每次修改本地模块都要重新构建,而且没法自动处理传递依赖,只适合临时测试场景,不推荐日常开发用。
总结一下:复合构建是最优解,既不用改主项目的settings,又能享受本地项目依赖的所有优势。
问题2:当前依赖声明方式的问题
你现在所有依赖都用远程Maven坐标(com.asdf:xxx:1.0)声明,但本地明明有对应的模块,这种方式会带来不少问题:
本地开发效率极低:每次修改
libx、liby这些本地库,都要先把它们发布到远程仓库或者本地Maven仓库,才能让appa或appb引用到修改后的代码,开发流程非常割裂,没法实时看到修改效果。依赖一致性风险:如果远程仓库里的依赖版本被更新,或者本地构建的版本和远程仓库的版本不一致,很可能导致本地运行的结果和CI构建的结果不一样,出现难以排查的“本地正常线上崩”的bug。
传递依赖管理混乱:比如
appa依赖liby,liby依赖libz,远程依赖的传递依赖可能和其他依赖版本冲突,而且你没法直接调试本地的传递依赖模块,排查问题时非常麻烦。无法利用增量构建优势:如果是本地项目依赖,Gradle会自动检测模块间的代码变化,只构建修改过的部分,构建速度会快很多;但用远程依赖的话,每次都要校验缓存或者重新下载,完全享受不到Gradle的增量构建优化。
另外还要提一句:compile配置已经在Gradle 3.4版本之后被废弃了,官方推荐用implementation或者api来代替,这样能更好地控制依赖的可见性,避免不必要的依赖泄露到上层模块。
内容的提问来源于stack exchange,提问作者Krease

