将 kotlin 多平台库发布到 Maven Central(InvalidMavenPublicationException 多个工件具有相同的......)
Posted
技术标签:
【中文标题】将 kotlin 多平台库发布到 Maven Central(InvalidMavenPublicationException 多个工件具有相同的......)【英文标题】:Publish kotlin multiplatform library to Maven Central (InvalidMavenPublicationException multiple artifacts with the identical ...) 【发布时间】:2021-05-25 12:56:43 【问题描述】:由于 Jcenter 即将关闭,我正在尝试将我的库迁移到 Maven Central。我进行了很多搜索以找到任何工作脚本,但没有运气。有official docs,但它就像一个笑话,只是告诉将maven-publish
插件放到gradle 脚本中,瞧,就是这样。
目前我遇到错误:
Caused by: org.gradle.api.publish.maven.InvalidMavenPublicationException: Invalid publication 'js': multiple artifacts with the identical extension and classifier ('jar', 'sources').
我的脚本如下所示:
plugins
id("kotlin-multiplatform")
id("org.jetbrains.dokka") version "1.4.0-rc"
`maven-publish`
signing
kotlin
sourceSets
jvm()
js()
nodejs()
browser()
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)
tasks
create<Jar>("javadocJar")
dependsOn(dokkaJavadoc)
archiveClassifier.set("javadoc")
from(dokkaJavadoc.get().outputDirectory)
dokkaJavadoc
println("Dokka !")
dokkaSourceSets
create("commonMain")
displayName = "common"
platform = "common"
// Publishing
val fis = FileInputStream("local.properties")
val properties = Properties().apply
load(fis)
val ossUser = properties.getProperty("oss.user")
val ossPassword = properties.getProperty("oss.password")
extra["signing.keyId"] = properties.getProperty("signing.keyId")
extra["signing.password"] = properties.getProperty("signing.password")
extra["signing.secretKeyRingFile"] = properties.getProperty("signing.secretKeyRingFile")
val libraryVersion: String by project
val publishedGroupId: String by project
val artifactName: String by project
val libraryName: 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
signing
sign(publishing.publications)
publishing
publications.withType(MavenPublication::class)
groupId = publishedGroupId
artifactId = artifactName
version = libraryVersion
artifact(tasks["javadocJar"])
artifact(tasks["sourcesJar"])
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://oss.sonatype.org/service/local/staging/deploy/maven2/")
name = "sonatype"
credentials
username = ossUser
password = ossPassword
我还发现这个reddit topic 没有解决方案,这个article 不起作用,还有很多其他的。有大量材料如何发布到 bintray,但现在它们无关紧要
【问题讨论】:
【参考方案1】:问题似乎出在artifact(tasks["sourcesJar"])
这一行,因为该任务已包含在内。
在这里,我想将我的工作脚本用于将 kotlin 多平台库上传到 Maven Central。
首先我们需要注册 Sonatype 账户,验证我们的域名等,这里是一个fresh article with detailed steps。
那么您的项目脚本build.gradle.kts
可能如下所示:
import java.io.FileInputStream
import java.util.Properties
import org.gradle.api.publish.PublishingExtension
plugins
id("kotlin-multiplatform")
id("org.jetbrains.dokka") version "1.4.0-rc"
id("io.codearte.nexus-staging") version "0.22.0"
`maven-publish`
signing
enum class OS
LINUX, WINDOWS, MAC
fun getHostOsName(): OS =
System.getProperty("os.name").let osName ->
when
osName == "Linux" -> OS.LINUX
osName.startsWith("Windows") -> OS.WINDOWS
osName.startsWith("Mac") -> OS.MAC
else -> throw GradleException("Unknown OS: $osName")
kotlin
sourceSets
jvm()
js()
browser()
nodejs()
when (getHostOsName())
OS.LINUX ->
linuxX64()
linuxArm64()
OS.WINDOWS ->
mingwX64()
OS.MAC ->
macosX64()
iosArm64()
iosX64()
val commonMain by getting
dependencies
implementation(kotlin("stdlib-common"))
implementation(Libs.olekdia.common)
val commonTest by getting
dependencies
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
val jvmMain by getting
dependencies
val jvmTest by getting
dependencies
implementation(kotlin("test"))
implementation(kotlin("test-junit"))
val jsMain by getting
dependencies
val nativeMain by creating
dependsOn(commonMain)
when (getHostOsName())
OS.LINUX ->
val linuxX64Main by getting
dependsOn(nativeMain)
val linuxArm64Main by getting
dependsOn(nativeMain)
OS.WINDOWS ->
val mingwX64Main by getting
dependsOn(nativeMain)
OS.MAC ->
val macosX64Main by getting
dependsOn(nativeMain)
val iosArm64Main by getting
dependsOn(nativeMain)
val iosX64Main by getting
dependsOn(nativeMain)
tasks
create<Jar>("javadocJar")
dependsOn(dokkaJavadoc)
archiveClassifier.set("javadoc")
from(dokkaJavadoc.get().outputDirectory)
dokkaJavadoc
dokkaSourceSets
create("commonMain")
displayName = "common"
platform = "common"
//--------------------------------------------------------------------------------------------------
// Publishing
//--------------------------------------------------------------------------------------------------
val fis = FileInputStream("local.properties")
val properties = Properties().apply
load(fis)
val ossUser = properties.getProperty("oss.user")
val ossPassword = properties.getProperty("oss.password")
extra["signing.keyId"] = properties.getProperty("signing.keyId")
extra["signing.password"] = properties.getProperty("signing.password")
extra["signing.secretKeyRingFile"] = properties.getProperty("signing.secretKeyRingFile")
val libraryVersion: String by project
val publishedGroupId: String by project
val artifactName: String by project
val libraryName: 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
signing
sign(publishing.publications)
afterEvaluate
configure<PublishingExtension>
publications.all
val mavenPublication = this as? MavenPublication
mavenPublication?.artifactId =
"$project.name$"-$name".takeUnless "kotlinMultiplatform" in name .orEmpty()"
publishing
publications.withType(MavenPublication::class)
groupId = publishedGroupId
artifactId = artifactName
version = libraryVersion
artifact(tasks["javadocJar"])
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://oss.sonatype.org/service/local/staging/deploy/maven2/")
name = "sonatype"
credentials
username = ossUser
password = ossPassword
nexusStaging
username = ossUser
password = ossPassword
packageGroup = publishedGroupId
在gradle.properties
中提供所需的库详细信息:
libraryVersion = 0.1.1
libraryName = Your library name
libraryDescription = Your library description
publishedGroupId = com.yourdomain
artifactName = your-cool-librayr
siteUrl = https://gitlab.com/yourlibrayr
gitUrl = https://gitlab.com/yourlibrayr.git
developerId = ...
developerOrg = ...
developerName = Your Name
developerEmail = yourmail@mail.com
licenseName = The Apache Software License, Version 2.0
licenseUrl = http://www.apache.org/licenses/LICENSE-2.0.txt
allLicenses = ["Apache-2.0"]
kotlin.mpp.enableGranularSourceSetsMetadata = true
gnsp.disableApplyOnlyOnRootProjectEnforcement = true
这里需要gnsp.disableApplyOnlyOnRootProjectEnforcement = true
属性来声明nexusStaging
in subprojects。
最后把你的学分给local.properties
:
oss.user=your_user_name
oss.password=your_pass
signing.keyId=last_8_numbers_of_key
signing.password=your_pass
signing.secretKeyRingFile=/path/to/keystorage.gpg
现在在项目目录中发布打开的终端:
./gradlew build
./gradlew publish
./gradlew closeAndReleaseRepository
您可以跳过最后一个命令,关闭并从Nexus repository manager 释放暂存包。 nexus-staging
插件只需要从命令行执行即可。
我曾尝试将脚本的发布部分移动到单独的文件中,并将其包含在 apply(from = "publish.gradle.kts")
中,但它不起作用,因为它在单独的文件中丢失了上下文
我使用旧版本的 dokka 库 (1.4.0-rc),因为新版本无法为所有平台生成 javadocs。存储库需要此 javadocs 才能发布。作为authors mentioned,我们可以为此目的生成空的javadoc.jar 文件。
【讨论】:
这是否意味着您发布了无源代码?如果我希望它们也包含在出版物中怎么办? @dimsuz 在./gradlew build
之后调用./gradlew sourcesJar
以上是关于将 kotlin 多平台库发布到 Maven Central(InvalidMavenPublicationException 多个工件具有相同的......)的主要内容,如果未能解决你的问题,请参考以下文章
从 ktor 提供 kotlin 多平台 javascript
如何在 Kotlin 标准库(多平台)上获取当前的 unixtime
无法将 FirebaseAnalytics 或 Crashlytics cocoapod 添加到 kotlin 多平台共享模块