Публикация метаданных Kotlin MPP с помощью Gradle Kotlin DSL

Я создал Kotlin MPP для совместного использования утилит Json между JVM и JS. Весь код находится в общем исходном наборе, и я настроил необходимые цели с их соответствующими зависимостями. Без дополнительной настройки я могу использовать утилиты как JVM, так и JS, но не из общего набора источников другого MPP, что связано с тем, как Gradle обрабатывает метаданные.

Я уже нашел решение (взято из https://medium.com/xorum-io/crafting-and-publishing-kotlin-multiplatform-library-to-bintray-cbc00a4f770)

afterEvaluate {
    project.publishing.publications.all {
        groupId = group
        if (it.name.contains('metadata')) {
            artifactId = "$libraryName"
        } else {
            artifactId = "$libraryName-$name"
        }
    }
}

и я также заставил его работать с Gradle Kotlin DSL:

afterEvaluate {
    publishing.publications.all {
        this as MavenPublication
        artifactId = project.name + "-$name".takeUnless { "metadata" in name }.orEmpty()
    }
}

Однако это пока не кажется правильным.

  1. В официальной документации такого фрагмента кода нет.

  2. В документации говорится, что одной зависимости из общего исходного набора должно быть достаточно для автоматического разрешения конкретных целевых зависимостей: https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#metadata-публикация. Мне пришлось добавить зависимости для каждой цели, соответственно, чтобы она работала.

  3. this as MavenPublication необходимо, потому что Publication не имеет поля artifactId.

  4. Я использую project.name вместо libraryName.

Это хотя бы отдаленно правильный способ делать что-то, или мне не хватает другого варианта, который сделал бы весь процесс тривиальным?

Сейчас я использую Kotlin 1.3.72 и Gradle 5.2.1 с enableFeaturePreview("GRADLE_METADATA") в settings.gradle.kts. Я также пробовал это с Gradle 6.5.1 (последний), но он ведет себя точно так же.

На данный момент я рад, что он вообще работает, но я подозреваю, что есть более чистый способ сделать это. Я был бы очень признателен, если бы кто-то с немного большим опытом Gradle мог прояснить для меня ситуацию или указать мне правильное направление.

Редактировать:

gradle.build.kts для полноты. Хотя здесь мало что происходит.

group = "org.example"
version = "1.0-SNAPSHOT"

plugins {
    kotlin("multiplatform") version "1.3.72"
    `maven-publish`
}

repositories {
    mavenCentral()
}

kotlin {
    jvm()

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation(kotlin("stdlib-common"))
            }
        }

        val jvmMain by getting {
            dependencies {
                implementation(kotlin("stdlib"))
            }
        }
    }
}

person Marvin    schedule 30.07.2020    source источник
comment
Выбросьте этот раствор. Вы продвигаетесь к bintray или maven central / sonatype?   -  person Kevin Galligan    schedule 30.07.2020
comment
Покажите мне лучшую, и я рад сделать это. Это небольшой личный проект, поэтому я пока публикую его в собственном репозитории maven.   -  person Marvin    schedule 30.07.2020
comment
Люди обычно публикуются в формате bintray или sonatype. Я не уверен, что такое ваше собственное репозиторий maven, если вы не имеете в виду локальный, я думаю.   -  person Kevin Galligan    schedule 31.07.2020
comment
Чтобы было ясно, делать что-то особенное с такими метаданными неправильно. Вам это совершенно не нужно. У меня нет сообщения в блоге, в котором объясняется, как настроить вашу публикацию, но я могу указать вам на множество библиотек, которые мы публикуем, как для общедоступных, так и для локальных репозиториев.   -  person Kevin Galligan    schedule 31.07.2020
comment
Кроме того, опубликуйте остальную часть вашей конфигурации, какую версию Gradle, Kotlin и т. Д. Эта часть вашей конфигурации больше не будет существовать, поскольку в ней нет необходимости, но было бы полезно увидеть остальную часть вашей конфигурации.   -  person Kevin Galligan    schedule 31.07.2020
comment
Это было бы прекрасно! Я просто хочу, чтобы минимальная настройка работала. Если он работает с maven local, он также будет работать с моим репозиторием, я думаю, что нет существенной разницы, кроме кеширования. (В любом случае я пробовал это как с моим репозиторием, так и с maven local. Решение не должно зависеть от того, как bintray, ... обрабатывает публикацию). См. Редактирование моего build.gradle.kts.   -  person Marvin    schedule 31.07.2020


Ответы (2)


В конце концов, проблем не было. Решение состоит в том, чтобы просто добавить enableFeaturePreview("GRADLE_METADATA") к потребляющему проекту.

Согласно https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#metadata-publishing в этом не должно быть необходимости:

В более ранних версиях Gradle, начиная с 5.3, метаданные модуля используются во время разрешения зависимостей, но публикации по умолчанию не включают никаких метаданных модуля. Чтобы включить публикацию метаданных модуля, добавьте enableFeaturePreview (GRADLE_METADATA) в файл settings.gradle корневого проекта.

Как ни странно, это работает только тогда, когда и публикующий, и потребительский проект имеют включенные метаданные, даже если оба используют последнюю версию Gradle.

