简体   繁体   English

gradle插件的版本管理如何封装?

[英]How do I encapsulate version management for gradle plugins?

Problem问题

I have a setup of various distinct repos/projects (ie app1 , app2 , app3 ) that all depend on shared functionality in my base package.我设置了各种不同的回购/项目(即app1app2app3 ),它们都依赖于我的base package 中的共享功能。

The projects also use various other third-party dependencies (ie app1 and app3 use spring, all of them use kotlinx-serialization ).这些项目还使用了各种其他第三方依赖项(即app1app3使用 spring,它们都使用kotlinx-serialization )。 I want to synchronise the versions of all third-party dependencies, so that any project using my base package uses the same version of every third-party dependency.我想同步所有第三方依赖的版本,这样任何使用我的基础 package 的项目都使用相同版本的每个第三方依赖。 However, I don't want to introduce new dependencies to projects that do not use them (ie app2 does not use spring)但是,我不想为不使用它们的项目引入新的依赖项(即app2不使用spring)

Solution attempts解决方案尝试

For libraries , I have been able to solve this with the help of a gradle platform , which does exactly what I want - I specify the versions in my base package, then add the platform as a dependency to my projects and can then simply add dependencies by name (ie implementation("org.springframework.boot:some-package") ) without having to specify a version number, because it uses the provided value from my platform .对于图书馆,我已经能够在 gradle platform的帮助下解决这个问题,这正是我想要的 - 我在我的基础 package 中指定版本,然后将该platform作为依赖项添加到我的项目中,然后可以简单地添加依赖项按名称(即implementation("org.springframework.boot:some-package") )无需指定版本号,因为它使用我的platform提供的值。

However, for plugins , I have not been able to do this.但是,对于插件,我无法做到这一点。 Many libraries come with plugins and naturally the plugin should be at the same version as the library.许多库都带有插件,插件自然应该与库的版本相同。 I have tried various approaches, including writing a standalone plugin, but none have worked.我尝试了各种方法,包括编写一个独立的插件,但都没有奏效。

Current best idea当前最佳创意

I added implementation("org.springframework.boot:spring-boot-gradle-plugin:3.0.2") to the dependencies of my standalone plugin.我将implementation("org.springframework.boot:spring-boot-gradle-plugin:3.0.2")添加到我的独立插件的依赖项中。 Then, I added the following code to my standalone plugin:然后,我将以下代码添加到我的独立插件中:

class BasePlugin : Plugin<Project> {
    override fun apply(target: Project) {
        target.plugins.apply("org.springframework.boot")
    }
}

This works and applies the plugin to my main project at the correct version.这有效并将插件以正确的版本应用于我的主项目。 However, there are 2 major problems with this:但是,这有两个主要问题:

a) Now every project applies the spring plugin, including app2 (which does not use spring). a) 现在每个项目都应用spring插件,包括app2 (没有使用spring)。

b) I have many plugins to manage and no idea how to get the long implementation-string for most of them. b) 我有很多插件要管理,但不知道如何为其中的大多数获取长实现字符串。 I found the "org.springframework.boot:spring-boot-gradle-plugin:3.0.2" by looking up the plugin-id on https://plugins.gradle.org/ and then looking at the legacy plugin application section, which sounds like I am on the wrong track.我通过在https://plugins.gradle.org/上查找插件 ID,然后查看遗留插件应用程序部分,找到了"org.springframework.boot:spring-boot-gradle-plugin:3.0.2" ,听起来我走错了路。

I just want to manage the versions of plugins and libraries of multiple projects/repos in a central place - this feels like a fairly basic use case - why is this so hard?我只想在一个中心位置管理多个项目/存储库的插件和库的版本——这感觉像是一个相当基本的用例——为什么这么难?

I use version numbers in a gradle.properties file for this purpose.为此,我在gradle.properties文件中使用了版本号。 Since the introduction of Gradle version catalogs, my approach is probably a bit out of date, but I'll share it here anyway.自从引入了Gradle版本目录,我的做法可能有点落伍了,不过还是分享一下吧。 It's based on the fact that plugin versions can be managed in settings.gradle.kts by reading values from the properties file.它基于这样一个事实,即可以通过从属性文件中读取值来在settings.gradle.kts中管理插件版本。

