Gradle 5 Kotlin DSL:多模块项目中的常见任务和Maven工件

时间:2018-12-05 11:56:26

标签: java maven gradle multi-module gradle-kotlin-dsl

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

任务

使用Maven默认目录布局中的几个相互依赖的子模块发布Java库,作为高质量的Maven构件/存储库。点,简单的Gradle构建(即 DRY )。

因此:拥有一个根项目作为伞,该根项目定义并包含所有通用配置(实际上是所有依赖项除外)。

我目前的挣扎

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

当前,我未能声明在我的 central 构建中提供标准-sources-javadoc工件的必要任务。

例如,在寻找基于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"))
}

1 个答案:

答案 0 :(得分:5)

尝试一下:

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)
            }
        }
    }
}

一些注意事项:

  • 当您可以进行类型安全的String时,为什么使用基于apply的{​​{1}}?
  • 在可以使用委托的情况下,为什么在apply<T>()中的字符串上使用use调用,所以hacky少且可重构性更好。
  • 考虑使用implementation instead of compile

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

当您使用Kotlin DSL时,它会基于所应用的插件为项目生成访问器。这是一个分为两个步骤的过程:首先Gradle处理插件(这就是为什么建议将它们放在sourceSets块中)并生成访问器,然后可以在代码中使用它们(访问器作为{{1的Kotlin扩展名生成}},plugins等。但是,如果要配置子项目,则有两个问题:

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

Project是Kotlin DSL为儿童创建的访问器之一。而且它在父级中不可用。您可以自己尝试:仅在NamedDomainObjectContainer中应用sourceSets插件。 java将在子代构建脚本中可用,而在父代构建脚本中不可用。

这也是为什么您可以在子级中使用subprojects,而在父级中配置sourceSets的原因。

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