person Marvin    schedule 31.07.2020
comment
Да, это: twitter.com/kpgalligan/status/1189895057404510208?s=20 - person Kevin Galligan; 31.07.2020

enableFeaturePreview("GRADLE_METADATA") включен по умолчанию в последней версии Gradle. Согласно this, вам необходимо заменить kotlinMultiplatform пустой строкой.

Наконец-то мне удалось выполнить публикацию на bintray только с maven-publish плагином, без устаревшей библиотеки bintray. Вот мой полный maven.publish.gradle.kts:

import java.io.FileInputStream
import java.util.*
import org.gradle.api.publish.PublishingExtension

apply(plugin = "maven-publish")

val fis = FileInputStream("local.properties")
val properties = Properties().apply {
    load(fis)
}
val bintrayUser = properties.getProperty("bintray.user")
val bintrayApiKey = properties.getProperty("bintray.apikey")
val bintrayPassword = properties.getProperty("bintray.gpg.password")
val libraryVersion: String by project
val publishedGroupId: String by project
val artifact: String by project
val bintrayRepo: String by project
val libraryName: String by project
val bintrayName: String by project
val libraryDescription: String by project
val siteUrl: String by project
val gitUrl: String by project
val licenseName: String by project
val licenseUrl: String by project
val developerOrg: String by project
val developerName: String by project
val developerEmail: String by project
val developerId: String by project

project.group = publishedGroupId
project.version = libraryVersion

afterEvaluate {
    configure<PublishingExtension> {
        publications.all {
            val mavenPublication = this as? MavenPublication
            mavenPublication?.artifactId =
                "${project.name}${"-$name".takeUnless { "kotlinMultiplatform" in name }.orEmpty()}"
        }
    }
}

configure<PublishingExtension> {
    publications {
        withType<MavenPublication> {
            groupId = publishedGroupId
            artifactId = artifact
            version = libraryVersion

            pom {
                name.set(libraryName)
                description.set(libraryDescription)
                url.set(siteUrl)

                licenses {
                    license {
                        name.set(licenseName)
                        url.set(licenseUrl)
                    }
                }
                developers {
                    developer {
                        id.set(developerId)
                        name.set(developerName)
                        email.set(developerEmail)
                    }
                }
                organization {
                    name.set(developerOrg)
                }
                scm {
                    connection.set(gitUrl)
                    developerConnection.set(gitUrl)
                    url.set(siteUrl)
                }
            }
        }
    }

    repositories {
        maven("https://api.bintray.com/maven/${developerOrg}/${bintrayRepo}/${artifact}/;publish=1") {
            credentials {
                username = bintrayUser
                password = bintrayApiKey
            }
        }
    }
}

И build.gradle.kts:

plugins {
    id("kotlin-multiplatform")
}

kotlin {
    sourceSets {
        jvm()
        js() {
            browser()
            nodejs()
        }
        linuxX64()
        linuxArm64()
        mingwX64()
        macosX64()
        iosArm64()
        iosX64()

        val commonMain by getting {
            dependencies {
            }
        }
        val commonTest by getting {
            dependencies {
                implementation(kotlin("test-common"))
                implementation(kotlin("test-annotations-common"))
            }
        }

        val jsMain by getting {
            dependencies {
            }
        }
        val jsTest by getting {
            dependencies {
                implementation(kotlin("test-js"))
            }
        }

        val jvmMain by getting {
            dependencies {
            }
        }
        val jvmTest by getting {
            dependencies {
                implementation(kotlin("test"))
                implementation(kotlin("test-junit"))
            }
        }

        val nativeMain by creating {
            dependsOn(commonMain)
            dependencies {
            }
        }

        val linuxX64Main by getting {
            dependsOn(nativeMain)
        }
        val linuxArm64Main by getting {
            dependsOn(nativeMain)
        }
        val mingwX64Main by getting {
            dependsOn(nativeMain)
        }
        val macosX64Main by getting {
            dependsOn(nativeMain)
        }
        val iosArm64Main by getting {
            dependsOn(nativeMain)
        }
        val iosX64Main by getting {
            dependsOn(nativeMain)
        }
    }
}

apply(from = "maven.publish.gradle.kts")

Обратите внимание, что в local.properties файле есть свойства bintray.user и bintray.apikey. Также gradle.properties содержит остальные перечисленные выше свойства:

libraryVersion = 0.5.22
libraryName = MultiplatformCommon
libraryDescription = Kotlin multiplatform extensions
publishedGroupId = com.olekdia
artifact = multiplatform-common
bintrayRepo = olekdia
bintrayName = multiplatform-common
siteUrl = https://gitlab.com/olekdia/common/libraries/multiplatform-common
gitUrl = https://gitlab.com/olekdia/common/libraries/multiplatform-common.git
.........
kotlin.mpp.enableGranularSourceSetsMetadata = true
systemProp.org.gradle.internal.publish.checksums.insecure = true

Если вы не создали организацию в bintray, вам нужно изменить этот URL:

https://api.bintray.com/maven/${developerOrg}/${bintrayRepo}/${artifact}/;publish=1

developerOrg от bintrayUser, где последнее - ваше имя пользователя на bintray.com

person Oleksandr Albul    schedule 20.08.2020