如何编写Gradle插件以减少build.gradle文件

bjp0bcyl  于 2023-02-09  发布在  其他
关注(0)|答案(1)|浏览(136)

先了解一下背景:我正在将公司的项目迁移到Gradle构建。这会导致我的build. gradle文件中出现冗余,因为我一遍又一遍地配置相同的Skeleton。这包括:

  • 设置java插件、maven插件和org插件
  • 将存储库配置为mavenCentral和我们的私有Artifactory Repo
  • 配置发布块,除了artifactId之外,其他都是一样的
  • 在Jar块中构建清单(使用helper方法,以正确构建清单类路径)
  • 帮助器方法
  • 两项任务
  • 两个dependsOn语句

build. gradle文件截至目前:

plugins {
    id 'io.spring.dependency-management' version '1.0.12.RELEASE'
    id "org.sonarqube" version "3.2.0"
    id 'maven-publish'
    id 'java' 
}

group = 'group'
version = 'version'
sourceCompatibility = '11'
ext.artifactName = 'ProjectName'

// Where to look for dependencies:
repositories {
    mavenCentral()
    maven{
        credentials{
            username = "${artifactory_user}"
            password = "${artifactory_password}"
        }
        url "${artifactory_contextUrl}"
        allowInsecureProtocol = true
    }
}
// Where to publish what Artifacts to:
publishing {
    publications {
        maven(MavenPublication) {
            groupId = 'group'
            artifactId = 'ProjectName'
            String buildEnvVar = System.env.BUILDENVIRONMENT
            if(buildEnvVar == null){
                version = 'LOCAL BUILD'
            }else{
                version = 'version'
            }
            from components.java
        }
    }
    repositories {
        maven {
            // change to point to your repo, e.g. http://my.org/repo
            name = "gradle-dev"
            url = "${artifactory_contextUrl}"
            allowInsecureProtocol = true
            credentials{
                username = "${artifactory_user}"
                password = "${artifactory_password}"
            }
        }
    }
}

dependencies {...}

jar { 
    // configuration of variables
    String dateString = new Date().format("yyyy-MM-dd HH:mm:ss ")
    String localBuild = "LOCAL BUILD by " + System.getProperty("user.name") + " on " + dateString
    String buildEnvVar = System.env.BUILDENVIRONMENT
    String buildEnvironment
    String classpath = createCP()
    if(buildEnvVar == null){
        buildEnvironment = localBuild 
        archiveName = "ProjectName"
    }else{
        buildEnvironment = buildEnvVar
        archiveFileName= "ProjectName_" + version + ".jar"
        
        delete fileTree("build/libs") {
            include('*')
        }
    }
    manifest {
        attributes (
            "Main-Class": "org.example.foo",
            "Specification-Title" : "ProjectName",
            "Specification-Vendor" : "blab",
            "Specification-Version" : "Spec-version", 
            "Implementation-Title" : "$System.env.JOB_NAME",
            "Implementation-Version" : "Impl-version",
            "Implementation-Vendor" : "blub",
            "Implementation-Vendor-Id" : "blob",
            "Implementation-Url" : "bleb",
            "Build-By" : buildEnvironment,
            'Class-Path': classpath
        )
    }
}

String createCP () {
    // super secret can't share
}

// will suffix the jars with release or debug, depending on it being compiled with or without debug-information
project.gradle.taskGraph.whenReady{
    boolean isDebug = project.gradle.taskGraph.getAllTasks().join(' ').contains('debugJar')
    compileJava.options.debug = isDebug
    String suffix = isDebug? "debug" : "release"
    String fullJarName = "$artifactName-$suffix" + ".jar"
    
    jar.setProperty('archiveName', fullJarName)
}

tasks.named('test') {
    useJUnitPlatform()
}

task debugJar() {}
debugJar.dependsOn(jar)

//Downloads all Jars the project depends on, and saves them in buildDirectory/output/libs if the gradle build command is executed.

 task copyToLib(type: Copy) {
    into "${buildDir}/output/libs"
    from configurations.runtimeClasspath
}

build.dependsOn(copyToLib)

我想要达到的目标:

plugins {
    id 'io.spring.dependency-management' version '1.0.12.RELEASE'
    id "org.sonarqube" version "3.2.0"
    id 'maven-publish'
    id 'java'
    id 'mySuperPlugin'
}

// Configure mySuperPlugin
mySuperPlugin {
    artifactId = 'xyz'
    mainClass = 'org.example.foo'
    version = 'version'
    stuffFromOtherTasks = ...
}

// Where to look for dependencies:
repositories {
    mavenCentral()
    maven{
        credentials{
            username = "${artifactory_user}"
            password = "${artifactory_password}"
        }
        url "${artifactory_contextUrl}"
        allowInsecureProtocol = true
    }
}

dependencies {...}

大部分的值是相同的。那些不是通过环境变量(Jenkins-JobName,...)传入的,或者通过helper方法确定的。我估计,我最有可能不会像上面这样结束构建文件,但至少一些构建文件必须是可外包的。
我现在知道,我可以在插件中创建单独的任务,如比较两个文件,已通过.我还没有找到解决方案:

  • 我可以在插件内部修改应用插件的项目的Jar任务吗?
  • 如何将输出从其他任务传递到我的插件任务?
  • 如何访问应用项目数据(即runtimeClasspath)
  • 插件是我想做的吗,还是有其他方法可以减少build. gradle文件?

我对gradle相对来说没有经验。我已经阅读了相当多的文档和其他帖子,但很可能我只是忽略了一些做某些事情的最佳实践方法。因此,请随意批评我的构建文件以及我的方法!

bsxbgnwa

bsxbgnwa1#

您可以通过几种方式来实现这一点。这取决于您的项目是由多个子项目组成还是由独立项目组成。对于独立项目,您可以在settings.gradle文件中执行以下操作:

includeBuild("../common-project/build.gradle")

公共项目只包含公共build.gradle文件,您可以在其中声明要共享的所有项,它看起来就像一个普通的build.gradle文件。
这将要求每个项目共享另一个项目的公共配置,但不要求 checkout 任何其他项目。只需 checkout 公共项目和项目本身。有关详细信息,请参阅:
https://docs.gradle.org/current/userguide/composite_builds.html
如果您有更多的多项目构建,比如说许多微服务或子项目组成了一个更大的项目,那么请使用多项目设置,并在根构建的allprojects闭包中声明公共部分。gradle:

allprojects {
    plugin: java
    plugin: web

    repositories {
      ....
    }

    dependencies {
       ....
    }
}

在多项目的情况下,您必须 checkout 顶级项目和所有子项目。您的文件夹布局可能如下所示:

- my-project
  - service-1
      src
      build.gradle
  - service-2
      src
      build.gradle
  - service-3
      src
      build.gradle
    build.gradle
    settings.gradle

在多项目设置中,service1、service2和service3将在settings.gradle文件中使用include声明,如下所示:

rootProject.name = 'my-project'
include `service1`
include `service2`
include `service3`

在一个多项目的环境中,你通常会把它放在一个源代码库中,而不是使用includeBuild,每个项目都属于一个单独的源代码库。前一种方式迫使你在多项目的情况下 checkout 适当数量的项目。但是,在includeBuild的情况下,开发人员必须知道最少 checkout 2个项目。

相关问题