如何在多模块项目中构建和使用 gradle 插件?

tft*_*ftd 5 java gradle gradle-plugin gradle-kotlin-dsl

大局观

我有一个库,用作其他项目的依赖项。该库有一些与test suites每个项目相关的配置要求,具体取决于它。这就是为什么我创建了一个plugin为我配置这些插件的原因,这样我就可以添加插件并完成它:

plugins {
   id("org.my.gradle.plugin") version "internal"
}
Run Code Online (Sandbox Code Playgroud)

项目结构

+ root
  + my-api/... (self-sustained; doesn't depend on anything, pretty much interfaces)
  + my-implementation/... (depends on my-api and `my-gradle-plugin` via `plugins { id("org.my.plugin") }`)
  + my-gradle-plugin/... (the plugin itself)
    + 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 // a bunch of shared task configurations and some repository configuration (mavenLocal, maven(xyz), mavenCentral())
  + gradle.properties - contains only "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)
                }
            }
        }
    }

Run Code Online (Sandbox Code Playgroud)

问题

如果它是一个单独的独立项目,该插件可以正常工作。不幸的是,这使我的工作流程变得复杂,因此我认为我可以将它放在同一个多模块项目中。

不幸的是,我遇到了问题,因为gradle似乎不知道它需要构建plugin才能将use其放入其中一个模块中,因此我得到:

* 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


Run Code Online (Sandbox Code Playgroud)

为什么会失败?

我知道这spring-boot-gralde-plugin是 spring boot 多模块 gradle 项目的一部分,并且在项目本身中使用。不幸的是,我一直无法弄清楚让它发挥作用的“魔术”是什么。

我在这里缺少什么想法吗?

tft*_*ftd 6

好吧,这花了我大半天的时间,但我终于弄清楚了。

为了在同一存储库中使用该插件,您必须settings.gradle.ktsplugin. 这将plugin构建与其余模块分开。然后您可以includeBuild()在内部使用pluginManagement来强制构建插件,然后再执行其他操作:

// ./root/settings.kotlin.kts

rootProject.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)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后您就可以毫无问题地使用该插件:

plugins {
   id("org.my.gradle.plugin") version "internal"
}
Run Code Online (Sandbox Code Playgroud)

我使用的是 gradle 7.5+,所以不确定这是否适用于旧版本。

文档还在这里提到了这一点: https: //docs.gradle.org/7.6/userguide/composite_builds.html#included_plugin_builds

  • 很好的答案!我认为 Stackoverflow 需要“拍拍自己的后退按钮”,因为这种情况下没有其他人发表评论或试图提供帮助,而你最终却回答了自己的复杂问题。 (3认同)