gpt4 book ai didi

gradle - 使用Gradle Kotlin DSL在Gradle中进行样板项目配置

转载 作者:IT老高 更新时间:2023-10-28 13:28:06 29 4
gpt4 key购买 nike

我目前正在尝试改善我们的项目共享其配置的方式。我们所有的库和微服务都有很多不同的多模块gradle项目(即许多git repos)。

我的主要目标是:

  • 不要在每个项目中都复制我的Nexus存储库配置(而且,我可以放心地认为URL不会更改)
  • 使我的自定义Gradle插件(发布到Nexus)可用于每个项目,且模板/重复项最少(它们应可用于每个项目,并且该项目唯一关心的是它使用的版本)
  • 没魔力-开发人员应该清楚如何配置

  • 我当前的解决方案是使用以下脚本的自定义gradle分发:
  • mavenLocal()和我们的Nexus存储库添加到项目存储库中(非常类似于Gradle init script documentation example,不同之处在于它添加了存储库并对其进行了验证)
  • 配置了一个扩展,该扩展允许将gradle插件添加到buildscript类路径中(使用this workaround)。它还将我们的Nexus存储库添加为构建脚本存储库,因为这是托管插件的位置。我们有很多用于各种样板的插件(基于Netflix出色的nebula plugins构建):标准项目设置(kotlin设置,测试设置等),发布,发布,文档等,这意味着我们的项目build.gradle文件几乎完全是用于依赖项的。

  • 这是初始化脚本(已清除):
    /**
    * Gradle extension applied to all projects to allow automatic configuration of Corporate plugins.
    */
    class CorporatePlugins {

    public static final String NEXUS_URL = "https://example.com/repository/maven-public"
    public static final String CORPORATE_PLUGINS = "com.example:corporate-gradle-plugins"

    def buildscript

    CorporatePlugins(buildscript) {
    this.buildscript = buildscript
    }

    void version(String corporatePluginsVersion) {
    buildscript.repositories {
    maven {
    url NEXUS_URL
    }
    }
    buildscript.dependencies {
    classpath "$CORPORATE_PLUGINS:$corporatePluginsVersion"
    }
    }

    }

    allprojects {
    extensions.create('corporatePlugins', CorporatePlugins, buildscript)
    }

    apply plugin: CorporateInitPlugin

    class CorporateInitPlugin implements Plugin<Gradle> {

    void apply(Gradle gradle) {

    gradle.allprojects { project ->

    project.repositories {
    all { ArtifactRepository repo ->
    if (!(repo instanceof MavenArtifactRepository)) {
    project.logger.warn "Non-maven repository ${repo.name} detected in project ${project.name}. What are you doing???"
    } else if(repo.url.toString() == CorporatePlugins.NEXUS_URL || repo.name == "MavenLocal") {
    // Nexus and local maven are good!
    } else if (repo.name.startsWith("MavenLocal") && repo.url.toString().startsWith("file:")){
    // Duplicate local maven - remove it!
    project.logger.warn("Duplicate mavenLocal() repo detected in project ${project.name} - the corporate gradle distribution has already configured it, so you should remove this!")
    remove repo
    } else {
    project.logger.warn "External repository ${repo.url} detected in project ${project.name}. You should only be using Nexus!"
    }
    }

    mavenLocal()

    // define Nexus repo for downloads
    maven {
    name "CorporateNexus"
    url CorporatePlugins.NEXUS_URL
    }
    }
    }

    }

    }

    然后,通过将以下内容添加到root build.gradle文件中,配置每个新项目:
    buildscript {
    // makes our plugins (and any others in Nexus) available to all build scripts in the project
    allprojects {
    corporatePlugins.version "1.2.3"
    }
    }

    allprojects {
    // apply plugins relevant to all projects (other plugins are applied where required)
    apply plugin: 'corporate.project'

    group = 'com.example'

    // allows quickly updating the wrapper for our custom distribution
    task wrapper(type: Wrapper) {
    distributionUrl = 'https://com.example/repository/maven-public/com/example/corporate-gradle/3.5/corporate-gradle-3.5.zip'
    }
    }

    虽然这种方法行之有效,但允许可复制的构建(不同于我们以前的应用程序通过URL应用构建脚本-当时是不可缓存的),并且允许脱机工作,这确实使它有些不可思议,我想知道我是否可以做得更好。

    这全部是由Gradle开发者Stefan Oehme阅读 a comment on Github触发的,该声明表示构建应该可以在不依赖初始化脚本的情况下工作,即,初始化脚本应该只是装饰性的,并且可以像已记录的示例那样进行操作-防止未经授权的回购等。

    我的想法是编写一些扩展功能,使我可以将Nexus repo和插件添加到内部版本中,就像它们内置在gradle中一样(类似于Gradle Kotlin DSL提供的扩展功能 gradleScriptKotlin() kotlin-dsl() )。

    因此,我在kotlin gradle项目中创建了扩展功能:
    package com.example

    import org.gradle.api.artifacts.dsl.DependencyHandler
    import org.gradle.api.artifacts.dsl.RepositoryHandler
    import org.gradle.api.artifacts.repositories.MavenArtifactRepository

    fun RepositoryHandler.corporateNexus(): MavenArtifactRepository {
    return maven {
    with(it) {
    name = "Nexus"
    setUrl("https://example.com/repository/maven-public")
    }
    }
    }

    fun DependencyHandler.corporatePlugins(version: String) : Any {
    return "com.example:corporate-gradle-plugins:$version"
    }

    计划在我的项目的 build.gradle.kts中使用它们,如下所示:
    import com.example.corporateNexus
    import com.example.corporatePlugins

    buildscript {

    repositories {
    corporateNexus()
    }

    dependencies {
    classpath(corporatePlugins(version = "1.2.3"))
    }
    }

    但是,在 buildscript块中使用时,Gradle无法看到我的函数(无法编译脚本)。尽管在正常的项目存储库/依赖项中使用它们仍然可以正常工作(它们可见且按预期运行)。

    如果可行,我希望将jar bundle 到我的自定义发行版中,这意味着我的init脚本可以执行简单的验证,而不是隐藏神奇的插件和回购配置。扩展功能不需要更改,因此在插件更改时不需要发布新的Gradle发行版。

    我试过的
  • 将我的jar添加到测试项目的buildscript类路径(即buildscript.dependencies)中-不起作用(也许这在设计上不起作用,因为在同一块中引用的buildscript中添加依赖项似乎不正确)
  • 将函数放在buildSrc中(该功能适用​​于常规项目deps / repos,但不适用于buildscript,但不是真正的解决方案,因为它只是移动样板)
  • 将 jar 放到发行版
  • lib文件夹中

    所以我的问题实际上可以归结为:
  • 我要实现的目标是否可能(是否可以使buildScript块可见自定义类/函数)?
  • 是否有更好的方法来配置公司Nexus回购协议(protocol),并以最少的样板配置在许多单独的项目(即完全不同的代码库)中提供自定义插件(已发布到Nexus)?
  • 最佳答案

    如果您想从Gradle Kotlin DSL的所有优点中受益,您应该努力使用plugins {}块来应用所有插件。参见https://github.com/gradle/kotlin-dsl/blob/master/doc/getting-started/Configuring-Plugins.md

    您可以在设置文件中管理插件存储库和解析策略(例如其版本)。从Gradle 4.4开始,可以使用Kotlin DSL aka settings.gradle.kts编写此文件。参见https://docs.gradle.org/4.4-rc-1/release-notes.html

    考虑到这一点,您便可以使用一个集中的Settings脚本插件来进行设置并将其应用到您的生成settings.gradle.kts文件中:

    // corporate-settings.gradle.kts
    pluginManagement {
    repositories {
    maven {
    name = "Corporate Nexus"
    url = uri("https://example.com/repository/maven-public")
    }
    gradlePluginPortal()
    }
    }

    和:
    // settings.gradle.kts
    apply(from = "https://url.to/corporate-settings.gradle.kts")

    然后,在项目构建脚本中,您可以简单地从公司资源库中请求插件:
    // build.gradle.kts
    plugins {
    id("my-corporate-plugin") version "1.2.3"
    }

    如果您希望多项目构建中的项目构建脚本不重复插件版本,则可以通过在根项目中声明版本来使用 Gradle 4.3。请注意,如果所有版本都使用相同的插件版本,则也可以使用 settings.gradle.ktspluginManagement.resolutionStrategy中设置版本。

    另请注意,要使所有这些工作正常进行,您的插件必须使用其 plugin marker artifact发布。使用 java-gradle-plugin插件可以轻松完成此操作。

    关于gradle - 使用Gradle Kotlin DSL在Gradle中进行样板项目配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43657807/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com