mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-07 16:40:43 +08:00
Fix gradle multi-projects packaging error; fix #1973
This commit is contained in:
parent
fbadf4a256
commit
7f3b67ad9e
@ -70,6 +70,20 @@ dependencies {
|
||||
}
|
||||
```
|
||||
|
||||
特别的, 如果使用了子项目 (Gradle MultiProjects), Mirai Console Gradle 默认也会打包进 JAR.
|
||||
|
||||
如果您希望 Mirai Console Gradle 像处理一般依赖一样处理 Gradle 子项目, 请使用以下配置告知
|
||||
|
||||
```groovy
|
||||
dependencies {
|
||||
implementation project(":nested")
|
||||
|
||||
asNormalDep project(":nested")
|
||||
// build.gradle.kts
|
||||
"asNormalDep"(project(":nested"))
|
||||
}
|
||||
```
|
||||
|
||||
### `publishPlugin`
|
||||
|
||||
配置好 Bintray 参数,使用 `./gradlew publishPlugin` 可自动发布并上传插件到 Bintray。
|
||||
|
@ -7,9 +7,13 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("DuplicatedCode")
|
||||
|
||||
package net.mamoe.mirai.console.gradle
|
||||
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.io.File
|
||||
import java.util.zip.ZipFile
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNotNull
|
||||
@ -17,6 +21,148 @@ import kotlin.test.assertTrue
|
||||
|
||||
class TestBuildPlugin : AbstractTest() {
|
||||
|
||||
@Test
|
||||
@DisplayName("project as normal dependency")
|
||||
fun buildWithMultiProjectsAsNormalDependency() {
|
||||
settingsFile.appendText(
|
||||
"""
|
||||
include("nested")
|
||||
""".trimIndent()
|
||||
)
|
||||
tempDir.resolve("nested").also { it.mkdirs() }.resolve("build.gradle").writeText(
|
||||
"""
|
||||
plugins {
|
||||
id("org.jetbrains.kotlin.jvm")
|
||||
id("net.mamoe.mirai-console")
|
||||
}
|
||||
dependencies {
|
||||
api "com.zaxxer:SparseBitSet:1.2"
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
tempDir.resolve("build.gradle").appendText(
|
||||
"""
|
||||
dependencies {
|
||||
implementation project(":nested")
|
||||
asNormalDep project(":nested")
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
gradleRunner()
|
||||
.withArguments(":buildPlugin", "--stacktrace", "--info")
|
||||
.build()
|
||||
|
||||
|
||||
ZipFile(findJar()).use { zipFile ->
|
||||
|
||||
val dpPrivate = zipFile.getInputStream(
|
||||
zipFile.getEntry("META-INF/mirai-console-plugin/dependencies-private.txt")
|
||||
).use { it.readBytes().decodeToString() }
|
||||
val dpShared = zipFile.getInputStream(
|
||||
zipFile.getEntry("META-INF/mirai-console-plugin/dependencies-shared.txt")
|
||||
).use { it.readBytes().decodeToString() }
|
||||
|
||||
assertFalse { dpShared.contains("com.zaxxer:SparseBitSet:1.2") }
|
||||
assertTrue { dpPrivate.contains("com.zaxxer:SparseBitSet:1.2") }
|
||||
assertTrue { dpPrivate.contains(":nested") }
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("no api extends if using implementation")
|
||||
fun buildWithMultiProjectsWithoutApi() {
|
||||
settingsFile.appendText(
|
||||
"""
|
||||
include("nested")
|
||||
""".trimIndent()
|
||||
)
|
||||
tempDir.resolve("nested").also { it.mkdirs() }.resolve("build.gradle").writeText(
|
||||
"""
|
||||
plugins {
|
||||
id("org.jetbrains.kotlin.jvm")
|
||||
id("net.mamoe.mirai-console")
|
||||
}
|
||||
dependencies {
|
||||
api "com.zaxxer:SparseBitSet:1.2"
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
tempDir.resolve("build.gradle").appendText(
|
||||
"""
|
||||
dependencies {
|
||||
implementation project(":nested")
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
gradleRunner()
|
||||
.withArguments(":buildPlugin", "--stacktrace", "--info")
|
||||
.build()
|
||||
|
||||
|
||||
ZipFile(findJar()).use { zipFile ->
|
||||
|
||||
val dpPrivate = zipFile.getInputStream(
|
||||
zipFile.getEntry("META-INF/mirai-console-plugin/dependencies-private.txt")
|
||||
).use { it.readBytes().decodeToString() }
|
||||
val dpShared = zipFile.getInputStream(
|
||||
zipFile.getEntry("META-INF/mirai-console-plugin/dependencies-shared.txt")
|
||||
).use { it.readBytes().decodeToString() }
|
||||
|
||||
assertFalse { dpShared.contains("com.zaxxer:SparseBitSet:1.2") }
|
||||
assertTrue { dpPrivate.contains("com.zaxxer:SparseBitSet:1.2") }
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("build with multi projects")
|
||||
fun buildWithMultiProjects() {
|
||||
settingsFile.appendText(
|
||||
"""
|
||||
include("nested")
|
||||
""".trimIndent()
|
||||
)
|
||||
tempDir.resolve("nested").also { it.mkdirs() }.resolve("build.gradle").writeText(
|
||||
"""
|
||||
plugins {
|
||||
id("org.jetbrains.kotlin.jvm")
|
||||
id("net.mamoe.mirai-console")
|
||||
}
|
||||
dependencies {
|
||||
api "com.zaxxer:SparseBitSet:1.2"
|
||||
implementation "com.google.code.gson:gson:2.8.9"
|
||||
api "org.slf4j:slf4j-simple:1.7.32"
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
tempDir.resolve("build.gradle").appendText(
|
||||
"""
|
||||
dependencies {
|
||||
api project(":nested")
|
||||
shadowLink "org.slf4j:slf4j-simple"
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
gradleRunner()
|
||||
.withArguments(":buildPlugin", "dependencies", "--stacktrace", "--info")
|
||||
.build()
|
||||
checkOutput()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can build plugin`() {
|
||||
tempDir.resolve("build.gradle").appendText(
|
||||
@ -32,7 +178,13 @@ class TestBuildPlugin : AbstractTest() {
|
||||
gradleRunner()
|
||||
.withArguments("buildPlugin", "dependencies", "--stacktrace", "--info")
|
||||
.build()
|
||||
val jar = tempDir.resolve("build/libs").listFiles()!!.first { it.name.endsWith(".mirai.jar") }
|
||||
checkOutput()
|
||||
}
|
||||
|
||||
private fun findJar(): File = tempDir.resolve("build/libs").listFiles()!!.first { it.name.endsWith(".mirai.jar") }
|
||||
|
||||
private fun checkOutput() {
|
||||
val jar = findJar()
|
||||
ZipFile(jar).use { zipFile ->
|
||||
|
||||
assertNotNull(zipFile.getEntry("org/slf4j/impl/SimpleLogger.class"))
|
||||
|
@ -10,9 +10,9 @@
|
||||
package net.mamoe.mirai.console.gradle
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.artifacts.ExternalModuleDependency
|
||||
import org.gradle.api.artifacts.ResolvedArtifact
|
||||
import org.gradle.api.artifacts.ResolvedDependency
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.*
|
||||
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import org.gradle.api.capabilities.Capability
|
||||
import org.gradle.api.file.DuplicatesStrategy
|
||||
@ -58,6 +58,8 @@ public open class BuildMiraiPluginV2 : Jar() {
|
||||
"net.mamoe:mirai-console-terminal",
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("LocalVariableName")
|
||||
@TaskAction
|
||||
internal fun run() {
|
||||
val runtime = mutableSetOf<String>()
|
||||
@ -66,6 +68,8 @@ public open class BuildMiraiPluginV2 : Jar() {
|
||||
val linkToApi = mutableSetOf<String>()
|
||||
val shadowedFiles = mutableSetOf<File>()
|
||||
val shadowedDependencies = mutableSetOf<String>()
|
||||
val subprojects = mutableSetOf<String>()
|
||||
val subprojects_fullpath = mutableSetOf<String>()
|
||||
|
||||
project.configurations.findByName(MiraiConsoleGradlePlugin.MIRAI_SHADOW_CONF_NAME)?.allDependencies?.forEach { dep ->
|
||||
if (dep is ExternalModuleDependency) {
|
||||
@ -73,18 +77,52 @@ public open class BuildMiraiPluginV2 : Jar() {
|
||||
shadowedDependencies.add(artId)
|
||||
}
|
||||
}
|
||||
project.configurations.findByName("apiElements")?.allDependencies?.forEach { dep ->
|
||||
if (dep is ExternalModuleDependency) {
|
||||
val artId = "${dep.group}:${dep.name}"
|
||||
linkedDependencies.add(artId)
|
||||
linkToApi.add(artId)
|
||||
}
|
||||
}
|
||||
project.configurations.findByName("implementation")?.allDependencies?.forEach { dep ->
|
||||
if (dep is ExternalModuleDependency) {
|
||||
project.configurations.findByName(MiraiConsoleGradlePlugin.MIRAI_AS_NORMAL_DEP_CONF_NAME)?.allDependencies?.forEach { dep ->
|
||||
if (dep is ProjectDependency) {
|
||||
linkedDependencies.add("${dep.group}:${dep.name}")
|
||||
}
|
||||
}
|
||||
|
||||
fun deepForeachDependencies(conf: Configuration?, action: (Dependency) -> Unit) {
|
||||
(conf ?: return).allDependencies.forEach { dep ->
|
||||
action(dep)
|
||||
if (dep is ProjectDependency) {
|
||||
subprojects.add("${dep.group}:${dep.name}")
|
||||
deepForeachDependencies(dep.dependencyProject.configurations.findByName(conf.name), action)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun resolveProject(project: Project, doResolveApi: Boolean) {
|
||||
deepForeachDependencies(project.configurations.findByName("apiElements")) { dep ->
|
||||
if (dep is ExternalModuleDependency) {
|
||||
val artId = "${dep.group}:${dep.name}"
|
||||
linkedDependencies.add(artId)
|
||||
if (doResolveApi) {
|
||||
linkToApi.add(artId)
|
||||
}
|
||||
}
|
||||
if (dep is ProjectDependency) {
|
||||
subprojects_fullpath.add(dep.dependencyProject.path)
|
||||
subprojects.add("${dep.group}:${dep.name}")
|
||||
resolveProject(dep.dependencyProject, doResolveApi)
|
||||
}
|
||||
}
|
||||
|
||||
project.configurations.findByName("implementation")?.allDependencies?.forEach { dep ->
|
||||
if (dep is ExternalModuleDependency) {
|
||||
linkedDependencies.add("${dep.group}:${dep.name}")
|
||||
}
|
||||
if (dep is ProjectDependency) {
|
||||
subprojects_fullpath.add(dep.dependencyProject.path)
|
||||
subprojects.add("${dep.group}:${dep.name}")
|
||||
resolveProject(dep.dependencyProject, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resolveProject(project, true)
|
||||
linkedDependencies.removeAll(shadowedDependencies)
|
||||
linkToApi.removeAll(shadowedDependencies)
|
||||
linkedDependencies.addAll(miraiDependencies)
|
||||
@ -105,6 +143,7 @@ public open class BuildMiraiPluginV2 : Jar() {
|
||||
|
||||
fun resolveDependency(resolvedDependency: ResolvedDependency) {
|
||||
val depId = resolvedDependency.depId()
|
||||
logger.info { "resolving : $depId" }
|
||||
if (depId in linkedDependencies) {
|
||||
markAsResolved(resolvedDependency)
|
||||
linkDependencyTo(resolvedDependency, runtime)
|
||||
@ -113,6 +152,10 @@ public open class BuildMiraiPluginV2 : Jar() {
|
||||
}
|
||||
return
|
||||
}
|
||||
if (depId in subprojects) {
|
||||
resolvedDependency.children.forEach { resolveDependency(it) }
|
||||
return
|
||||
}
|
||||
}
|
||||
runtimeClasspath.firstLevelModuleDependencies.forEach { resolveDependency(it) }
|
||||
|
||||
@ -120,6 +163,7 @@ public open class BuildMiraiPluginV2 : Jar() {
|
||||
logger.info { "linkToAPi : $linkToApi" }
|
||||
logger.info { "api : $api" }
|
||||
logger.info { "runtime : $runtime" }
|
||||
logger.info { "subprojects : $subprojects" }
|
||||
|
||||
val lenientConfiguration = runtimeClasspath.lenientConfiguration
|
||||
if (lenientConfiguration is DefaultLenientConfiguration) {
|
||||
@ -152,6 +196,12 @@ public open class BuildMiraiPluginV2 : Jar() {
|
||||
return@forEach
|
||||
}
|
||||
}
|
||||
val cid = artId.componentIdentifier
|
||||
if (cid is ProjectComponentIdentifier) {
|
||||
if (cid.projectPath in subprojects_fullpath) {
|
||||
return@forEach
|
||||
}
|
||||
}
|
||||
logger.info { " `- $artId - ${artId.javaClass}" }
|
||||
shadowedFiles.add(artifact.file)
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
public class MiraiConsoleGradlePlugin : Plugin<Project> {
|
||||
internal companion object {
|
||||
const val MIRAI_SHADOW_CONF_NAME: String = "shadowLink"
|
||||
const val MIRAI_AS_NORMAL_DEP_CONF_NAME: String = "asNormalDep"
|
||||
}
|
||||
|
||||
private fun KotlinSourceSet.configureSourceSet(project: Project, target: KotlinTarget) {
|
||||
@ -167,6 +168,7 @@ public class MiraiConsoleGradlePlugin : Plugin<Project> {
|
||||
|
||||
private fun Project.setupConfigurations() {
|
||||
configurations.create(MIRAI_SHADOW_CONF_NAME).isCanBeResolved = false
|
||||
configurations.create(MIRAI_AS_NORMAL_DEP_CONF_NAME).isCanBeResolved = false
|
||||
}
|
||||
|
||||
override fun apply(target: Project): Unit = with(target) {
|
||||
|
Loading…
Reference in New Issue
Block a user