Configure shadow relocation and add checks for multiplatform publishing

This commit is contained in:
Him188 2022-06-26 16:03:15 +08:00
parent dc747ea438
commit fd67ba9204
25 changed files with 1034 additions and 187 deletions

View File

@ -280,6 +280,9 @@ jobs:
- name: "Assemble" - name: "Assemble"
run: ./gradlew assemble ${{ env.gradleArgs }} run: ./gradlew assemble ${{ env.gradleArgs }}
- name: Publish Local Artifacts
run: ./gradlew :mirai-deps-test:publishMiraiLocalArtifacts ${{ env.gradleArgs }}
- name: "Check" - name: "Check"
run: ./gradlew check ${{ env.gradleArgs }} run: ./gradlew check ${{ env.gradleArgs }}
@ -403,3 +406,9 @@ jobs:
- name: "Test mirai-core for ${{ matrix.os }}" - name: "Test mirai-core for ${{ matrix.os }}"
run: ./gradlew :mirai-core:${{ matrix.targetName }}Test ${{ env.gradleArgs }} run: ./gradlew :mirai-core:${{ matrix.targetName }}Test ${{ env.gradleArgs }}
- name: Publish Local Artifacts
run: ./gradlew :mirai-deps-test:publishMiraiLocalArtifacts ${{ env.gradleArgs }}
- name: Check Publication
run: ./gradlew :mirai-deps-test:check ${{ env.gradleArgs }}

View File

@ -37,9 +37,13 @@ jobs:
- name: Assemble - name: Assemble
run: ./gradlew assemble --scan run: ./gradlew assemble --scan
- name: Publish Local Artifacts
run: >
./gradlew :mirai-deps-test:publishMiraiLocalArtifacts --scan
- name: Check - name: Check
run: > run: >
./gradlew check --scan --no-parallel ./gradlew check --scan
-Dmirai.network.show.all.components=true -Dmirai.network.show.all.components=true
-Dkotlinx.coroutines.debug=on -Dkotlinx.coroutines.debug=on
-Dmirai.network.show.packet.details=true -Dmirai.network.show.packet.details=true

View File

@ -12,8 +12,6 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.jetbrains.dokka.base.DokkaBase import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.DokkaBaseConfiguration import org.jetbrains.dokka.base.DokkaBaseConfiguration
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import java.time.LocalDateTime import java.time.LocalDateTime
buildscript { buildscript {
@ -35,12 +33,13 @@ buildscript {
} }
plugins { plugins {
kotlin("jvm") // version Versions.kotlinCompiler kotlin("jvm") apply false // version Versions.kotlinCompiler
kotlin("plugin.serialization") version Versions.kotlinCompiler kotlin("plugin.serialization") version Versions.kotlinCompiler apply false
id("com.google.osdetector") id("com.google.osdetector")
id("org.jetbrains.dokka") version Versions.dokka id("org.jetbrains.dokka") version Versions.dokka
id("me.him188.kotlin-jvm-blocking-bridge") version Versions.blockingBridge id("me.him188.kotlin-jvm-blocking-bridge") version Versions.blockingBridge
id("me.him188.kotlin-dynamic-delegation") version Versions.dynamicDelegation id("me.him188.kotlin-dynamic-delegation") version Versions.dynamicDelegation apply false
id("me.him188.maven-central-publish") version Versions.mavenCentralPublish apply false
id("com.gradle.plugin-publish") version "1.0.0-rc-3" apply false id("com.gradle.plugin-publish") version "1.0.0-rc-3" apply false
id("org.jetbrains.kotlinx.binary-compatibility-validator") version Versions.binaryValidator apply false id("org.jetbrains.kotlinx.binary-compatibility-validator") version Versions.binaryValidator apply false
} }
@ -179,43 +178,3 @@ fun Project.configureDokka() {
} }
} }
} }
fun Project.configureMppShadow() {
val kotlin =
runCatching {
(this as ExtensionAware).extensions.getByName("kotlin") as? KotlinMultiplatformExtension
}.getOrNull() ?: return
if (project.configurations.findByName("jvmRuntimeClasspath") != null) {
val shadowJvmJar by tasks.creating(ShadowJar::class) sd@{
group = "mirai"
archiveClassifier.set("-all")
val compilations =
kotlin.targets.filter { it.platformType == KotlinPlatformType.jvm }
.map { it.compilations["main"] }
compilations.forEach {
dependsOn(it.compileKotlinTask)
from(it.output)
}
from(project.configurations.findByName("jvmRuntimeClasspath"))
this.exclude { file ->
file.name.endsWith(".sf", ignoreCase = true)
}
/*
this.manifest {
this.attributes(
"Manifest-Version" to 1,
"Implementation-Vendor" to "Mamoe Technologies",
"Implementation-Title" to this.name.toString(),
"Implementation-Version" to this.version.toString()
)
}*/
}
}
}

View File

@ -57,6 +57,7 @@ dependencies {
api(asm("tree")) api(asm("tree"))
api(asm("util")) api(asm("util"))
api(asm("commons")) api(asm("commons"))
api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
api("gradle.plugin.com.google.gradle:osdetector-gradle-plugin:1.7.0") api("gradle.plugin.com.google.gradle:osdetector-gradle-plugin:1.7.0")

View File

@ -25,7 +25,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import org.jetbrains.kotlin.gradle.plugin.mpp.TestExecutable import org.jetbrains.kotlin.gradle.plugin.mpp.TestExecutable
import java.io.File import java.io.File
private val miraiPlatform = Attribute.of( val MIRAI_PLATFORM_ATTRIBUTE = Attribute.of(
"net.mamoe.mirai.platform", String::class.java "net.mamoe.mirai.platform", String::class.java
) )
@ -140,7 +140,7 @@ fun Project.configureJvmTargetsHierarchical() {
this.compileKotlinTask.enabled = false // IDE complain this.compileKotlinTask.enabled = false // IDE complain
} }
attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.common) // magic attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.common) // magic
attributes.attribute(miraiPlatform, "jvmBase") // avoid resolution attributes.attribute(MIRAI_PLATFORM_ATTRIBUTE, "jvmBase") // avoid resolution
} }
} }
@ -160,7 +160,7 @@ fun Project.configureJvmTargetsHierarchical() {
jvm("android") { jvm("android") {
attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.androidJvm) attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.androidJvm)
if (IDEA_ACTIVE) { if (IDEA_ACTIVE) {
attributes.attribute(miraiPlatform, "android") // avoid resolution attributes.attribute(MIRAI_PLATFORM_ATTRIBUTE, "android") // avoid resolution
} }
} }
val androidMain by sourceSets.getting val androidMain by sourceSets.getting