In gradle.properties :gradle.properties

springBootVersion=3.0.2

In settings.gradle.kts :settings.gradle.kts

pluginManagement {
    val springBootVersion: String by settings

    plugins {
        id("org.springframework.boot") version springBootVersion
    }
}

And finally in build.gradle.kts :最后在build.gradle.kts中:

plugins {
    id("org.springframework.boot")
}

dependencies {
    val springBootVersion: String by project
    implementation(platform("org.springframework.boot:spring-boot-dependencies:$springBootVersion"))
}

Notice that the plugin version is omitted in the build script because it is already specified in the settings file.请注意,构建脚本中省略了插件版本,因为它已在设置文件中指定。 And note also that the method for accessing the property in the settings script is slightly different from that in the build script.另请注意,设置脚本中访问属性的方法与构建脚本中的略有不同。

a) Now every project applies the spring plugin, including app2 (which does not use spring). a) 现在每个项目都应用spring插件,包括app2 (没有使用spring)。

It is indeed better to avoid applying too many plugins - and that's why Gradle encourages reacting to plugins .避免应用太多插件确实更好——这就是为什么 Gradle 鼓励对插件做出反应

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.*
import org.springframework.boot.gradle.plugin.SpringBootPlugin

class BasePlugin : Plugin<Project> {
    override fun apply(target: Project) {
        // don't apply
        //target.plugins.apply("org.springframework.boot")

        // instead, react!
        target.plugins.withType<SpringBootPlugin>().configureEach {
            // this configuration will only trigger if the project applies both
            // BasePlugin *and* the Spring Boot pluging
        }

        // you can also react based on the plugin ID
        target.pluginManager.withPlugin("org.springframework.boot") {

        }
    }
}

Using the class is convenient if you want to access the plugin, or the plugin's extension, in a typesafe manner.如果您想以类型安全的方式访问插件或插件的扩展,使用 class 会很方便。

You can find the Plugin's class by您可以通过以下方式找到插件的 class

  • looking in the source code for the class that implements Plugin<Project> ,查看实现Plugin<Project>的 class 的源代码,
  • in the plugin's build config for the implementationClass ,在插件的implementationClass构建配置中,
  • or in the published plugin JAR - in the META-INF/gradle-plugins directory there will be a file that has the implementationClass .或者在已发布的插件 JAR 中 - 在META-INF/gradle-plugins目录中将有一个具有implementationClass的文件。

This doesn't help your version alignment problem - but I thought it was worth mentioning!这对您的版本 alignment 问题没有帮助 - 但我认为值得一提!

b) I have many plugins to manage and no idea how to get the long implementation-string for most of them. b) 我有很多插件要管理,但不知道如何为其中的大多数获取长实现字符串。 I found the "org.springframework.boot:spring-boot-gradle-plugin:3.0.2" by looking up the plugin-id on https://plugins.gradle.org/ and then looking at the legacy plugin application section, which sounds like I am on the wrong track.我通过在https://plugins.gradle.org/上查找插件 ID,然后查看遗留插件应用程序部分,找到了"org.springframework.boot:spring-boot-gradle-plugin:3.0.2" ,听起来我走错了路。

You're on the right track with the "long implementation string" as you call it.您所说的“长实施字符串”走在正确的轨道上。 I'll refer to those as the 'Maven coordinates' of the plugin.我将这些称为插件的“Maven 坐标”。

Gradle Plugin Maven Coordinates Gradle 插件 Maven 坐标

The plugin id of the Kotlin JVM plugin is org.jetbrains.kotlin.jvm , but the Maven coordinates are org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0 . Kotlin JVM 插件的插件idorg.jetbrains.kotlin.jvm ,但是Maven坐标org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0

