mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-23 22:30:47 +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`
|
### `publishPlugin`
|
||||||
|
|
||||||
配置好 Bintray 参数,使用 `./gradlew publishPlugin` 可自动发布并上传插件到 Bintray。
|
配置好 Bintray 参数,使用 `./gradlew publishPlugin` 可自动发布并上传插件到 Bintray。
|
||||||
|
@ -7,9 +7,13 @@
|
|||||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("DuplicatedCode")
|
||||||
|
|
||||||
package net.mamoe.mirai.console.gradle
|
package net.mamoe.mirai.console.gradle
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import java.io.File
|
||||||
import java.util.zip.ZipFile
|
import java.util.zip.ZipFile
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
import kotlin.test.assertNotNull
|
import kotlin.test.assertNotNull
|
||||||
@ -17,6 +21,148 @@ import kotlin.test.assertTrue
|
|||||||
|
|
||||||
class TestBuildPlugin : AbstractTest() {
|
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
|
@Test
|
||||||
fun `can build plugin`() {
|
fun `can build plugin`() {
|
||||||
tempDir.resolve("build.gradle").appendText(
|
tempDir.resolve("build.gradle").appendText(
|
||||||
@ -32,7 +178,13 @@ class TestBuildPlugin : AbstractTest() {
|
|||||||
gradleRunner()
|
gradleRunner()
|
||||||
.withArguments("buildPlugin", "dependencies", "--stacktrace", "--info")
|
.withArguments("buildPlugin", "dependencies", "--stacktrace", "--info")
|
||||||
.build()
|
.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 ->
|
ZipFile(jar).use { zipFile ->
|
||||||
|
|
||||||
assertNotNull(zipFile.getEntry("org/slf4j/impl/SimpleLogger.class"))
|
assertNotNull(zipFile.getEntry("org/slf4j/impl/SimpleLogger.class"))
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
package net.mamoe.mirai.console.gradle
|
package net.mamoe.mirai.console.gradle
|
||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.artifacts.ExternalModuleDependency
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.artifacts.ResolvedArtifact
|
import org.gradle.api.artifacts.*
|
||||||
import org.gradle.api.artifacts.ResolvedDependency
|
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
||||||
import org.gradle.api.attributes.AttributeContainer
|
import org.gradle.api.attributes.AttributeContainer
|
||||||
import org.gradle.api.capabilities.Capability
|
import org.gradle.api.capabilities.Capability
|
||||||
import org.gradle.api.file.DuplicatesStrategy
|
import org.gradle.api.file.DuplicatesStrategy
|
||||||
@ -58,6 +58,8 @@ public open class BuildMiraiPluginV2 : Jar() {
|
|||||||
"net.mamoe:mirai-console-terminal",
|
"net.mamoe:mirai-console-terminal",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("LocalVariableName")
|
||||||
@TaskAction
|
@TaskAction
|
||||||
internal fun run() {
|
internal fun run() {
|
||||||
val runtime = mutableSetOf<String>()
|
val runtime = mutableSetOf<String>()
|
||||||
@ -66,6 +68,8 @@ public open class BuildMiraiPluginV2 : Jar() {
|
|||||||
val linkToApi = mutableSetOf<String>()
|
val linkToApi = mutableSetOf<String>()
|
||||||
val shadowedFiles = mutableSetOf<File>()
|
val shadowedFiles = mutableSetOf<File>()
|
||||||
val shadowedDependencies = mutableSetOf<String>()
|
val shadowedDependencies = mutableSetOf<String>()
|
||||||
|
val subprojects = mutableSetOf<String>()
|
||||||
|
val subprojects_fullpath = mutableSetOf<String>()
|
||||||
|
|
||||||
project.configurations.findByName(MiraiConsoleGradlePlugin.MIRAI_SHADOW_CONF_NAME)?.allDependencies?.forEach { dep ->
|
project.configurations.findByName(MiraiConsoleGradlePlugin.MIRAI_SHADOW_CONF_NAME)?.allDependencies?.forEach { dep ->
|
||||||
if (dep is ExternalModuleDependency) {
|
if (dep is ExternalModuleDependency) {
|
||||||
@ -73,18 +77,52 @@ public open class BuildMiraiPluginV2 : Jar() {
|
|||||||
shadowedDependencies.add(artId)
|
shadowedDependencies.add(artId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
project.configurations.findByName("apiElements")?.allDependencies?.forEach { dep ->
|
project.configurations.findByName(MiraiConsoleGradlePlugin.MIRAI_AS_NORMAL_DEP_CONF_NAME)?.allDependencies?.forEach { dep ->
|
||||||
if (dep is ExternalModuleDependency) {
|
if (dep is ProjectDependency) {
|
||||||
val artId = "${dep.group}:${dep.name}"
|
|
||||||
linkedDependencies.add(artId)
|
|
||||||
linkToApi.add(artId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
project.configurations.findByName("implementation")?.allDependencies?.forEach { dep ->
|
|
||||||
if (dep is ExternalModuleDependency) {
|
|
||||||
linkedDependencies.add("${dep.group}:${dep.name}")
|
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)
|
linkedDependencies.removeAll(shadowedDependencies)
|
||||||
linkToApi.removeAll(shadowedDependencies)
|
linkToApi.removeAll(shadowedDependencies)
|
||||||
linkedDependencies.addAll(miraiDependencies)
|
linkedDependencies.addAll(miraiDependencies)
|
||||||
@ -105,6 +143,7 @@ public open class BuildMiraiPluginV2 : Jar() {
|
|||||||
|
|
||||||
fun resolveDependency(resolvedDependency: ResolvedDependency) {
|
fun resolveDependency(resolvedDependency: ResolvedDependency) {
|
||||||
val depId = resolvedDependency.depId()
|
val depId = resolvedDependency.depId()
|
||||||
|
logger.info { "resolving : $depId" }
|
||||||
if (depId in linkedDependencies) {
|
if (depId in linkedDependencies) {
|
||||||
markAsResolved(resolvedDependency)
|
markAsResolved(resolvedDependency)
|
||||||
linkDependencyTo(resolvedDependency, runtime)
|
linkDependencyTo(resolvedDependency, runtime)
|
||||||
@ -113,6 +152,10 @@ public open class BuildMiraiPluginV2 : Jar() {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (depId in subprojects) {
|
||||||
|
resolvedDependency.children.forEach { resolveDependency(it) }
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
runtimeClasspath.firstLevelModuleDependencies.forEach { resolveDependency(it) }
|
runtimeClasspath.firstLevelModuleDependencies.forEach { resolveDependency(it) }
|
||||||
|
|
||||||
@ -120,6 +163,7 @@ public open class BuildMiraiPluginV2 : Jar() {
|
|||||||
logger.info { "linkToAPi : $linkToApi" }
|
logger.info { "linkToAPi : $linkToApi" }
|
||||||
logger.info { "api : $api" }
|
logger.info { "api : $api" }
|
||||||
logger.info { "runtime : $runtime" }
|
logger.info { "runtime : $runtime" }
|
||||||
|
logger.info { "subprojects : $subprojects" }
|
||||||
|
|
||||||
val lenientConfiguration = runtimeClasspath.lenientConfiguration
|
val lenientConfiguration = runtimeClasspath.lenientConfiguration
|
||||||
if (lenientConfiguration is DefaultLenientConfiguration) {
|
if (lenientConfiguration is DefaultLenientConfiguration) {
|
||||||
@ -152,6 +196,12 @@ public open class BuildMiraiPluginV2 : Jar() {
|
|||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val cid = artId.componentIdentifier
|
||||||
|
if (cid is ProjectComponentIdentifier) {
|
||||||
|
if (cid.projectPath in subprojects_fullpath) {
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
}
|
||||||
logger.info { " `- $artId - ${artId.javaClass}" }
|
logger.info { " `- $artId - ${artId.javaClass}" }
|
||||||
shadowedFiles.add(artifact.file)
|
shadowedFiles.add(artifact.file)
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
|||||||
public class MiraiConsoleGradlePlugin : Plugin<Project> {
|
public class MiraiConsoleGradlePlugin : Plugin<Project> {
|
||||||
internal companion object {
|
internal companion object {
|
||||||
const val MIRAI_SHADOW_CONF_NAME: String = "shadowLink"
|
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) {
|
private fun KotlinSourceSet.configureSourceSet(project: Project, target: KotlinTarget) {
|
||||||
@ -167,6 +168,7 @@ public class MiraiConsoleGradlePlugin : Plugin<Project> {
|
|||||||
|
|
||||||
private fun Project.setupConfigurations() {
|
private fun Project.setupConfigurations() {
|
||||||
configurations.create(MIRAI_SHADOW_CONF_NAME).isCanBeResolved = false
|
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) {
|
override fun apply(target: Project): Unit = with(target) {
|
||||||
|
Loading…
Reference in New Issue
Block a user