瀏覽代碼

New MPP publishing (#489)

Him188 5 年之前
父節點
當前提交
ad74673e7f

+ 4 - 7
.github/workflows/bintray.yml

@@ -28,13 +28,10 @@ jobs:
         run: ./gradlew build # if test's failed, don't publish
       - name: Check keys
         run: ./gradlew :mirai-core:ensureBintrayAvailable :mirai-core-qqandroid:ensureBintrayAvailable -Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }} -Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
-      - name: Gradle :mirai-core:bintrayUpload
-        run: ./gradlew :mirai-core:bintrayUpload -Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }} -Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
-      - name: Gradle :mirai-core-qqandroid:bintrayUpload
-        run: ./gradlew :mirai-core-qqandroid:bintrayUpload -Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }} -Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
-      - name: Gradle :mirai-serialization:bintrayUpload
-        run: ./gradlew :mirai-serialization:bintrayUpload -Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }} -Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
-
+      - name: Gradle :mirai-core:publish
+        run: ./gradlew :mirai-core:publish -Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }} -Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
+      - name: Gradle :mirai-core-qqandroid:publish
+        run: ./gradlew :mirai-core-qqandroid:publish -Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }} -Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
 
 #      - name: Upload artifact
 #        uses: actions/[email protected]

+ 3 - 1
gradle.properties

@@ -6,4 +6,6 @@ kotlin.parallel.tasks.in.project=true
 org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=512m -Dfile.encoding=UTF-8
 org.gradle.parallel=true
 
-#kotlin.mpp.enableGranularSourceSetsMetadata=true
+#kotlin.mpp.enableGranularSourceSetsMetadata=true
+
+systemProp.org.gradle.internal.publish.checksums.insecure=true

+ 12 - 0
gradle/bintray.gradle

@@ -0,0 +1,12 @@
+publishing {
+    repositories {
+        maven {
+            url = "https://api.bintray.com/maven/mamoe/mirai/mirai-core/;publish=0"
+
+            credentials {
+                username = upload.Bintray.getUser(project)
+                password = upload.Bintray.getKey(project)
+            }
+        }
+    }
+}

+ 126 - 94
gradle/publish.gradle

@@ -1,129 +1,161 @@
-import upload.Bintray
-
 // 部分源码来自 kotlinx.coroutines
 // Source code from kotlinx.coroutines
 