View File

@ -1,10 +1,10 @@
/* /*
* Copyright 2019-2021 Mamoe Technologies and contributors. * Copyright 2019-2022 Mamoe Technologies and contributors.
* *
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* *
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/dev/LICENSE
*/ */
import org.gradle.api.NamedDomainObjectCollection import org.gradle.api.NamedDomainObjectCollection
@ -13,17 +13,10 @@ import org.gradle.api.Project
import org.gradle.api.artifacts.DependencySubstitutions import org.gradle.api.artifacts.DependencySubstitutions
import org.gradle.api.artifacts.ResolutionStrategy import org.gradle.api.artifacts.ResolutionStrategy
import org.gradle.api.artifacts.component.ComponentSelector import org.gradle.api.artifacts.component.ComponentSelector
import org.gradle.api.plugins.ExtensionAware
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import java.util.* import java.util.*
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
private object ProjectAndroidSdkAvailability { private object ProjectAndroidSdkAvailability {
val map: MutableMap<String, Boolean> = mutableMapOf() val map: MutableMap<String, Boolean> = mutableMapOf()
@ -117,3 +110,10 @@ fun ResolutionStrategy.substituteDependencies(action: ResolutionStrategyDsl.() -
action(ResolutionStrategyDsl(this)) action(ResolutionStrategyDsl(this))
} }
} }
val Project.kotlinMpp
get() = runCatching {
(this as ExtensionAware).extensions.getByName("kotlin") as? KotlinMultiplatformExtension
}.getOrNull()

View File

@ -11,6 +11,7 @@ import org.gradle.api.Project
import org.gradle.api.XmlProvider import org.gradle.api.XmlProvider
import org.gradle.api.publish.maven.MavenArtifact import org.gradle.api.publish.maven.MavenArtifact
import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.TaskProvider
import org.gradle.jvm.tasks.Jar import org.gradle.jvm.tasks.Jar
import org.gradle.kotlin.dsl.get import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.register
@ -43,14 +44,58 @@ fun Project.configureMppPublishing() {
publishing { publishing {
logPublishing("Publications: ${publications.joinToString { it.name }}") logPublishing("Publications: ${publications.joinToString { it.name }}")
publications.filterIsInstance<MavenPublication>().forEach { publication -> val (nonJvmPublications, jvmPublications) = publications.filterIsInstance<MavenPublication>()
.partition { publication -> tasks.findByName("relocate${publication.name.titlecase()}Dependencies") == null }
for (publication in nonJvmPublications) {
configureMultiplatformPublication(publication, stubJavadoc, publication.name)
}
for (publication in jvmPublications) {
// publications.remove(publication)
// val newPublication =
// publications.register(publication.name + "Shadowed", MavenPublication::class.java) {
// val target = kotlinTargets.orEmpty().single { it.targetName == publication.name }
// from(target.components.single())
// this.groupId = publication.groupId
// this.artifactId = publication.artifactId
// this.version = publication.version
// artifacts {
// publication.artifacts
// .filter { !(it.classifier.isNullOrEmpty() && it.extension == "jar") } // not .jar
// .forEach { artifact(it) } // copy Kotlin metadata artifacts
// }
// artifacts.removeAll { it.classifier.isNullOrEmpty() && it.extension == "jar" }
// // add relocated jar
// tasks.findByName("relocate${publication.name.titlecase()}Dependencies")?.let { relocation ->
// artifact(relocation) {
// classifier = ""
// extension = "jar"
// }
// }
// }
configureMultiplatformPublication(publication, stubJavadoc, publication.name)
publication.apply {
artifacts.filter { it.classifier.isNullOrEmpty() && it.extension == "jar" }.forEach {
it.builtBy(tasks.findByName("relocate${publication.name.titlecase()}Dependencies"))
}
}
}
configGpgSign(this@configureMppPublishing)
}
}
}
private fun Project.configureMultiplatformPublication(
publication: MavenPublication,
stubJavadoc: TaskProvider<Jar>,
moduleName: String,
) {
// Maven Central always require javadoc.jar // Maven Central always require javadoc.jar
publication.artifact(stubJavadoc) publication.artifact(stubJavadoc)
publication.setupPom(project) publication.setupPom(project)
logPublishing(publication.name) logPublishing(publication.name + ": moduleName = $moduleName")
when (val type = publication.name) { when (moduleName) {
"kotlinMultiplatform" -> { "kotlinMultiplatform" -> {
publication.artifactId = project.name publication.artifactId = project.name
@ -62,15 +107,9 @@ fun Project.configureMppPublishing() {
"metadata" -> { // TODO: 2021/1/21 seems no use. none `type` is "metadata" "metadata" -> { // TODO: 2021/1/21 seems no use. none `type` is "metadata"
publication.artifactId = "${project.name}-metadata" publication.artifactId = "${project.name}-metadata"
} }
"common" -> {
}
else -> { else -> {
// "jvm", "native", "js" // "jvm", "native", "js", "common"
publication.artifactId = "${project.name}-$type" publication.artifactId = "${project.name}-$moduleName"
}
}
}
configGpgSign(this@configureMppPublishing)
} }
} }
} }

View File

@ -111,8 +111,8 @@ fun Project.configureKotlinTestSettings() {
dependencies { dependencies {
"testImplementation"(kotlin("test-junit5"))?.because(b) "testImplementation"(kotlin("test-junit5"))?.because(b)
"testApi"("org.junit.jupiter:junit-jupiter-api:${Versions.junit}")?.because(b) "testApi"(`junit-jupiter-api`)?.because(b)
"testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:${Versions.junit}")?.because(b) "testRuntimeOnly"(`junit-jupiter-engine`)?.because(b)
} }
} }
isKotlinMpp -> { isKotlinMpp -> {
@ -121,8 +121,8 @@ fun Project.configureKotlinTestSettings() {
sourceSet.dependencies { sourceSet.dependencies {
implementation(kotlin("test-junit5"))?.because(b) implementation(kotlin("test-junit5"))?.because(b)
implementation("org.junit.jupiter:junit-jupiter-api:${Versions.junit}")?.because(b) implementation(`junit-jupiter-api`)?.because(b)
runtimeOnly("org.junit.jupiter:junit-jupiter-engine:${Versions.junit}")?.because(b) runtimeOnly(`junit-jupiter-engine`)?.because(b)
} }
} }

View File

@ -0,0 +1,276 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import org.gradle.api.DomainObjectCollection
import org.gradle.api.Project
import org.gradle.api.publish.tasks.GenerateModuleMetadata
import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.creating
import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.get
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import java.io.File
fun Project.configureMppShadow() {
val kotlin = kotlinMpp ?: return
configure(kotlin.targets.filter {
it.platformType == org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.jvm
&& it.attributes.getAttribute(MIRAI_PLATFORM_ATTRIBUTE) == null
}) {
configureRelocationForTarget(project)
}
// regular shadow file, with suffix `-all`
configureRegularShadowJar(kotlin)
}
/**
* Relocate some dependencies for `.jar`
*/
private fun KotlinTarget.configureRelocationForTarget(project: Project) = project.run {
val relocateDependencies =
// e.g. relocateJvmDependencies
tasks.create("relocate${targetName.titlecase()}Dependencies", ShadowJar::class) {
group = "mirai"
description = "Relocate dependencies to internal package"
destinationDirectory.set(buildDir.resolve("libs"))
// archiveClassifier.set("")
archiveBaseName.set("${project.name}-${targetName.toLowerCase()}")
dependsOn(compilations["main"].compileKotlinTask) // compileKotlinJvm
// Run after all *Jar tasks from all projects, since Kotlin compiler may depend on the .jar file, concurrently modifying the jar will cause Kotlin compiler to fail.
// allprojects
// .asSequence()
// .flatMap { it.tasks }
// .filter { it.name.contains("compileKotlin") }
// .forEach { jar ->
// mustRunAfter(jar)
// }
from(compilations["main"].output)
// // change name to
// doLast {
// outputs.files.singleFile.renameTo(
// outputs.files.singleFile.parentFile.resolve(
// "${project.name}-${targetName.toLowerCase()}-${project.version}.jar"
// )
// )
// }
// Filter only those should be relocated
afterEvaluate {
setRelocations()
var fileFiltered = relocationFilters.isEmpty()
from(project.configurations.getByName("${targetName}RuntimeClasspath")
.files
.filter { file ->
relocationFilters.any { filter ->
// file.absolutePath example: /Users/xxx/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.7.0-RC/7f9f07fc65e534c15a820f61d846b9ffdba8f162/kotlin-stdlib-jdk8-1.7.0-RC.jar
filter.matchesFile(file)
}.also {
fileFiltered = fileFiltered || it
if (it) {
println("Including file: ${file.absolutePath}")
}
}
}
)
check(fileFiltered) { "[Shadow Relocation] Expected at least one file filtered for target $targetName. Filters: $relocationFilters" }
}
}
val allTasks = rootProject.allprojects.asSequence().flatMap { it.tasks }
allTasks
.filter {
it.name.startsWith("publish${targetName.titlecase()}PublicationTo")
}
.onEach { it.dependsOn(relocateDependencies) }
.count().let {
check(it > 0) { "[Shadow Relocation] Expected at least one publication matched for target $targetName." }
}
// Ensure all compilation has finished, otherwise Kotlin compiler will complain.
allTasks
.filter { it.name.endsWith("Jar") }
.onEach { relocateDependencies.dependsOn(it) }
.count().let {
check(it > 0) { "[Shadow Relocation] Expected at least one task matched for target $targetName." }
}
allTasks
.filter { it.name.startsWith("compileKotlin") }
.onEach { relocateDependencies.dependsOn(it) }
.count().let {
check(it > 0) { "[Shadow Relocation] Expected at least one task matched for target $targetName." }
}
val metadataTask =
tasks.getByName("generateMetadataFileFor${targetName.capitalize()}Publication") as GenerateModuleMetadata
relocateDependencies.dependsOn(metadataTask)
afterEvaluate {
// remove dependencies in Maven pom
mavenPublication {
pom.withXml {
val node = this.asNode().getSingleChild("dependencies")
val dependencies = node.childrenNodes()
logger.trace("[Shadow Relocation] deps: $dependencies")
dependencies.forEach { dep ->
val groupId = dep.getSingleChild("groupId").value().toString()
val artifactId = dep.getSingleChild("artifactId").value().toString()
logger.trace("[Shadow Relocation] Checking $groupId:$artifactId")
if (
relocationFilters.any { filter ->
filter.matchesDependency(groupId = groupId, artifactId = artifactId)
}
) {
println("[Shadow Relocation] Filtering out $groupId:$artifactId from pom")
check(node.remove(dep)) { "Failed to remove dependency node" }
}
}
}
}
// remove dependencies in Kotlin module metadata
relocateDependencies.doLast {
// mirai-core-jvm-2.13.0.module
val file = metadataTask.outputFile.asFile.get()
val metadata = Gson().fromJson(
file.readText(),
com.google.gson.JsonElement::class.java
).asJsonObject
val metadataVersion = metadata["formatVersion"]?.asString
check(metadataVersion == "1.1") {
"Unsupported Kotlin metadata version. version=$metadataVersion, file=${file.absolutePath}"
}
for (variant in metadata["variants"]!!.asJsonArray) {
val dependencies = variant.asJsonObject["dependencies"]!!.asJsonArray
dependencies.removeAll { dependency ->
val dep = dependency.asJsonObject
val groupId = dep["group"]!!.asString
val artifactId = dep["module"]!!.asString
relocationFilters.any { filter ->
filter.matchesDependency(
groupId = groupId,
artifactId = artifactId
)
}.also {
println("[Shadow Relocation] Filtering out $groupId:$artifactId from Kotlin module")
}
}
}
file.writeText(GsonBuilder().setPrettyPrinting().create().toJson(metadata))
}
}
}
private fun Project.configureRegularShadowJar(kotlin: KotlinMultiplatformExtension) {
if (project.configurations.findByName("jvmRuntimeClasspath") != null) {
val shadowJvmJar by tasks.creating(ShadowJar::class) sd@{
group = "mirai"
archiveClassifier.set("-all")
val compilations =
kotlin.targets.filter { it.platformType == KotlinPlatformType.jvm }
.map { it.compilations["main"] }
compilations.forEach {
dependsOn(it.compileKotlinTask)
from(it.output)
}
setRelocations()
from(project.configurations.findByName("jvmRuntimeClasspath"))
this.exclude { file ->
file.name.endsWith(".sf", ignoreCase = true)
}
/*
this.manifest {
this.attributes(
"Manifest-Version" to 1,
"Implementation-Vendor" to "Mamoe Technologies",
"Implementation-Title" to this.name.toString(),
"Implementation-Version" to this.version.toString()
)
}*/
}
}
}
data class RelocationFilter(
val groupId: String,
val artifactId: String? = null,
val shadowFilter: String = groupId,
val filesFilter: String = groupId.replace(".", "/")
) {
fun matchesFile(file: File): Boolean {
val path = file.absolutePath.replace("\\", "/")
return filesFilter in path
|| groupId in path
}
fun matchesDependency(groupId: String?, artifactId: String?): Boolean {
if (this.groupId == groupId) return true
if (this.artifactId != null && this.artifactId == artifactId) return true
return false
}
}
val Project.relocationFilters: DomainObjectCollection<RelocationFilter>
get() {
if (project.extra.has("relocationFilters")) {
@Suppress("UNCHECKED_CAST")
return project.extra.get("relocationFilters") as DomainObjectCollection<RelocationFilter>
} else {
val container = project.objects.domainObjectSet(RelocationFilter::class.java)
project.extra.set("relocationFilters", container)
return container
}
}
private const val relocationRootPackage = "net.mamoe.mirai.internal.deps"
private fun ShadowJar.setRelocations() {
project.relocationFilters.forEach { relocation ->
relocate(relocation.shadowFilter, "$relocationRootPackage.${relocation.groupId}")
}
}
fun Project.configureRelocationForCore() {
relocateAllFromGroupId("io.ktor")
}
fun Project.relocateAllFromGroupId(groupId: String) {
relocationFilters.add(RelocationFilter(groupId))
}
// This does not include transitive dependencies
fun Project.relocateExactArtifact(groupId: String, artifactId: String) {
relocationFilters.add(RelocationFilter(groupId, artifactId))
}

View File

@ -13,6 +13,9 @@ import org.gradle.api.attributes.Attribute
import org.gradle.kotlin.dsl.exclude import org.gradle.kotlin.dsl.exclude
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
// DO NOT CHANGE FILENAME OR RELATIVE PATH TO ROOT PROJECT.
// mirai-deps-test DEPENDS ON THE PATH.
object Versions { object Versions {
val project = System.getenv("mirai.build.project.version") val project = System.getenv("mirai.build.project.version")
?: /*PROJECT_VERSION_START*/"2.13.0"/*PROJECT_VERSION_END*/ ?: /*PROJECT_VERSION_START*/"2.13.0"/*PROJECT_VERSION_END*/
@ -22,11 +25,11 @@ object Versions {
val consoleIntellij = "221-$project-162-1" // idea-mirai-kotlin-patch val consoleIntellij = "221-$project-162-1" // idea-mirai-kotlin-patch
val consoleTerminal = project val consoleTerminal = project
const val kotlinCompiler = "1.7.0-RC" const val kotlinCompiler = "1.7.0"
const val kotlinStdlib = kotlinCompiler const val kotlinStdlib = kotlinCompiler
const val dokka = "1.6.21" const val dokka = "1.6.21"
const val kotlinCompilerForIdeaPlugin = "1.7.0-RC" const val kotlinCompilerForIdeaPlugin = "1.7.0"
const val coroutines = "1.6.2" const val coroutines = "1.6.2"
const val atomicFU = "0.17.2" const val atomicFU = "0.17.2"
@ -40,6 +43,7 @@ object Versions {
const val blockingBridge = "2.1.0-170.1" const val blockingBridge = "2.1.0-170.1"
const val dynamicDelegation = "0.3.0-170.1" const val dynamicDelegation = "0.3.0-170.1"
const val mavenCentralPublish = "1.0.0-dev-3"
const val androidGradlePlugin = "4.1.1" const val androidGradlePlugin = "4.1.1"
const val android = "4.1.1.4" const val android = "4.1.1.4"
@ -138,7 +142,9 @@ const val `kotlin-stdlib-jdk8` = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${Vers
const val `kotlin-reflect` = "org.jetbrains.kotlin:kotlin-reflect:${Versions.kotlinStdlib}" const val `kotlin-reflect` = "org.jetbrains.kotlin:kotlin-reflect:${Versions.kotlinStdlib}"
const val `kotlin-test` = "org.jetbrains.kotlin:kotlin-test:${Versions.kotlinStdlib}" const val `kotlin-test` = "org.jetbrains.kotlin:kotlin-test:${Versions.kotlinStdlib}"
const val `kotlin-test-junit5` = "org.jetbrains.kotlin:kotlin-test-junit5:${Versions.kotlinStdlib}" const val `kotlin-test-junit5` = "org.jetbrains.kotlin:kotlin-test-junit5:${Versions.kotlinStdlib}"
const val `junit-jupiter-api` = "org.junit.jupiter:junit-jupiter-api:${Versions.junit}"
const val `junit-jupiter-params` = "org.junit.jupiter:junit-jupiter-params:${Versions.junit}"
const val `junit-jupiter-engine` = "org.junit.jupiter:junit-jupiter-engine:${Versions.junit}"
//const val `mirai-core-api` = "net.mamoe:mirai-core-api:${Versions.core}" //const val `mirai-core-api` = "net.mamoe:mirai-core-api:${Versions.core}"
//const val `mirai-core` = "net.mamoe:mirai-core:${Versions.core}" //const val `mirai-core` = "net.mamoe:mirai-core:${Versions.core}"

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2019-2021 Mamoe Technologies and contributors. * Copyright 2019-2022 Mamoe Technologies and contributors.
* *
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -7,6 +7,8 @@
* https://github.com/mamoe/mirai/blob/dev/LICENSE * https://github.com/mamoe/mirai/blob/dev/LICENSE
*/ */
import groovy.util.Node
import groovy.util.NodeList
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import java.security.MessageDigest import java.security.MessageDigest
@ -60,3 +62,14 @@ fun InputStream.md5(): ByteArray {
} }
return digest.digest() return digest.digest()
} }
fun Node.getSingleChild(name: String): Node {
return (this.get(name) as NodeList).single() as Node
}
fun Node.childrenNodes(): List<Node> {
return this.children().filterIsInstance<Node>()
}

View File

@ -46,14 +46,13 @@ dependencies {
implementation(`log4j-core`) implementation(`log4j-core`)
testApi(kotlin("test-junit5")) testApi(kotlin("test-junit5"))
testApi("org.junit.jupiter:junit-jupiter-api:${Versions.junit}") testApi(`junit-jupiter-api`)
testApi("org.junit.jupiter:junit-jupiter-params:${Versions.junit}") testApi(`junit-jupiter-params`)
"integTestApi"(kotlin("test-junit5")) "integTestApi"(kotlin("test-junit5"))
"integTestApi"("org.junit.jupiter:junit-jupiter-api:${Versions.junit}") "integTestApi"(`junit-jupiter-api`)
"integTestApi"("org.junit.jupiter:junit-jupiter-params:${Versions.junit}") "integTestApi"(`junit-jupiter-params`)
"integTestImplementation"("org.junit.jupiter:junit-jupiter-engine:${Versions.junit}") "integTestImplementation"(`junit-jupiter-engine`)
// "integTestImplementation"("org.spockframework:spock-core:1.3-groovy-2.5")
"integTestImplementation"(gradleTestKit()) "integTestImplementation"(gradleTestKit())
kotlinVersionForIntegrationTest(kotlin("gradle-plugin", "1.5.21")) kotlinVersionForIntegrationTest(kotlin("gradle-plugin", "1.5.21"))

View File

@ -1,10 +1,10 @@
/* /*
* Copyright 2019-2021 Mamoe Technologies and contributors. * Copyright 2019-2022 Mamoe Technologies and contributors.
* *
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* *
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/dev/LICENSE
*/ */
@file:Suppress("UnusedImport") @file:Suppress("UnusedImport")
@ -28,3 +28,5 @@ dependencies {
if (System.getenv("MIRAI_IS_SNAPSHOTS_PUBLISHING")?.toBoolean() != true) { if (System.getenv("MIRAI_IS_SNAPSHOTS_PUBLISHING")?.toBoolean() != true) {
configurePublishing("mirai-core-all") configurePublishing("mirai-core-all")
} }
configureRelocationForCore()

View File

@ -18,6 +18,7 @@ plugins {
id("signing") id("signing")
id("me.him188.kotlin-jvm-blocking-bridge") id("me.him188.kotlin-jvm-blocking-bridge")
id("me.him188.kotlin-dynamic-delegation") id("me.him188.kotlin-dynamic-delegation")
// id("me.him188.maven-central-publish")
`maven-publish` `maven-publish`
} }
@ -106,3 +107,12 @@ if (tasks.findByName("androidMainClasses") != null) {
configureMppPublishing() configureMppPublishing()
configureBinaryValidators(setOf("jvm", "android").filterTargets()) configureBinaryValidators(setOf("jvm", "android").filterTargets())
configureRelocationForCore()
//mavenCentralPublish {
// artifactId = "mirai-core-api"
// githubProject("mamoe", "mirai")
// developer("Mamoe Technologies", email = "support@mamoe.net", url = "https://github.com/mamoe")
// licenseFromGitHubProject("AGPLv3", "dev")
// publishPlatformArtifactsInRootModule = "jvm"
//}

View File

@ -15,6 +15,7 @@ plugins {
id("kotlinx-atomicfu") id("kotlinx-atomicfu")
id("me.him188.kotlin-jvm-blocking-bridge") id("me.him188.kotlin-jvm-blocking-bridge")
// id("me.him188.maven-central-publish")
`maven-publish` `maven-publish`
} }
@ -94,22 +95,13 @@ if (tasks.findByName("androidMainClasses") != null) {
tasks.getByName("androidTest").dependsOn("checkAndroidApiLevel") tasks.getByName("androidTest").dependsOn("checkAndroidApiLevel")
} }
fun org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler.implementation1(dependencyNotation: String) =
implementation(dependencyNotation) {
exclude("org.jetbrains.kotlin", "kotlin-stdlib")
exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-core")
exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-core-common")
exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-core-jvm")
exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-core-metadata")
}
fun org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler.api1(dependencyNotation: String) =
api(dependencyNotation) {
exclude("org.jetbrains.kotlin", "kotlin-stdlib")
exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-core")
exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-core-common")
exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-core-jvm")
exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-core-metadata")
}
configureMppPublishing() configureMppPublishing()
configureRelocationForCore()
//mavenCentralPublish {
// artifactId = "mirai-core-utils"
// githubProject("mamoe", "mirai")
// developer("Mamoe Technologies", email = "support@mamoe.net", url = "https://github.com/mamoe")
// licenseFromGitHubProject("AGPLv3", "dev")
// publishPlatformArtifactsInRootModule = "jvm"
//}

View File

@ -19,6 +19,7 @@ plugins {
kotlin("plugin.serialization") kotlin("plugin.serialization")
id("me.him188.kotlin-jvm-blocking-bridge") id("me.him188.kotlin-jvm-blocking-bridge")
id("me.him188.kotlin-dynamic-delegation") id("me.him188.kotlin-dynamic-delegation")
// id("me.him188.maven-central-publish")
`maven-publish` `maven-publish`
} }
@ -203,3 +204,12 @@ if (tasks.findByName("androidMainClasses") != null) {
configureMppPublishing() configureMppPublishing()
configureBinaryValidators(setOf("jvm", "android").filterTargets()) configureBinaryValidators(setOf("jvm", "android").filterTargets())
configureRelocationForCore()
//mavenCentralPublish {
// artifactId = "mirai-core"
// githubProject("mamoe", "mirai")
// developer("Mamoe Technologies", email = "support@mamoe.net", url = "https://github.com/mamoe")
// licenseFromGitHubProject("AGPLv3", "dev")
// publishPlatformArtifactsInRootModule = "jvm"
//}

1
mirai-deps-test/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
src/BuildConfig.kt

View File

@ -0,0 +1,3 @@
# native-deps-test
测试 Native

View File

@ -0,0 +1,100 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:Suppress("UnusedImport")
plugins {
kotlin("jvm")
id("java-gradle-plugin")
}
dependencies {
implementation(gradleApi())
implementation(gradleKotlinDsl())
implementation(kotlin("gradle-plugin-api"))
implementation(kotlin("gradle-plugin"))
implementation(kotlin("stdlib"))
api("com.github.jengelman.gradle.plugins:shadow:6.0.0")
api(`jetbrains-annotations`)
testImplementation(kotlin("test-junit5"))
testImplementation(`junit-jupiter-api`)
testImplementation(`junit-jupiter-params`)
testRuntimeOnly(`junit-jupiter-engine`)
}
tasks.getByName("test", Test::class) {
environment("mirai.root.project.dir", rootProject.projectDir.absolutePath)
}
val publishMiraiArtifactsToMavenLocal by tasks.registering {
group = "mirai"
description = "Publish all mirai artifacts to MavenLocal"
val publishTasks = rootProject.allprojects.mapNotNull { proj ->
proj.tasks.findByName("publishToMavenLocal")
}
dependsOn(publishTasks)
doLast {
// delete shadowed Jars, since Kotlin can't compile modules that depend on them.
rootProject.subprojects
.asSequence()
.flatMap { proj -> proj.tasks.filter { task -> task.name.contains("relocate") } }
.flatMap { it.outputs.files }
.filter { it.isFile && it.name.endsWith(".jar") }
.forEach { it.delete() }
}
}
tasks.register("generateBuildConfig") {
group = "mirai"
doLast {
val text = """
package net.mamoe.mirai.deps.test
/**
* This file was generated by Gradle task `generateBuildConfig`.
*/
object BuildConfig {
/**
* Kotlin version used to compile mirai-core
*/
const val kotlinVersion = "${Versions.kotlinCompiler}"
}
""".trimIndent() + "\n"
val file = project.projectDir.resolve("src/BuildConfig.kt")
if (!file.exists() || file.readText() != text) {
file.writeText(text)
}
}
tasks.getByName("assemble").dependsOn(this) // if src is empty, compileKotlin will be skipped.
tasks.getByName("compileKotlin").dependsOn(this)
tasks.getByName("compileTestKotlin").dependsOn(this)
}
tasks.register("publishMiraiLocalArtifacts", Exec::class) {
group = "mirai"
description = "Starts a child process to publish v2.99.0-deps-test artifacts to MavenLocal"
workingDir(rootProject.projectDir)
environment("mirai.build.project.version", "2.99.0-deps-test")
commandLine(
"./gradlew",
publishMiraiArtifactsToMavenLocal.name,
"--no-daemon",
"-Pkotlin.compiler.execution.strategy=in-process"
)
standardOutput = System.out
errorOutput = System.err
}
version = Versions.core

View File

@ -0,0 +1,9 @@
#
# Copyright 2019-2022 Mamoe Technologies and contributors.
#
# 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
# Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
#
# https://github.com/mamoe/mirai/blob/dev/LICENSE
#

View File

@ -0,0 +1,173 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.deps.test
import org.gradle.api.internal.artifacts.mvnsettings.DefaultMavenFileLocations
import org.gradle.testkit.runner.GradleRunner
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.extension.AfterEachCallback
import org.junit.jupiter.api.extension.RegisterExtension
import org.junit.jupiter.api.io.TempDir
import java.io.File
// Copied from mirai-console-gradle
abstract class AbstractTest {
companion object {
const val miraiLocalVersion = "2.99.0-deps-test" // do Search Everywhere before changing this
const val REASON_LOCAL_ARTIFACT_NOT_AVAILABLE = "local artifacts not available"
private val mavenLocalDir: File by lazy {
org.gradle.api.internal.artifacts.mvnsettings.DefaultLocalMavenRepositoryLocator(
org.gradle.api.internal.artifacts.mvnsettings.DefaultMavenSettingsProvider(DefaultMavenFileLocations())
).localMavenRepository
}
@JvmStatic
fun isMiraiLocalAvailable(): Boolean {
return if (mavenLocalDir.resolve("net/mamoe/mirai-core/$miraiLocalVersion").exists()) {
println(
"""
[mirai-deps-test] Found local artifacts `$miraiLocalVersion`!
Please note that you may need to manually update local artifacts if you have:
- added/removed a dependency for mirai-core series modules
- changed version of any of the dependencies for mirai-core series modules
You can update by running `./gradlew publishMiraiLocalArtifacts`.
""".trimIndent()
)
true
} else {
System.err.println(
"""
[mirai-deps-test] ERROR: Test is not run, because there are no local artifacts available for dependencies testing.
Please build and publish local artifacts with version `$miraiLocalVersion` before running this test(:mirai-deps-test:test).
This could have be automated but it will take a huge amount of time for your routine testing.
You can run this test manually if you have:
- added/removed a dependency for mirai-core series modules
- changed version of any of the dependencies for mirai-core series modules
Note that you can ignore this test if you did not change project (dependency) structure.
And you don't need to worry if you does not run this test this test is always executed on the CI when you make a PR.
You can run `./gradlew publishMiraiLocalArtifacts` to publish local artifacts.
Then you can run this test again. (By your original way or ./gradlew :mirai-deps-test:test)
""".trimIndent()
)
false
}
}
}
@JvmField
@TempDir
var tempDirField: File? = null
val tempDir: File get() = tempDirField!!
val kotlinVersion = BuildConfig.kotlinVersion
lateinit var mainSrcDir: File
lateinit var commonMainSrcDir: File
lateinit var nativeMainSrcDir: File
lateinit var testDir: File
lateinit var buildFile: File
lateinit var settingsFile: File
lateinit var propertiesFile: File
@OptIn(ExperimentalStdlibApi::class)
fun runGradle(vararg arguments: String) {
System.gc()
GradleRunner.create()
.withProjectDir(tempDir)
.withPluginClasspath()
.withGradleVersion("7.2")
.forwardOutput()
.withEnvironment(System.getenv())
.withArguments(buildList {
addAll(arguments)
add("-Pkotlin.compiler.execution.strategy=in-process")
add("-Dorg.gradle.jvmargs=-Xmx512m -Dfile.encoding=UTF-8")
add("--stacktrace")
})
.build()
}
@BeforeEach
fun setup() {
println("Temp path is " + tempDir.absolutePath)
settingsFile = File(tempDir, "settings.gradle")
settingsFile.delete()
settingsFile.writeText(
"""
pluginManagement {
repositories {
gradlePluginPortal()
mavenCentral()
mavenLocal()
}
}
"""
)
File(tempDir, "gradle.properties").apply {
delete()
writeText(
"""
org.gradle.daemon=false
org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
""".trimIndent()
)
}
mainSrcDir = tempDir.resolve("src/main/kotlin").apply { mkdirs() }
commonMainSrcDir = tempDir.resolve("src/commonMain/kotlin").apply { mkdirs() }
nativeMainSrcDir = tempDir.resolve("src/nativeMain/kotlin").apply { mkdirs() }
testDir = tempDir.resolve("src/test/kotlin").apply { mkdirs() }
buildFile = tempDir.resolve("build.gradle.kts")
buildFile.writeText(
"""
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.7.0"
}
group = "org.example"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
testImplementation(kotlin("test"))
}
tasks.test {
useJUnitPlatform()
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
""".trimIndent() + "\n\n"
)
}
@JvmField
@RegisterExtension
internal val after: AfterEachCallback = AfterEachCallback { context ->
if (context.executionException.isPresent) {
val inst = context.requiredTestInstance as AbstractTest
println("====================== build.gradle ===========================")
println(inst.tempDir.resolve("build.gradle").readText())
println("==================== settings.gradle ==========================")
println(inst.tempDir.resolve("settings.gradle").readText())
}
}
}

View File

@ -0,0 +1,167 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.deps.test
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.condition.EnabledIf
class CoreDependencyResolutionTest : AbstractTest() {
@Test
@EnabledIf("isMiraiLocalAvailable", disabledReason = REASON_LOCAL_ARTIFACT_NOT_AVAILABLE)
fun `test resolve JVM root from Kotlin JVM`() {
mainSrcDir.resolve("main.kt").writeText(
"""
package test
fun main () {
println(net.mamoe.mirai.BotFactory)
}
""".trimIndent()
)
buildFile.writeText(
"""
plugins {
id("org.jetbrains.kotlin.jvm") version "$kotlinVersion"
}
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
implementation("net.mamoe:mirai-core:$miraiLocalVersion")
}
""".trimIndent()
)
runGradle("build")
}
@Test
@EnabledIf("isMiraiLocalAvailable", disabledReason = REASON_LOCAL_ARTIFACT_NOT_AVAILABLE)
fun `test resolve JVM from Kotlin JVM`() {
mainSrcDir.resolve("main.kt").writeText(
"""
package test
fun main () {
println(net.mamoe.mirai.BotFactory)
}
""".trimIndent()
)
buildFile.writeText(
"""
plugins {
id("org.jetbrains.kotlin.jvm") version "$kotlinVersion"
}
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
implementation("net.mamoe:mirai-core-jvm:$miraiLocalVersion")
}
""".trimIndent()
)
runGradle("build")
}
@Test
@EnabledIf("isMiraiLocalAvailable", disabledReason = REASON_LOCAL_ARTIFACT_NOT_AVAILABLE)
fun `test resolve JVM and Native from common`() {
commonMainSrcDir.resolve("main.kt").writeText(
"""
package test
fun main () {
println(net.mamoe.mirai.BotFactory)
}
""".trimIndent()
)
buildFile.writeText(
"""
|import org.apache.tools.ant.taskdefs.condition.Os
|import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
|plugins {
| id("org.jetbrains.kotlin.multiplatform") version "$kotlinVersion"
|}
|repositories {
| mavenCentral()
| mavenLocal()
|}
|kotlin {
| targets {
| jvm()
| val nativeMainSets = mutableListOf<KotlinSourceSet>()
| val nativeTestSets = mutableListOf<KotlinSourceSet>()
| when {
| Os.isFamily(Os.FAMILY_MAC) -> if (Os.isArch("aarch64")) macosArm64("native") else macosX64("native")
| Os.isFamily(Os.FAMILY_WINDOWS) -> mingwX64("native")
| else -> linuxX64("native")
| }
| }
| sourceSets {
| val commonMain by getting {
| dependencies {
| api("net.mamoe:mirai-core:$miraiLocalVersion")
| }
| }
| }
|}
""".trimMargin()
)
runGradle("build")
}
@Test
@EnabledIf("isMiraiLocalAvailable", disabledReason = REASON_LOCAL_ARTIFACT_NOT_AVAILABLE)
fun `test resolve Native from common`() {
nativeMainSrcDir.resolve("main.kt").writeText(
"""
package test
fun main () {
println(net.mamoe.mirai.BotFactory)
}
""".trimIndent()
)
buildFile.writeText(
"""
|import org.apache.tools.ant.taskdefs.condition.Os
|import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
|plugins {
| id("org.jetbrains.kotlin.multiplatform") version "$kotlinVersion"
|}
|repositories {
| mavenCentral()
| mavenLocal()
|}
|kotlin {
| targets {
| jvm()
| val nativeMainSets = mutableListOf<KotlinSourceSet>()
| val nativeTestSets = mutableListOf<KotlinSourceSet>()
| when {
| Os.isFamily(Os.FAMILY_MAC) -> if (Os.isArch("aarch64")) macosArm64("native") else macosX64("native")
| Os.isFamily(Os.FAMILY_WINDOWS) -> mingwX64("native")
| else -> linuxX64("native")
| }
| }
| sourceSets {
| val nativeMain by getting {
| dependencies {
| api("net.mamoe:mirai-core:$miraiLocalVersion")
| }
| }
| }
|}
""".trimMargin()
)
runGradle("build")
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.deps.test
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.condition.EnabledIf
class CoreShadowRelocationTest : AbstractTest() {
@Test
@EnabledIf("isMiraiLocalAvailable", disabledReason = REASON_LOCAL_ARTIFACT_NOT_AVAILABLE)
fun `test OkHttp filtered out`() {
testDir.resolve("test.kt").writeText(
"""
package test
import org.junit.jupiter.api.*
class MyTest {
@Test
fun `test base dependency`() {
assertThrows<ClassNotFoundException> {
Class.forName("io.ktor.client.engine.okhttp.OkHttp")
}
}
@Test
fun `test transitive dependency`() {
assertThrows<ClassNotFoundException> {
Class.forName("okhttp3.OkHttpClient")
}
}
}
""".trimIndent()
)
buildFile.appendText(
"""
dependencies {
implementation("net.mamoe:mirai-core:$miraiLocalVersion")
}
""".trimIndent()
)
runGradle("check")
}
}

View File

@ -0,0 +1,10 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.deps.test

View File

@ -1,15 +1,15 @@
/* /*
* Copyright 2019-2021 Mamoe Technologies and contributors. * Copyright 2019-2022 Mamoe Technologies and contributors.
* *
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* *
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/dev/LICENSE
*/ */
pluginManagement { pluginManagement {
repositories { repositories {
if (System.getProperty("use.maven.local") == "true") { if (System.getProperty("use.maven.local") == "true") { // you can enable by adding `systemProp.use.maven.local=true` in 'gradle.properties'.
mavenLocal() mavenLocal()
} }
gradlePluginPortal() gradlePluginPortal()
@ -18,24 +18,31 @@ pluginManagement {
} }
} }
val allProjects = mutableListOf<ProjectDescriptor>()
rootProject.name = "mirai" rootProject.name = "mirai"
/**
* Projects included so far
*/
val allProjects = mutableListOf<ProjectDescriptor>()
fun includeProject(projectPath: String, dir: String? = null) { fun includeProject(projectPath: String, dir: String? = null) {
include(projectPath) include(projectPath)
if (dir != null) project(projectPath).projectDir = file(dir) if (dir != null) project(projectPath).projectDir = file(dir)
allProjects.add(project(projectPath)) allProjects.add(project(projectPath))
} }
fun includeConsoleProject(projectPath: String, dir: String? = null) =
includeProject(projectPath, "mirai-console/$dir")
includeProject(":mirai-core-utils") includeProject(":mirai-core-utils")
includeProject(":mirai-core-api") includeProject(":mirai-core-api")
includeProject(":mirai-core") includeProject(":mirai-core")
includeProject(":mirai-core-all") includeProject(":mirai-core-all")
includeProject(":mirai-bom") includeProject(":mirai-bom")
includeProject(":mirai-dokka") includeProject(":mirai-dokka")
includeProject(":mirai-deps-test")
//includeProject(":binary-compatibility-validator")
//includeProject(":binary-compatibility-validator-android", "binary-compatibility-validator/android")
includeProject(":mirai-logging-log4j2", "logging/mirai-logging-log4j2") includeProject(":mirai-logging-log4j2", "logging/mirai-logging-log4j2")
includeProject(":mirai-logging-slf4j", "logging/mirai-logging-slf4j") includeProject(":mirai-logging-slf4j", "logging/mirai-logging-slf4j")
@ -43,17 +50,60 @@ includeProject(":mirai-logging-slf4j-simple", "logging/mirai-logging-slf4j-simpl
includeProject(":mirai-logging-slf4j-logback", "logging/mirai-logging-slf4j-logback") includeProject(":mirai-logging-slf4j-logback", "logging/mirai-logging-slf4j-logback")
val disableOldFrontEnds = true
fun includeConsoleProject(projectPath: String, dir: String? = null) =
includeProject(projectPath, "mirai-console/$dir")
includeConsoleProject(":mirai-console-compiler-annotations", "tools/compiler-annotations") includeConsoleProject(":mirai-console-compiler-annotations", "tools/compiler-annotations")
includeConsoleProject(":mirai-console", "backend/mirai-console") includeConsoleProject(":mirai-console", "backend/mirai-console")
includeConsoleProject(":mirai-console.codegen", "backend/codegen") includeConsoleProject(":mirai-console.codegen", "backend/codegen")
includeConsoleProject(":mirai-console-terminal", "frontend/mirai-console-terminal") includeConsoleProject(":mirai-console-terminal", "frontend/mirai-console-terminal")
// region mirai-console.integration-test includeConsoleIntegrationTestProjects()
includeConsoleProject(":mirai-console-compiler-common", "tools/compiler-common")
includeConsoleProject(":mirai-console-intellij", "tools/intellij-plugin")
includeConsoleProject(":mirai-console-gradle", "tools/gradle-plugin")
//includeConsoleFrontendGraphical()
includeProject(":ci-release-helper")
includeBinaryCompatibilityValidatorProjects()
/**
* Configures a project `:validator:path-to-project:target-name` for binary compatibility validation.
*
* To enable validation for a project,
* create a subdirectory with name of the target under "compatibility-validation",
* then sync **twice**. See `:mirai-core-api` for an example.
*
* **Note**: This function depends on [allProjects], and should be used at the end.
*/
fun includeBinaryCompatibilityValidatorProjects() {
val result = mutableListOf<ProjectDescriptor>()
for (project in allProjects) {
val validationDir = project.projectDir.resolve("compatibility-validation")
if (!validationDir.exists()) continue
validationDir.listFiles().orEmpty<File>().forEach { dir ->
if (dir.resolve("build.gradle.kts").isFile) {
val path = ":validator" + project.path + ":${dir.name}"
include(path)
project(path).projectDir = dir
// project(path).name = "${project.name}-validator-${dir.name}"
result.add(project(path))
}
}
}
}
fun includeConsoleLegacyFrontendProjects() {
println("JDK version: ${JavaVersion.current()}")
if (JavaVersion.current() >= JavaVersion.VERSION_1_9) {
includeConsoleProject(":mirai-console-graphical", "frontend/mirai-console-graphical")
} else {
println("当前使用的 JDK 版本为 ${System.getProperty("java.version")}, 请使用 JDK 9 以上版本引入模块 `:mirai-console-graphical`\n")
}
}
fun includeConsoleIntegrationTestProjects() {
includeConsoleProject(":mirai-console.integration-test", "backend/integration-test") includeConsoleProject(":mirai-console.integration-test", "backend/integration-test")
val consoleIntegrationTestSubPluginBuildGradleKtsTemplate by lazy { val consoleIntegrationTestSubPluginBuildGradleKtsTemplate by lazy {
@ -77,44 +127,10 @@ fun includeConsoleITPlugin(prefix: String, path: File) {
.filter { it.resolve(".nested-module.txt").exists() } .filter { it.resolve(".nested-module.txt").exists() }
.forEach { includeConsoleITPlugin("${projectPath}:", it) } .forEach { includeConsoleITPlugin("${projectPath}:", it) }
} }
rootProject.projectDir rootProject.projectDir
.resolve("mirai-console/backend/integration-test/testers") .resolve("mirai-console/backend/integration-test/testers")
.listFiles()?.asSequence().orEmpty() .listFiles()?.asSequence().orEmpty()
.filter { it.isDirectory } .filter { it.isDirectory }
.forEach { includeConsoleITPlugin(":mirai-console.integration-test:", it) } .forEach { includeConsoleITPlugin(":mirai-console.integration-test:", it) }
// endregion
includeConsoleProject(":mirai-console-compiler-common", "tools/compiler-common")
includeConsoleProject(":mirai-console-intellij", "tools/intellij-plugin")
includeConsoleProject(":mirai-console-gradle", "tools/gradle-plugin")
@Suppress("ConstantConditionIf")
if (!disableOldFrontEnds) {
includeConsoleProject(":mirai-console-terminal", "frontend/mirai-console-terminal")
println("JDK version: ${JavaVersion.current()}")
if (JavaVersion.current() >= JavaVersion.VERSION_1_9) {
includeConsoleProject(":mirai-console-graphical", "frontend/mirai-console-graphical")
} else {
println("当前使用的 JDK 版本为 ${System.getProperty("java.version")}, 请使用 JDK 9 以上版本引入模块 `:mirai-console-graphical`\n")
}
}
includeProject(":ci-release-helper")
val result = mutableListOf<ProjectDescriptor>()
for (project in allProjects) {
val validationDir = project.projectDir.resolve("compatibility-validation")
if (!validationDir.exists()) continue
validationDir.listFiles().orEmpty<File>().forEach { dir ->
if (dir.resolve("build.gradle.kts").isFile) {
val path = ":validator" + project.path + ":${dir.name}"
include(path)
project(path).projectDir = dir
// project(path).name = "${project.name}-validator-${dir.name}"
result.add(project(path))
}
}
} }