草庐IT

java - Gradle 5 Kotlin DSL : Common Tasks & Maven Artifacts in multi-modules projects

coder 2024-03-29 原文

我真的很想欣赏 Gradle 5,尤其是与新的 Kotlin DSL 结合使用,但我很难(在我看来)使用 Gradle 运行一个非常非常简单和通用的构建。

任务

发布一个 Java 库,其中包含 Maven 默认目录布局中的多个相互依赖的子模块 作为高质量的 Maven Artifact/存储库 -point,简单的 Gradle 构建(即 DRY)。

因此:有一个根项目作为保护伞,它定义并包含所有通用配置(实际上除了真正的依赖项之外的所有配置)。

我目前的挣扎

我将当前的“结果”移植到 a sample project on Githubasked this question in the Gradle forum already .

目前,我未能声明在我的中央构建中提供标准-sources-javadoc Artifact 的必要任务。

例如,在多模块场景中,您在寻找基于 Kotlin DSL 的解决方案时会发现这三个“解决方案”都不再(不再)工作:

不完整的解决方案(/build.gradle.kts)

完整示例请参见 Github:https://github.com/bentolor/gradle-maven-multimodule-kotlindsl

subprojects {
    apply(plugin = "java-library")
    apply(plugin = "maven-publish")
    group = "de.bentolor.sampleproject"
    version = "0.1.0"

    repositories {
        jcenter()
    }

    dependencies {
        // Dependencies used in EVERY module
        "compile"("commons-logging:commons-logging:1.2")
        "testImplementation"("junit:junit:4.12")
    }

    tasks {
        // not working
        /*register("sourcesJar", Jar::class.java) {
            from(sourceSets.main.get().allJava)
            classifier = "sources"
        }*/

       // not working, eiher
       /* task<Jar>("sourcesJar") {
            from(sourceSets.main.get().allJava)
            classifier = "sources"
       } */
    }

    configure<JavaPluginExtension> {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }

    configure<PublishingExtension> {
        publications {
            create<MavenPublication>(project.name) {
                from(components["java"])
                // won't work, beause inaccessible declaration in `tasks{}`-Block
                //add("archives", javadocJar)
                //add("archives", sourcesJar)
            }
        }

        repositories {
            mavenLocal()
        }
    }
}

示例子模块 /module2/build.gradle.kts

group = "de.bentolor.sampleproject.module2"

dependencies {
    compile(project(":module1"))
}

最佳答案

试试这个:

subprojects {
    apply<JavaLibraryPlugin>()
    apply<MavenPublishPlugin>()

    group = "de.bentolor.sampleproject"
    version = "0.1.0"

    repositories {
        jcenter()
    }

    dependencies {
        val implementation by configurations
        val testImplementation by configurations

        implementation("commons-logging:commons-logging:1.2")
        testImplementation("junit:junit:4.12")
    }

    // This will work, but as long as these tasks are need only for publishing you can declare them inplace later where you need 
    // tasks {
    //     val sourcesJar by creating(Jar::class) {
    //         val sourceSets: SourceSetContainer by project
    //         from(sourceSets["main"].allJava)
    //         classifier = "sources"
    //     }
    //     val javadoc by getting(Javadoc::class)
    //     val javadocJar by creating(Jar::class) {
    //         from(javadoc)
    //         classifier = "javadoc"
    //     }
    // }

    configure<JavaPluginExtension> {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }

    configure<PublishingExtension> {
        publications {
            create<MavenPublication>(project.name) {
                from(components["java"])

                // If you configured them before
                // val sourcesJar by tasks.getting(Jar::class)
                // val javadocJar by tasks.getting(Jar::class)

                val sourcesJar by tasks.creating(Jar::class) {
                    val sourceSets: SourceSetContainer by project

                    from(sourceSets["main"].allJava)
                    classifier = "sources"
                }
                val javadocJar by tasks.creating(Jar::class) {
                    from(tasks.get("javadoc"))
                    classifier = "javadoc"
                }

                artifact(sourcesJar)
                artifact(javadocJar)
            }
        }
    }
}

一些注意事项:

  • 为什么要使用基于 Stringapply ,当你可以做一个类型安全的 apply<T>() 时?
  • 为什么在 dependencies 中对 stings 使用调用,当您可以使用委托(delegate)时,委托(delegate)更少且可重构性更好。
  • 考虑使用 implementation instead of compile

为什么 sourceSets 在多模块项目中不起作用?

当您使用 Kotlin DSL 时,它会根据应用的插件为项目生成访问器。这是一个两步过程:首先 Gradle 处理插件(这就是为什么建议将它们放在 plugins block 中)并生成访问器,然后您可以在代码中使用它们(访问器生成为 ProjectNamedDomainObjectContainer 等的 Kotlin 扩展) .但是,如果您正在配置子项目,则存在两个问题:

  • 父项目在子项目之前评估,因此子项目的扩展在父项目中是未知的。
  • 应用于父项和子项的插件集不同,您需要在父项中使用子项访问器。

sourceSets 是 Kotlin DSL 为 child 生成的访问器之一。而且它在父级中不可用。您可以自己尝试一下:在 java 中只应用 subprojects 插件。 sourceSets 将在子构建脚本中可用,但在父脚本中不可用。

这也是为什么你可以在 child 中使用 java,但在父中配置时必须使用 configure<JavaPluginExtension>

但是您可以使用委托(delegate)来获取域对象的引用,例如任务、源集、配置等。

关于java - Gradle 5 Kotlin DSL : Common Tasks & Maven Artifacts in multi-modules projects,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53631780/

有关java - Gradle 5 Kotlin DSL : Common Tasks & Maven Artifacts in multi-modules projects的更多相关文章

随机推荐