如何让 Gradle Plugin 与 Library 共存
当开发一个 Android Library 时,如果还同时还要提供相应的 __Gradle Plugin__,对于 Gradle 新手来说,要在一个 Gradle 工程中同时集成 Android Library__,__Gradle Plugin 和 Example App 三个模块,并不是一件很容易的事,主要的问题在于 Android App 模块中无法引用同一个工程中的 Gradle Plugin 模块,这是因为 Gradle Plugin 需要先于所有的工程进行配置和编译,所以,很多工程师都会将 Gradle Plugin 作为一个独立的工程进行开发和发布,这对于频繁地开发和调试 Gradle Plugin 的工程师来说,是非常的痛苦,每次修改了 Gradle Plugin 都要先发布到 __Maven Local__,然后再跨工程进行调试,效率极低,那有什么优雅的解决方案呢?
buildSrc 模块
要让 Android App 能引用到同一个工程中的 Gradle Plugin 模块,那么,这个 Gradle Plugin 模块就不能是一个普通的模块,正好 Gradle 提供了 buildSrc 的机制,Gradle 默认会将工程根目录下的 buildSrc 目录作为 Composite Build 自动编译和测试,并将其产物添加到 buildscript 的 classpath 中,这样就可以访问到 buildSrc 中定义的 Gradle Plugin 了。
虽然引用 Gradle Plugin 的问题解决了,但是,想要同时发布同一个工程中的 Gradle Plugin 模块和 Android Library 模块是一个问题,因为对于 buildSrc 来说,虽然是在同一个工程中,但其实在 Gradle 看来,它是一个完全隔离的工程,这就意味着:
- buildSrc 模块与普通模块不能同时进行发布
- 所有的配置和属性都不能在 buildSrc 和普通模块间共享,例如:版本号
那如何才能上述的问题呢?
影子模块
要想「鱼和熊掌兼得」,就必须将 buildSrc 模块变成一个普通模块,所以,我们可以再创建一个普通的 Java/Kotlin Library 模块,用来解决 Gradle Plugin 的发布问题,工程目录结构如下:
1 | . |
但问题是,如何让这个普通模块共享 buildSrc 中的代码呢?
软链接
熟悉 Linux 的用户可能会想到一个比较便捷的方式 —— 软链接(Soft Link),有点类似于 Windows 中的「快捷方式」,通过 ln
命令来创建,我们可以在 plugin 模块下创建一个 src 的软链接到 __buildSrc/src__:
1 | $ cd plugin |
工程结构如下所示:
1 | . |
这样就很好的解决了普通 Gradle 模块与 buildSrc 模块共享代码的问题了。
Source Set
由于存在平台间的差异性,例如 Windows 和 *nix 系统之间是否都能很好的兼容软链接,不是很确定(还未在 Windows 上测试过),有没有一种兼容性更好的方案呢?答案是肯定的 —— __Source Set__,我们可以为 plugin 模块配置额外的 SourceSet :
1 | sourceSets { |
这样就完美的解决了所有问题,对于版本号的问题,我们可以在根目录下的 build.gradle.kts 中通过 allprojects
或者 subprojects
来统一配置:
1 | allprojects { |
所以,plugin 模块用来解决 Gradle Plugin 的发布问题,而 buildSrc 用来解决同一个工程中的 Gradle Plugin 的引用问题,plugin 模块与 buildSrc 模块共享同一份代码,但 build.gradle.kts 除外,稍微有点细微的差别:
- 由于 buildSrc 是一个完全独立的工程,如果使用
plugins
DSL 来启用插件需要指定版本号 - plugin 模块中使用
plugins
DSL 来启用插件不用指定版本号(因为在根目录中的 build.gradel.kts 已经指定过) - buildSrc 模块不需要发布,所以,不需要启用
maven-publish
等跟发布相关的插件
buildSrc/build.gradle.kts
1 | plugins { |
plugin/build.gradle.kts
1 | plugins { |
- 本文链接:https://johnsonlee.io/2021/10/06/integrate-gradle-plugin-and-library-into-one-project/
- 版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。