Gradle 5 Kotlin DSL: общие задачи и артефакты Maven в многомодульных проектах - PullRequest
0 голосов
/ 05 декабря 2018

Мне бы очень хотелось по достоинству оценить Gradle 5, особенно в сочетании с новым Kotlin DSL, но мне очень тяжело получить (на мой взгляд) очень, очень простую и распространенную сборку, работающую с Gradle.

Задача

Выпуск библиотеки Java с несколькими взаимозависимыми подмодулями в макете каталога Maven по умолчанию в качестве высококачественных артефактов / хранилища Maven в простой простой сборке Gradle (т.е. DRY ).

Поэтому: создайте корневой проект в качестве зонтика, который определяет и содержит все общие конфигурации (практически все, кроме реальнойзависимости).

Моя текущая борьба

Я перенес свои текущие "результаты" в пример проекта на Github и уже задавал этот вопрос на форуме Gradle .

В настоящее время я не могу объявить необходимую задачу для обеспечения стандартных -sources и -javadoc артефактов в моей центральной сборке.

Например, этитри "солуtions », которые вы найдете при поиске решений на базе 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 голосов
/ 07 декабря 2018

Попробуйте это:

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, когда вы можете сделать типобезопасным apply<T>()?
  • Зачем использовать вызовы для строк в dependencies, когда вы можете использовать делегатов, что менее хакерское и лучше рефакторизируемое.
  • Попробуйте использовать implementation вместо compile

Почему sourceSets не работает в многомодульном проекте?

Когда вы используете Kotlin DSL, он генерирует средства доступа для проектов на основе примененных плагинов.Это двухэтапный процесс: сначала Gradle обрабатывает плагины (поэтому рекомендуется поместить их в блок plugins) и генерирует средства доступа, а затем вы можете использовать их в своем коде (средства доступа генерируются как расширения Kotlin для Project, NamedDomainObjectContainer и тд).Но если вы конфигурируете подпроекты, есть две проблемы:

  • Родительский проект оценивается до дочернего, поэтому расширения для дочернего не известны в родительском.
  • Набор плагинов, применяемых кparent и child различаются, и вам необходимо использовать дочерние методы доступа в parent.

sourceSets является одним из методов доступа, созданных Kotlin DSL для детей.И это просто не доступно в родительском.Вы можете попробовать сами: примените только java плагин в subprojects.sourceSets будет доступно в дочерних сценариях сборки, но не в родительских.

По этой же причине вы можете использовать java в дочерних, но при настройке его в родительском * придется использовать configure<JavaPluginExtension>.

Но вы можете использовать делегатов для получения ссылок на объекты домена, такие как задачи, исходные наборы, настройки и т. Д.

...