-task ensureBintrayAvailable() {
+tasks.register("ensureBintrayAvailable") {
     doLast {
-        if (!Bintray.isBintrayAvailable(project)) {
+        if (!upload.Bintray.isBintrayAvailable(project)) {
             throw new IllegalStateException("bintray isn't available. ")
         }
     }
 }
 
-if (!Bintray.isBintrayAvailable(project)) {
-    println("bintray isn't available. NO PUBLICATIONS WILL BE SET")
-    return
+def vcs = "https://github.com/mamoe/mirai"
+
+def pomConfig = {
+    licenses {
+        license {
+            name "AGPLv3 with Mamoe Exceptions"
+            url "https://github.com/mamoe/mirai/blob/master/LICENSE"
+            distribution "repo"
+        }
+    }
+    developers {
+        developer {
+            id "mamoe"
+            name "Mamoe Technologies"
+            email "[email protected]"
+        }
+    }
+    scm {
+        url vcs
+    }
+}
+
+project.ext.configureMavenCentralMetadata = { pom ->
+    def root = asNode()
+    root.appendNode('name', project.name)
+    root.appendNode('description', project.description)
+    root.appendNode('url', vcs)
+    root.children().last() + pomConfig
+}
+
+try {
+
+// empty xxx-javadoc.jar
+    task javadocJar(type: Jar) {
+        archiveClassifier = 'javadoc'
+    }
+} catch (Exception ignored) {
+
 }
 
-def miraiGitHubUrl = "https://github.com/mamoe/mirai"
-
-bintray {
-    user = Bintray.getUser(project)
-    key = Bintray.getKey(project)
-
-    pkg {
-        repo = 'mirai'
-        name = "mirai-core"
-        licenses = ['AGPL']
-        vcsUrl = miraiGitHubUrl
-        websiteUrl = miraiGitHubUrl
-        githubRepo = miraiGitHubUrl
-        issueTrackerUrl = "$miraiGitHubUrl/issues"
-       /* version {
-            name = project.version
-        }*/
+try {
+    task stubJavadoc(type: Jar) {
+        archiveClassifier = 'javadoc'
     }
+}catch (Exception ignored) {
+
 }
 
-afterEvaluate {
-    project.publishing.publications.forEach { publication ->
-        publication.pom.withXml {
-            def root = asNode()
-            //root.appendNode('groupId', project.group)
-            //root.appendNode('artifactId', project.name)
-            //root.appendNode('version', project.version)
-            root.appendNode('name', project.name)
-            root.appendNode('description', project.description)
-            root.appendNode('url', miraiGitHubUrl)
-            root.children().last() + {
-                licenses {
-                    license {
-                        name "AGPL-V3"
-                        url "https://www.gnu.org/licenses/agpl-3.0.txt"
-                        distribution "repo"
-                    }
-                }
-                developers {
-                    developer {
-                        id "mamoe"
-                        name "Mamoe Technologies"
-                        email "[email protected]"
+/**
+ * Publish the platform JAR and POM so that consumers who depend on this module and can't read Gradle module
+ * metadata can still get the platform artifact and transitive dependencies from the POM
+ * (see details in https://youtrack.jetbrains.com/issue/KT-39184#focus=streamItem-27-4115233.0-0)
+ */
+project.ext.publishPlatformArtifactsInRootModule = { platformPublication ->
+    afterEvaluate {
+        def platformPomBuilder = null
+
+        platformPublication.pom.withXml { platformPomBuilder = asString() }
+
+        publishing.publications.kotlinMultiplatform {
+            platformPublication.artifacts.forEach {
+                artifact(it)
+            }
+
+            pom.withXml {
+                def pomStringBuilder = asString()
+                pomStringBuilder.setLength(0)
+                // The platform POM needs its artifact ID replaced with the artifact ID of the root module:
+                def platformPomString = platformPomBuilder.toString()
+                platformPomString.eachLine { line ->
+                    if (!line.contains("<!--")) { // Remove the Gradle module metadata marker as it will be added anew
+                        pomStringBuilder.append(line.replace(platformPublication.artifactId, artifactId))
+                        pomStringBuilder.append("\n")
                     }
                 }
-                scm {
-                    url miraiGitHubUrl
-                }
             }
         }
+
+        tasks.matching { it.name == "generatePomFileForKotlinMultiplatformPublication" }.configureEach {
+            dependsOn(tasks["generatePomFileFor${platformPublication.name.capitalize()}Publication"])
+        }
     }
 }
 
-bintrayUpload.doFirst {
-    publications = project.publishing.publications
-}
+def isKotlin137x = false
 
-bintrayUpload.dependsOn {
-    def list = new LinkedList<Task>()
-    list.add(tasks.getByName("build"))
+afterEvaluate {
 
-    list.addAll(tasks.findAll { task -> task.name.contains('Jar') })
-    list.addAll(tasks.findAll { task -> task.name.startsWith('generateMetadataFileFor') })
-    list.addAll(tasks.findAll { task -> task.name.startsWith('generatePomFileFor') })
+    publishing {
+        def variantName = "${project.name}"
+
+        // Rename artifacts for backward compatibility
+        publications.all {
+            def type = it.name
+            logger.info("Configuring $type")
+            switch (type) {
+                case 'kotlinMultiplatform':
+                    if (isKotlin137x) {
+                        it.artifactId = "$variantName-native"
+                        it.artifact sourcesJar
+                    } else {
+                        // With Kotlin 1.4.0, the root module ID has no suffix, but for compatibility with
+                        // the consumers who can't read Gradle module metadata, we publish the JVM artifacts in it
+                        it.artifactId = variantName
+                        publishPlatformArtifactsInRootModule(publications["jvm"])
+                    }
+                    break
 
-    list
-}
+                case 'metadata':
+                    it.artifactId = isKotlin137x ? "$variantName-common" : "$variantName-metadata"
+                    break
 
-try {
+                case 'jvm':
+                    it.artifactId = isKotlin137x ? "$variantName" : "$variantName-jvm"
+                    break
 
-// empty xxx-javadoc.jar
-    task javadocJar(type: Jar) {
-        archiveClassifier = 'javadoc'
-    }
+                case 'js':
+                    it.artifactId = "$variantName-$type"
+                    break
+            }
+            logger.info("Artifact id = ${it.artifactId}")
 
-} catch (Exception ignored) {
+            pom.withXml(configureMavenCentralMetadata)
 
-}
-publishing {
-    publications.all {
-        // add empty javadocs (no need for MPP root publication which publishes only pom file)
-        if (it.name != 'kotlinMultiplatform') {
-            it.artifact(javadocJar)
-        }
+            // The 'root' module publishes the JVM module's Javadoc JAR as per publishPlatformArtifactsInRootModule, and
 
-        // Rename MPP artifacts for backward compatibility
-        def type = it.name
-        switch (type) {
-            case 'kotlinMultiplatform':
-                it.artifactId = "$project.name-native"
-                break
-            case 'metadata':
-                it.artifactId = "$project.name-common"
-                break
-            case 'jvm':
-                it.artifactId = "$project.name"
-                break
-            case 'js':
-            case 'native':
-                it.artifactId = "$project.name-$type"
-                break
+            if (name != "kotlinMultiplatform")
+                artifact stubJavadoc
         }
 
-        // disable metadata everywhere, but in native modules
-        if (type == 'maven' || type == 'metadata' || type == 'jvm' || type == 'js') {
-            moduleDescriptorGenerator = null
+        if (isKotlin137x) {
+            disableMetadataPublication()
         }
     }
 }
 
-// bintrayUpload.dependsOn publishToMavenLocal
+
+if (upload.Bintray.isBintrayAvailable(project)) {
+    apply from: rootProject.file("gradle/bintray.gradle")
+}
+
+/*
+task bintrayUpload(dependsOn: publish)
+
+// This is required for K/N publishing
+bintrayUpload.dependsOn publishToMavenLocal
+
+
+bintrayUpload.dependsOn generatePomFileForKotlinMultiplatformPublication
+ */

+ 129 - 0
gradle/publishOld.gradle

@@ -0,0 +1,129 @@
+import upload.Bintray
+
+// 部分源码来自 kotlinx.coroutines
+// Source code from kotlinx.coroutines
+
+task ensureBintrayAvailable() {
+    doLast {
+        if (!Bintray.isBintrayAvailable(project)) {
+            throw new IllegalStateException("bintray isn't available. ")
+        }
+    }
+}
+
+if (!Bintray.isBintrayAvailable(project)) {
+    println("bintray isn't available. NO PUBLICATIONS WILL BE SET")
+    return
+}
+
+def miraiGitHubUrl = "https://github.com/mamoe/mirai"
+
+bintray {
+    user = Bintray.getUser(project)
+    key = Bintray.getKey(project)
+
+    pkg {
+        repo = 'mirai'
+        name = "mirai-core"
+        licenses = ['AGPL']
+        vcsUrl = miraiGitHubUrl
+        websiteUrl = miraiGitHubUrl
+        githubRepo = miraiGitHubUrl
+        issueTrackerUrl = "$miraiGitHubUrl/issues"
+       /* version {
+            name = project.version
+        }*/
+    }
+}
+
+afterEvaluate {
+    project.publishing.publications.forEach { publication ->
+        publication.pom.withXml {
+            def root = asNode()
+            //root.appendNode('groupId', project.group)
+            //root.appendNode('artifactId', project.name)
+            //root.appendNode('version', project.version)
+            root.appendNode('name', project.name)
+            root.appendNode('description', project.description)
+            root.appendNode('url', miraiGitHubUrl)
+            root.children().last() + {
+                licenses {
+                    license {
+                        name "AGPL-V3"
+                        url "https://www.gnu.org/licenses/agpl-3.0.txt"
+                        distribution "repo"
+                    }
+                }
+                developers {
+                    developer {
+                        id "mamoe"
+                        name "Mamoe Technologies"
+                        email "[email protected]"
+                    }
+                }
+                scm {
+                    url miraiGitHubUrl
+                }
+            }
+        }
+    }
+}
+
+bintrayUpload.doFirst {
+    publications = project.publishing.publications
+}
+
+bintrayUpload.dependsOn {
+    def list = new LinkedList<Task>()
+    list.add(tasks.getByName("build"))
+
+    list.addAll(tasks.findAll { task -> task.name.contains('Jar') })
+    list.addAll(tasks.findAll { task -> task.name.startsWith('generateMetadataFileFor') })
+    list.addAll(tasks.findAll { task -> task.name.startsWith('generatePomFileFor') })
+
+    list
+}
+
+try {
+
+// empty xxx-javadoc.jar
+    task javadocJar(type: Jar) {
+        archiveClassifier = 'javadoc'
+    }
+
+} catch (Exception ignored) {
+
+}
+publishing {
+    publications.all {
+        // add empty javadocs (no need for MPP root publication which publishes only pom file)
+        if (it.name != 'kotlinMultiplatform') {
+            it.artifact(javadocJar)
+        }
+
+        // Rename MPP artifacts for backward compatibility
+        def type = it.name
+        switch (type) {
+            case 'kotlinMultiplatform':
+                it.artifactId = "$project.name-native"
+                break
+            case 'metadata':
+                it.artifactId = "$project.name-common"
+                break
+            case 'jvm':
+                it.artifactId = "$project.name"
+                break
+            case 'js':
+            case 'native':
+                it.artifactId = "$project.name-$type"
+                break
+        }
+
+        // disable metadata everywhere, but in native modules
+        if (type == 'maven' || type == 'metadata' || type == 'jvm' || type == 'js') {
+            moduleDescriptorGenerator = null
+        }
+    }
+}
+
+// bintrayUpload.dependsOn publishToMavenLocal

+ 16 - 0
mirai-core-qqandroid/build.gradle.kts

@@ -114,3 +114,19 @@ kotlin {
 }
 
 apply(from = rootProject.file("gradle/publish.gradle"))
+
+
+tasks.withType<com.jfrog.bintray.gradle.tasks.BintrayUploadTask> {
+    doFirst {
+        publishing.publications
+            .filterIsInstance<MavenPublication>()
+            .forEach { publication ->
+                val moduleFile = buildDir.resolve("publications/${publication.name}/module.json")
+                if (moduleFile.exists()) {
+                    publication.artifact(object : org.gradle.api.publish.maven.internal.artifact.FileBasedMavenArtifact(moduleFile) {
+                        override fun getDefaultExtension() = "module"
+                    })
+                }
+            }
+    }
+}

+ 17 - 1
mirai-core/build.gradle.kts

@@ -51,6 +51,7 @@ kotlin {
             languageSettings.useExperimentalAnnotation("kotlin.experimental.ExperimentalTypeInference")
             languageSettings.useExperimentalAnnotation("kotlin.time.ExperimentalTime")
             languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
+            languageSettings.useExperimentalAnnotation("kotlinx.serialization.ExperimentalSerializationApi")
 
             languageSettings.progressiveMode = true
         }
@@ -131,4 +132,19 @@ kotlin {
     }
 }
 
-apply(from = rootProject.file("gradle/publish.gradle"))
+apply(from = rootProject.file("gradle/publish.gradle"))
+
+tasks.withType<com.jfrog.bintray.gradle.tasks.BintrayUploadTask> {
+    doFirst {
+        publishing.publications
+            .filterIsInstance<MavenPublication>()
+            .forEach { publication ->
+                val moduleFile = buildDir.resolve("publications/${publication.name}/module.json")
+                if (moduleFile.exists()) {
+                    publication.artifact(object : org.gradle.api.publish.maven.internal.artifact.FileBasedMavenArtifact(moduleFile) {
+                        override fun getDefaultExtension() = "module"
+                    })
+                }
+            }
+    }
+}