Kotlin JVM 插件的 Gradle 插件门户屏幕截图,展示了如何使用插件 {} 块应用插件,与“传统”`apply(plugin = "org.jetbrains.kotlin.jvm")

The 'legacy' part refers to how the plugins are applied, using the apply(plugin = "...") syntax. 'legacy' 部分指的是如何应用插件,使用apply(plugin = "...")语法。 The new way uses the plugin {} block, but under the hood, both methods still use the Maven coordinates of the plugin.新方法使用plugin {}块,但在幕后,这两种方法仍然使用插件的 Maven 坐标。

If you add those Maven coordinates (with versions) to your Java Platform , then you can import the platform into your project.如果您将这些 Maven 坐标(带版本)添加到您的Java 平台,那么您可以将该平台导入您的项目。 But where?但是哪里?

Defining plugin versions定义插件版本

There are a lot of ways to define plugins, so I'll only describe one, and coincidentally it will be compatible with defining the version using a Java Platform.定义插件的方式有很多种,这里只介绍一种,巧合的是兼容Java平台定义版本。

If you're familiar with buildSrc convention plugins, you'll know that they can apply plugins, but they can't define versions.如果你熟悉 buildSrc 约定插件,你就会知道他们可以应用插件,但他们不能定义版本。

// ./buildSrc/src/main/kotlin/kotlin-jvm-convention.gradle.kts

plugins {
  kotlin("jvm") version "1.8.0" // error: pre-compiled script plugins can't set plugin versions!
}

Instead, plugin versions must be defined in the build config for buildSrc相反,必须在 buildSrc 的构建配置中定义插件版本

// ./buildSrc/build.gradle.kts

plugins {
  `kotlin-dsl`
}

dependencies {
  // the Maven coordinates of the Kotlin JVM plugin - including the version
  implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0")
}

This looks a lot more traditional, and so I hope the next step is clean: use your Java Platform!这看起来更传统,所以我希望下一步是干净的:使用你的 Java 平台!

Applying a Java Platform to buildSrc将 Java 平台应用于 buildSrc

// ./buildSrc/build.gradle.kts

plugins {
  `kotlin-dsl`
}

dependencies {
  // import your Java Platform
  implementation(platform("my.group:my-platform:1.2.3"))

  // no version necessary - it will be supplied by my.group:my-platform
  implementation("org.jetbrains.kotlin:kotlin-gradle-plugin")
}

Note that this same method will also apply if your projects an 'included build' instead of buildSrc.请注意,如果您的项目是“包含构建”而不是 buildSrc,则同样的方法也适用。

Once the plugin versions are defined in ./buildSrc/build.gradle.kts , you can use them throughout your project (whether in convention plugins, or in subprojects), they will be aligned.一旦在./buildSrc/build.gradle.kts中定义了插件版本,您就可以在整个项目中使用它们(无论是在约定插件中还是在子项目中),它们将被对齐。

// ./subproject-alpha/build.gradle.kts

plugins {
  kotlin("jvm") // no version here - it's defined in buildSrc/build.gradle.kts
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将 Gradle 插件发布到 Artifactory? - How do I publish Gradle plugins to Artifactory? 如何在 build.gradle.kts 脚本的插件块中参数化 Kotlin 版本? - How to parametrize Kotlin version in the plugins block of a build.gradle.kts script? 编写 gradle 需要二进制插件版本的社区插件 - Compose gradle community plugins requiring a version in a binary plugin 如何避免每次在 build.gradle 中添加插件“kotlin-android-extensions” - How can I avoid adding the plugins 'kotlin-android-extensions' everytime in the build.gradle 如何在Gradle中设置Kotlin的版本? - How to set the version of Kotlin in Gradle? 如何在 Gradle 中为 Kotlin 项目正确设置 java 版本? (由于收到“No virtual method”错误,我无法访问函数) - how do I set java version correctly in Gradle for Kotlin projects? (I can't access functions due to `No virtual method` error being received) 如何解决此错误:数据绑定注释处理器版本需要匹配 Android Gradle 插件版本 - How can I solve this error : Data Binding annotation processor version needs to match the Android Gradle Plugin version 如何将自定义 Gradle 插件放在另一个项目构建类路径上? - How to put custom Gradle plugins on an another projects build classpath? 我是否需要添加 kapt “com.android.databinding:compiler:$compiler_version” gradle 条目? - Do I need to add kapt “com.android.databinding:compiler:$compiler_version” gradle entry? 如何使用 Kotlin DSL 和插件块使用 gradle 和 android 选择性地应用一些插件 - How to optionally apply some plugins using Kotlin DSL and plugins block with gradle and android
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM