Skip to content

Commit

Permalink
Update gradle system
Browse files Browse the repository at this point in the history
  • Loading branch information
Karlatemp committed Jan 21, 2022
1 parent c9e137b commit fc3750e
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 82 deletions.
10 changes: 6 additions & 4 deletions mirai-console/backend/mirai-console/src/plugin/PluginManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,20 @@ public interface PluginManager {
public val pluginsConfigFolder: File

/**
* 插件运行时依赖存放路径 [Path]
* 插件运行时依赖存放路径 [Path], 插件自动下载的依赖都会存放于此目录
*
* **实现细节**: 在 terminal 前端实现为 `$rootPath/plugin-libraries`
* **实现细节**: 在 terminal 前端实现为 `$rootPath/plugin-libraries`,
* 依赖 jar 文件由插件共享, 但是运行时插件加载的类是互相隔离的
*
* @since 2.11
*/
public val pluginLibrariesPath: Path

/**
* 插件运行时依赖存放路径 [File]
* 插件运行时依赖存放路径 [File], 插件自动下载的依赖都会存放于此目录
*
* **实现细节**: 在 terminal 前端实现为 `$rootPath/plugin-libraries`
* **实现细节**: 在 terminal 前端实现为 `$rootPath/plugin-libraries`,
* 依赖 jar 文件由插件共享, 但是运行时插件加载的类是互相隔离的
*
* @since 2.11
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ package net.mamoe.mirai.console.gradle
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.internal.PluginUnderTestMetadataReading
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

Expand Down Expand Up @@ -91,4 +93,16 @@ abstract class AbstractTest {
// """

}

@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())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
package net.mamoe.mirai.console.gradle

import org.junit.jupiter.api.Test
import java.io.File
import java.util.zip.ZipFile
import kotlin.test.assertFalse
import kotlin.test.assertTrue
Expand All @@ -27,7 +28,7 @@ class TestBuildPlugin : AbstractTest() {
""".trimIndent()
)
gradleRunner()
.withArguments("buildPlugin", "--stacktrace")
.withArguments("buildPlugin", "dependencies", "--stacktrace", "--info")
.build()
val jar = tempDir.resolve("build/libs").listFiles()!!.first { it.name.endsWith(".mirai.jar") }
ZipFile(jar).use { zipFile ->
Expand All @@ -44,6 +45,10 @@ class TestBuildPlugin : AbstractTest() {
assertTrue { dpPrivate.contains("com.zaxxer:SparseBitSet:1.2") }
assertTrue { dpPrivate.contains("com.google.code.gson:gson:2.8.9") }
}

jar.copyTo(File("G:\\IDEAProjects\\mirai\\mirai-console\\tools\\gradle-plugin\\build\\ax").also {
it.mkdirs()
}.resolve(jar.name))
}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/*
* 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.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.attributes.AttributeContainer
import org.gradle.api.capabilities.Capability
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactVisitor
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvableArtifact
import org.gradle.api.internal.file.FileCollectionInternal
import org.gradle.api.internal.file.FileCollectionStructureVisitor
import org.gradle.api.tasks.TaskAction
import org.gradle.internal.DisplayName
import org.gradle.internal.component.external.model.ModuleComponentArtifactIdentifier
import org.gradle.jvm.tasks.Jar
import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.get
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import java.io.File
import javax.inject.Inject

public open class BuildMiraiPluginV2 : Jar() {

// @get:Internal
private lateinit var metadataTask: GenMetadataTask

public open class GenMetadataTask
@Inject internal constructor(
@JvmField internal val orgTask: BuildMiraiPluginV2,
) : DefaultTask() {
@TaskAction
internal fun run() {
val runtime = mutableSetOf<String>()
val api = mutableSetOf<String>()
val linkedDependencies = mutableSetOf(
"net.mamoe:mirai-core-api",
"net.mamoe:mirai-core-api-jvm",
"net.mamoe:mirai-core-api-android",
"net.mamoe:mirai-core",
"net.mamoe:mirai-core-jvm",
"net.mamoe:mirai-core-android",
"net.mamoe:mirai-core-utils",
"net.mamoe:mirai-core-utils-jvm",
"net.mamoe:mirai-core-utils-android",
"net.mamoe:mirai-console",
"net.mamoe:mirai-console-terminal",
)
val linkToApi = mutableSetOf<String>()
val shadowedFiles = mutableSetOf<File>()

// TODO: check dependencies
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) {
linkedDependencies.add("${dep.group}:${dep.name}")
}
}

fun ResolvedDependency.depId(): String = "$moduleGroup:$moduleName"

val runtimeClasspath = project.configurations["runtimeClasspath"].resolvedConfiguration
fun markAsResolved(resolvedDependency: ResolvedDependency) {
val depId = resolvedDependency.depId()
linkedDependencies.add(depId)
resolvedDependency.children.forEach { markAsResolved(it) }
}

fun linkDependencyTo(resolvedDependency: ResolvedDependency, dependencies: MutableCollection<String>) {
dependencies.add(resolvedDependency.module.toString())
resolvedDependency.children.forEach { linkDependencyTo(it, dependencies) }
}

fun resolveDependency(resolvedDependency: ResolvedDependency) {
val depId = resolvedDependency.depId()
if (depId in linkedDependencies) {
markAsResolved(resolvedDependency)
linkDependencyTo(resolvedDependency, runtime)
if (depId in linkToApi) {
linkDependencyTo(resolvedDependency, api)
}
return
}
}
runtimeClasspath.firstLevelModuleDependencies.forEach { resolveDependency(it) }

logger.info { "linkedDependencies: $linkedDependencies" }
logger.info { "linkToAPi : $linkToApi" }
logger.info { "api : $api" }
logger.info { "runtime : $runtime" }

val lenientConfiguration = runtimeClasspath.lenientConfiguration
if (lenientConfiguration is DefaultLenientConfiguration) {
val resolvedArtifacts = mutableSetOf<ResolvedArtifact>()
lenientConfiguration.select().visitArtifacts(object : ArtifactVisitor {
override fun prepareForVisit(source: FileCollectionInternal.Source): FileCollectionStructureVisitor.VisitType {
return FileCollectionStructureVisitor.VisitType.Visit
}

override fun visitArtifact(
variantName: DisplayName,
variantAttributes: AttributeContainer,
capabilities: MutableList<out Capability>,
artifact: ResolvableArtifact
) {
resolvedArtifacts.add(artifact.toPublicView())
}

override fun requireArtifactFiles(): Boolean = false
override fun visitFailure(failure: Throwable) {}
}, false)
resolvedArtifacts
} else {
runtimeClasspath.resolvedArtifacts
}.forEach { artifact ->
val artId = artifact.id
if (artId is ModuleComponentArtifactIdentifier) {
val cid = artId.componentIdentifier
if ("${cid.group}:${cid.module}" in linkedDependencies) {
return@forEach
}
}
logger.info { " `- $artId - ${artId.javaClass}" }
shadowedFiles.add(artifact.file)
}

shadowedFiles.forEach { file ->
if (file.isDirectory) {
orgTask.from(file)
} else if (file.extension == "jar") {
orgTask.from(project.zipTree(file))
} else {
orgTask.from(file)
}
}

temporaryDir.also {
it.mkdirs()
}.let { tmpDir ->
tmpDir.resolve("api.txt").writeText(api.sorted().joinToString("\n"))
tmpDir.resolve("runtime.txt").writeText(runtime.sorted().joinToString("\n"))
orgTask.from(tmpDir.resolve("api.txt")) { copy ->
copy.into("META-INF/mirai-console-plugin")
copy.rename { "dependencies-shared.txt" }
}
orgTask.from(tmpDir.resolve("runtime.txt")) { copy ->
copy.into("META-INF/mirai-console-plugin")
copy.rename { "dependencies-private.txt" }
}
}
}
}

@Suppress("RedundantLambdaArrow", "RemoveExplicitTypeArguments")
internal fun init(target: KotlinTarget) {
metadataTask = project.tasks.create<GenMetadataTask>(name + "GenMetadata", this)
dependsOn(metadataTask)
archiveExtension.set("mirai.jar")
duplicatesStrategy = DuplicatesStrategy.WARN

val compilations = target.compilations.filter { it.name == KotlinCompilation.MAIN_COMPILATION_NAME }
compilations.forEach {
dependsOn(it.compileKotlinTask)
from(it.output.allOutputs)
metadataTask.dependsOn(it.compileKotlinTask)
}
exclude { elm ->
elm.path.startsWith("META-INF/") && elm.name.endsWith(".sf", ignoreCase = true)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ public class MiraiConsoleGradlePlugin : Plugin<Project> {
fun registerBuildPluginTask(target: KotlinTarget, isSingleTarget: Boolean) {
tasks.create(
"buildPlugin".wrapNameWithPlatform(target, isSingleTarget),
BuildMiraiPluginNew::class.java
).init()
BuildMiraiPluginV2::class.java
).init(target)
tasks.create(
"buildPluginLegacy".wrapNameWithPlatform(target, isSingleTarget),
BuildMiraiPluginTask::class.java,
Expand Down Expand Up @@ -157,6 +157,10 @@ public class MiraiConsoleGradlePlugin : Plugin<Project> {
}
}

private fun Project.setupConfigurations() {
// TODO
}

override fun apply(target: Project): Unit = with(target) {
extensions.create("mirai", MiraiConsoleExtension::class.java)

Expand All @@ -166,6 +170,8 @@ public class MiraiConsoleGradlePlugin : Plugin<Project> {
plugins.apply(ShadowPlugin::class.java)
plugins.apply(BintrayPlugin::class.java)

project.setupConfigurations()

afterEvaluate {
configureCompileTarget()
kotlinTargets.forEach { configureTarget(it) }
Expand Down
16 changes: 16 additions & 0 deletions mirai-console/tools/gradle-plugin/src/main/kotlin/dsl.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* 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.console.gradle

import org.gradle.api.logging.Logger

internal inline fun Logger.info(msg: () -> String) {
if (isInfoEnabled) info(msg())
}

0 comments on commit fc3750e

Please sign in to comment.