
本文探讨了在gradle多模块项目中构建和消费自定义插件时遇到的“插件未找到”问题及其解决方案。核心在于利用gradle的复合构建(composite builds)功能,通过在根项目的`settings.gradle.kts`中使用`includebuild()`指令,并为插件模块提供独立的`settings.gradle.kts`文件,确保插件在被其他模块消费前得到正确构建和解析。这使得插件能够无缝集成到同一项目结构中,简化了开发工作流。
在大型多模块项目中,为了统一和简化特定模块的构建配置,开发自定义Gradle插件是一种常见且高效的实践。例如,一个库可能需要针对其依赖项目配置特定的测试套件,此时一个自定义插件就能自动化这些配置。然而,当尝试在同一个多模块项目内部构建并消费这个插件时,开发者可能会遇到“插件未找到”的问题。
挑战:在多模块项目中消费内部插件
通常,一个Gradle多模块项目的结构可能如下所示:
+ root + my-api/ // 接口模块 + my-implementation/ // 实现模块,依赖my-api并尝试消费自定义插件 + my-gradle-plugin/ // 自定义Gradle插件模块 + build.gradle.kts + build.gradle.kts // 根项目构建脚本 + settings.gradle.kts // 根项目设置脚本 + gradle.properties
其中,my-gradle-plugin模块负责定义和实现自定义插件。其build.gradle.kts可能包含如下配置:
// my-gradle-plugin/build.gradle.ktsplugins { `java-gradle-plugin` `maven-publish`}gradlePlugin { plugins { create("org.my.gradle.plugin") { id = "org.my.gradle.plugin" group = "org.my.gradle.plugin" implementationClass = "org.my.gradle.plugin.MyGradlePlugin" version = project.version } }}
当my-implementation模块尝试通过plugins { id(“org.my.gradle.plugin”) version “internal” }来应用这个插件时,Gradle可能会报告以下错误:
* What went wrong:Plugin [id: 'org.my.gradle.plugin', version: '0.0.3-SNAPSHOT'] was not found in any of the following sources:- Gradle Core Plugins (plugin is not in 'org.gradle' namespace)- Plugin Repositories (could not resolve plugin artifact 'org.my.gradle.plugin:org.my.gradle.plugin.gradle.plugin:0.0.3-SNAPSHOT') Searched in the following repositories: MavenLocal(...) maven(...) Gradle Central Plugin Repository MavenRepo
这个错误表明Gradle在解析my-implementation模块时,无法在配置的插件仓库中找到org.my.gradle.plugin。问题在于,Gradle默认并不知道my-gradle-plugin模块需要先被构建成一个可用的插件,才能在同一个构建过程中被其他模块消费。它会将插件视为外部依赖,尝试从远程或本地Maven仓库中查找。
稿定抠图
AI自动消除图片背景
76 查看详情
解决方案:利用Gradle复合构建(Composite Builds)
解决这个问题的关键在于利用Gradle的复合构建(Composite Builds)功能。复合构建允许将多个独立的Gradle构建(包括插件项目)组合成一个单一的构建。这样,主构建就可以在本地解析和使用“包含”的构建所提供的插件或项目。
具体步骤如下:
为插件模块创建独立的settings.gradle.kts:在my-gradle-plugin模块的根目录下创建一个空的settings.gradle.kts文件。这个文件将把my-gradle-plugin标记为一个独立的Gradle构建,使其能够被主项目作为复合构建的一部分来“包含”。即使是空文件,它的存在也是必要的。
+ root + my-gradle-plugin/ + build.gradle.kts + settings.gradle.kts // 新增文件
在根项目的settings.gradle.kts中声明includeBuild():在主项目的settings.gradle.kts中,使用includeBuild()指令将my-gradle-plugin模块作为复合构建包含进来。这会告诉Gradle,在构建主项目之前,需要先构建my-gradle-plugin。
// ./root/settings.gradle.ktsrootProject.name = "root-project"// 包含其他子模块include("my-api", "my-implementation")// 关键:将插件模块作为复合构建包含进来pluginManagement { includeBuild("my-gradle-plugin") // 指向插件模块的路径 repositories { mavenLocal() maven { url = uri("https://xyz") } // 你的私有仓库 gradlePluginPortal() mavenCentral() } resolutionStrategy { val version: String by settings eachPlugin { // 确保自定义插件使用根项目定义的版本 if (requested.id.id == "org.my.gradle.plugin") { useVersion(version) } } }}
includeBuild(“my-gradle-plugin”): 这行代码指示Gradle将my-gradle-plugin目录下的项目视为一个独立的构建,并将其纳入当前构建的范围。Gradle会确保在需要该插件时,它已经被构建并可用。pluginManagement块中的resolutionStrategy: 这是一个最佳实践,确保你的自定义插件能够正确解析到根项目gradle.properties中定义的版本(例如version=0.0.3-SNAPSHOT),而不是尝试从远程仓库查找特定版本。version: String by settings用于从settings.gradle.kts中获取gradle.properties定义的属性。
消费插件:完成上述配置后,my-implementation模块就可以像消费任何其他插件一样,直接应用自定义插件了。
// my-implementation/build.gradle.ktsplugins { id("org.my.gradle.plugin") version "internal" // "internal" 或具体的版本号,取决于resolutionStrategy}
这里使用”internal”作为版本号,是因为pluginManagement中的resolutionStrategy会强制使用根项目定义的版本。如果你的resolutionStrategy配置不同,你可能需要指定实际的版本号。
注意事项
Gradle版本兼容性: 上述方法在Gradle 7.5及更高版本中验证有效。对于更早的Gradle版本,行为可能有所不同,建议查阅对应版本的Gradle文档。插件模块的独立性: 在插件模块内部添加settings.gradle.kts,即使是空文件,也至关重要。它将该模块提升为一个独立的Gradle构建,使得includeBuild()能够识别并管理它。版本管理: 推荐使用resolutionStrategy来统一管理自定义插件的版本,使其与主项目的版本保持一致,避免因版本不匹配导致的问题。
通过采用复合构建和includeBuild()机制,开发者可以在一个统一的多模块项目中无缝地构建和消费自定义Gradle插件,极大地简化了开发和维护工作流,提升了项目的模块化和可配置性。
以上就是在Gradle多模块项目中构建与消费自定义插件的指南的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1051520.html
微信扫一扫
支付宝扫一扫