使用 Gradle Kotlin DSL 发布 Kotlin MPP 元数据

Posted

技术标签:

【中文标题】使用 Gradle Kotlin DSL 发布 Kotlin MPP 元数据【英文标题】:Publish Kotlin MPP metadata with Gradle Kotlin DSL 【发布时间】:2020-11-20 09:27:46 【问题描述】:

我创建了一个 Kotlin MPP 来在 JVM 和 JS 之间共享 Json 实用程序。所有代码都位于公共源集中,并且我已经配置了必要的目标及其各自的依赖项。无需进一步配置,我就可以使用来自 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()
    

但是,这感觉还不太对。

    官方文档中没有sn-p这样的代码。

    文档宣传来自公共源集的单个依赖项应该足以自动解决目标特定依赖项:https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#metadata-publishing。我必须分别为每个目标添加依赖项才能使其工作。

    this as MavenPublication 是必需的,因为Publication 没有字段artifactId

    我使用project.name 而不是libraryName

这甚至是正确的做事方式,还是我错过了一些其他选项,这会使整个过程变得微不足道?

现在我在 settings.gradle.kts 中使用 Kotlin 1.3.72 和 Gradle 5.2.1enableFeaturePreview("GRADLE_METADATA")。我也用 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"))
            
        
    

【问题讨论】:

扔掉那个“解决方案”。你是在推动 bintray 还是 maven central/sonatype? 给我一个更好的,我很高兴这样做。这是一个小型个人项目,所以我现在将发布到我自己的 maven 存储库。 人们通常发布到 bintray 或 sonatype。我不确定你自己的 maven repo 是什么,除非你的意思是我猜是本地的。 明确地说,对元数据做一些特殊的事情是错误的。你完全不需要。我没有解释如何配置发布的博文,但我可以向您指出我们发布的大量库,包括公共和本地存储库。 另外,发布您的配置的其余部分,Gradle、Kotlin 的版本等。您的配置的那部分将不再存在,因为它不是必需的,但查看其余部分会很有用你的配置。 【参考方案1】:

毕竟没有真正的问题。解决方案是简单地将enableFeaturePreview("GRADLE_METADATA") 也添加到消费项目中。

根据https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#metadata-publishing,这应该没有必要:

在从 5.3 开始的早期 Gradle 版本中,模块元数据是 在依赖关系解析期间使用,但出版物不包含任何 默认情况下模块元数据。要启用模块元数据发布,请添加 enableFeaturePreview("GRADLE_METADATA") 到根项目的 settings.gradle 文件。

奇怪的是,它仅在发布项目和消费项目都启用了元数据时才有效,即使两者都使用最新的 Gradle 版本。

【讨论】:

是的,那个:twitter.com/kpgalligan/status/1189895057404510208?s=20【参考方案2】:

enableFeaturePreview("GRADLE_METADATA") 在最新的 gradle 中默认启用。 根据this,您需要将“kotlinMultiplatform”替换为“”一个空字符串。

我终于设法仅使用maven-publish 插件完成发布到bintray,而没有过时的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.userbintray.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 by bintrayUser,其中最后一个是您在 bintray.com 上的用户名

【讨论】:

以上是关于使用 Gradle Kotlin DSL 发布 Kotlin MPP 元数据的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 gradle kotlin-dsl 添加新的源集

使用 Gradle Kotlin DSL 进行集成测试

使用 Gradle Kotlin DSL 在 Gradle 中进行样板项目配置

gradle kotlin dsl:如何创建使用插件类的共享函数?

如何使用 Gradle Kotlin DSL 对 Spring Boot 应用程序进行 Dockerize

Kotlin DSL 中的 gradle 额外属性是如何设置的?