如何在多模块项目中构建并使用Gradle插件?
整体概述
我有一个被其他项目作为依赖的库,这个库对所有依赖它的项目有一些和test suites相关的配置要求。于是我写了一个plugin来自动完成这些配置,依赖项目只需要添加这个插件就能搞定配置:
plugins { id("org.my.gradle.plugin") version "internal" }
项目结构
+ root + my-api/...(独立模块;无依赖,主要是接口定义) + my-implementation/...(依赖my-api,通过`plugins { id("org.my.plugin") }`使用`my-gradle-plugin`) + my-gradle-plugin/...(插件模块本身) + build.gradle.kts plugins { `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 } } } + build.gradle.kts // 包含共享的任务配置和仓库配置(mavenLocal、maven(xyz)、mavenCentral()) + gradle.properties - 仅配置了"version=0.0.3-SNAPSHOT" + settings.gradle.kts pluginManagement { 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) } } } }
问题描述
这个插件作为独立项目时运行正常,但这样会增加工作流程的复杂度,所以我想把它整合到同一个多模块项目里。但遇到了问题:Gradle似乎不知道要先构建这个插件才能让其他模块使用它,报错信息如下:
* Where: Build file '/workspace/my-implementation/build.gradle.kts' line: 3 * 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(file:/home/jenkins/.m2/repository/) maven(https://xyz) Gradle Central Plugin Repository MavenRepo
疑问
我知道spring-boot-gradle-plugin是Spring Boot多模块Gradle项目的一部分,并且能在项目内部被直接使用,但没找到实现的关键配置。请问我遗漏了什么配置或者步骤?
解决方案
要让多模块项目里的Gradle插件能被其他模块直接使用,核心是让Gradle在解析插件时能找到本地构建的插件产物,而不是只去远程仓库查找。以下是两种可行的配置方式:
方式一:使用复合构建(推荐)
Gradle的复合构建可以直接将插件模块纳入项目构建流程,自动处理依赖顺序,无需额外发布配置。修改settings.gradle.kts:
pluginManagement { 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") include(":my-api") include(":my-implementation")
这样Gradle会自动识别插件模块,在构建my-implementation前先构建my-gradle-plugin,并且能直接解析插件ID。
方式二:本地发布插件并配置仓库引用
如果不想用复合构建,可以让插件构建后发布到本地临时仓库,再让其他模块从该仓库拉取插件:
配置插件模块发布到本地临时仓库
修改my-gradle-plugin/build.gradle.kts,添加本地发布配置:plugins { `java-gradle-plugin` `maven-publish` } publishing { repositories { maven { url = uri("$buildDir/repos") // 发布到模块的build/repos目录 } } } 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 } } }在settings.gradle.kts中添加临时仓库引用
在pluginManagement的仓库列表里添加插件模块的临时发布仓库:pluginManagement { repositories { mavenLocal() // 添加插件模块的临时发布仓库 maven { url = uri("my-gradle-plugin/build/repos") } maven { url = uri("https://xyz") } gradlePluginPortal() mavenCentral() } resolutionStrategy { val version: String by settings eachPlugin { if (requested.id.id == "org.my.gradle.plugin") { useVersion(version) } } } } include(":my-gradle-plugin") include(":my-api") include(":my-implementation")确保插件先被构建
在根项目的build.gradle.kts中添加构建依赖,保证my-implementation构建前先完成插件的发布:subprojects { if (name == "my-implementation") { tasks.withType<org.gradle.api.tasks.compile.JavaCompile> { dependsOn(":my-gradle-plugin:publishToMavenLocal") } } }
内容的提问来源于stack exchange,提问作者tftd

