Gradle plugin

This commit is contained in:
Him188 2020-09-19 20:33:34 +08:00
parent 55fc85cb4d
commit ad3124fe10
7 changed files with 533 additions and 48 deletions

View File

@ -1,9 +1,12 @@
@file:Suppress("UnstableApiUsage") @file:Suppress("UnstableApiUsage")
plugins { plugins {
id("com.jfrog.bintray") version Versions.bintray apply false
id("net.mamoe.kotlin-jvm-blocking-bridge") version Versions.blockingBridge apply false
kotlin("jvm") version Versions.kotlinCompiler kotlin("jvm") version Versions.kotlinCompiler
kotlin("plugin.serialization") version Versions.kotlinCompiler kotlin("plugin.serialization") version Versions.kotlinCompiler
id("com.jfrog.bintray") version Versions.bintray apply false
id("net.mamoe.kotlin-jvm-blocking-bridge") version Versions.blockingBridge apply false
id("com.gradle.plugin-publish") version "0.12.0" apply false
//id("com.bmuschko.nexus") version "2.3.1" apply false
//id("io.codearte.nexus-staging") version "0.11.0" apply false
} }
tasks.withType(JavaCompile::class.java) { tasks.withType(JavaCompile::class.java) {

View File

@ -9,7 +9,7 @@
object Versions { object Versions {
const val core = "1.3.0" const val core = "1.3.0"
const val console = "1.0-RC-dev-5" const val console = "1.0-RC-dev-28"
const val consoleGraphical = "0.0.7" const val consoleGraphical = "0.0.7"
const val consoleTerminal = console const val consoleTerminal = console

View File

@ -2,14 +2,112 @@
plugins { plugins {
kotlin("jvm") kotlin("jvm")
kotlin("kapt")
id("java-gradle-plugin")
id("com.gradle.plugin-publish")
id("java") id("java")
//signing
`maven-publish` `maven-publish`
id("com.jfrog.bintray") id("com.jfrog.bintray")
id("com.github.johnrengelman.shadow")
}
dependencies {
compileOnly(gradleApi())
compileOnly(kotlin("gradle-plugin-api").toString()) {
exclude("org.jetbrains.kotlin", "kotlin-stdlib")
}
compileOnly(kotlin("gradle-plugin").toString()) {
exclude("org.jetbrains.kotlin", "kotlin-stdlib")
}
compileOnly(kotlin("stdlib"))
api("com.github.jengelman.gradle.plugins:shadow:6.0.0")
api("org.jetbrains:annotations:19.0.0")
}
dependencies {
testApi(kotlin("test"))
testApi(kotlin("test-junit5"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.2.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.2.0")
} }
version = Versions.console version = Versions.console
description = "Gradle plugin for Mirai Console" description = "Gradle plugin for Mirai Console"
pluginBundle {
website = "https://github.com/mamoe/mirai-console"
vcsUrl = "https://github.com/mamoe/mirai-console"
tags = listOf("framework", "kotlin", "mirai")
}
gradlePlugin {
plugins {
create("miraiConsole") {
id = "net.mamoe.mirai-console"
displayName = "Mirai Console"
description = project.description
implementationClass = "net.mamoe.mirai.console.gradle.MiraiConsoleGradlePlugin"
}
}
}
kotlin {
sourceSets.all {
target.compilations.all {
kotlinOptions {
apiVersion = "1.3"
languageVersion = "1.3"
jvmTarget = "1.8"
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
}
}
languageSettings.apply {
progressiveMode = true
useExperimentalAnnotation("kotlin.RequiresOptIn")
useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
useExperimentalAnnotation("kotlin.experimental.ExperimentalTypeInference")
useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
}
}
}
tasks {
"test"(Test::class) {
useJUnitPlatform()
}
val compileKotlin by getting {}
@Suppress("UNUSED_VARIABLE")
val fillBuildConstants by registering {
group = "mirai"
doLast {
(compileKotlin as org.jetbrains.kotlin.gradle.tasks.KotlinCompile).source.filter { it.name == "VersionConstants.kt" }.single()
.let { file ->
file.writeText(
file.readText()
.replace(
Regex("""const val CONSOLE_VERSION = ".*"""")
) {
"""const val CONSOLE_VERSION = "${Versions.console}""""
}
.replace(
Regex("""const val CORE_VERSION = ".*"""")
) { """const val CORE_VERSION = "${Versions.core}"""" }
)
}
}
}
compileKotlin.dependsOn(fillBuildConstants)
}
java { java {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8
@ -19,49 +117,4 @@ tasks.withType(JavaCompile::class.java) {
options.encoding = "UTF8" options.encoding = "UTF8"
} }
kotlin {
sourceSets.all {
target.compilations.all {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
//useIR = true
}
}
languageSettings.apply {
progressiveMode = true
useExperimentalAnnotation("kotlin.Experimental")
useExperimentalAnnotation("kotlin.RequiresOptIn")
useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiInternalAPI")
useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiExperimentalAPI")
useExperimentalAnnotation("net.mamoe.mirai.console.ConsoleFrontEndImplementation")
useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleExperimentalApi")
useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
useExperimentalAnnotation("kotlin.experimental.ExperimentalTypeInference")
useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
useExperimentalAnnotation("kotlinx.serialization.ExperimentalSerializationApi")
useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleInternalApi")
}
}
}
dependencies {
api("org.jetbrains:annotations:19.0.0")
api(kotlinx("coroutines-jdk8", Versions.coroutines))
testApi(kotlin("test"))
testApi(kotlin("test-junit5"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.2.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.2.0")
}
tasks {
"test"(Test::class) {
useJUnitPlatform()
}
}
// setupPublishing("mirai-console-gradle") // setupPublishing("mirai-console-gradle")

View File

@ -0,0 +1,132 @@
/*
* 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
*/
@file:JvmMultifileClass
@file:JvmName("MiraiConsoleGradlePluginKt")
package net.mamoe.mirai.console.gradle
internal val IGNORED_DEPENDENCIES_IN_SHADOW = arrayOf(
"org.jetbrains.kotlin:kotlin-stdlib",
"org.jetbrains.kotlin:kotlin-stdlib-common",
"org.jetbrains.kotlin:kotlin-stdlib-metadata",
"org.jetbrains.kotlin:kotlin-stdlib-jvm",
"org.jetbrains.kotlin:kotlin-stdlib-jdk7",
"org.jetbrains.kotlin:kotlin-stdlib-jdk8",
"org.jetbrains.kotlin:kotlin-reflect",
"org.jetbrains.kotlin:kotlin-reflect-common",
"org.jetbrains.kotlin:kotlin-reflect-metadata",
"org.jetbrains.kotlin:kotlin-reflect-jvm",
"org.jetbrains.kotlinx:kotlinx-serialization-core",
"org.jetbrains.kotlinx:kotlinx-serialization-core-common",
"org.jetbrains.kotlinx:kotlinx-serialization-core-metadata",
"org.jetbrains.kotlinx:kotlinx-serialization-core-jvm",
"org.jetbrains.kotlinx:kotlinx-serialization-runtime",
"org.jetbrains.kotlinx:kotlinx-serialization-runtime-common",
"org.jetbrains.kotlinx:kotlinx-serialization-runtime-metadata",
"org.jetbrains.kotlinx:kotlinx-serialization-runtime-jvm",
"org.jetbrains.kotlinx:kotlinx-serialization-protobuf",
"org.jetbrains.kotlinx:kotlinx-serialization-protobuf-common",
"org.jetbrains.kotlinx:kotlinx-serialization-protobuf-metadata",
"org.jetbrains.kotlinx:kotlinx-serialization-protobuf-jvm",
"org.jetbrains.kotlinx:kotlinx-coroutines-core",
"org.jetbrains.kotlinx:kotlinx-coroutines-core-common",
"org.jetbrains.kotlinx:kotlinx-coroutines-core-metadata",
"org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm",
"org.jetbrains.kotlinx:kotlinx-io",
"org.jetbrains.kotlinx:kotlinx-io-common",
"org.jetbrains.kotlinx:kotlinx-io-metadata",
"org.jetbrains.kotlinx:kotlinx-io-jvm",
"org.jetbrains.kotlinx:kotlinx-coroutines-io",
"org.jetbrains.kotlinx:kotlinx-coroutines-io-common",
"org.jetbrains.kotlinx:kotlinx-coroutines-io-metadata",
"org.jetbrains.kotlinx:kotlinx-coroutines-io-jvm",
"org.jetbrains.kotlinx:kotlinx-coroutines-core-jdk7",
"org.jetbrains.kotlinx:kotlinx-coroutines-core-jdk8",
"org.jetbrains.kotlinx:kotlinx-coroutines-jdk7",
"org.jetbrains.kotlinx:kotlinx-coroutines-jdk8",
"org.jetbrains.kotlinx:atomicFu",
"org.jetbrains.kotlinx:atomicFu-common",
"org.jetbrains.kotlinx:atomicFu-metadata",
"org.jetbrains.kotlinx:atomicFu-jvm",
"org.jetbrains:annotations:19.0.0",
"io.ktor:ktor-client",
"io.ktor:ktor-client-common",
"io.ktor:ktor-client-metadata",
"io.ktor:ktor-client-jvm",
"io.ktor:ktor-client-cio",
"io.ktor:ktor-client-cio-common",
"io.ktor:ktor-client-cio-metadata",
"io.ktor:ktor-client-cio-jvm",
"io.ktor:ktor-client-core",
"io.ktor:ktor-client-core-common",
"io.ktor:ktor-client-core-metadata",
"io.ktor:ktor-client-core-jvm",
"io.ktor:ktor-client-network",
"io.ktor:ktor-client-network-common",
"io.ktor:ktor-client-network-metadata",
"io.ktor:ktor-client-network-jvm",
"io.ktor:ktor-client-util",
"io.ktor:ktor-client-util-common",
"io.ktor:ktor-client-util-metadata",
"io.ktor:ktor-client-util-jvm",
"io.ktor:ktor-client-http",
"io.ktor:ktor-client-http-common",
"io.ktor:ktor-client-http-metadata",
"io.ktor:ktor-client-http-jvm",
"org.bouncyCastle:bcProv-jdk15on",
"net.mamoe:mirai-core",
"net.mamoe:mirai-core-metadata",
"net.mamoe:mirai-core-common",
"net.mamoe:mirai-core-jvm",
"net.mamoe:mirai-core-api", // for future
"net.mamoe:mirai-core-api-metadata",
"net.mamoe:mirai-core-api-common",
"net.mamoe:mirai-core-api-jvm",
"net.mamoe:mirai-core-qqAndroid",
"net.mamoe:mirai-core-qqAndroid-metadata",
"net.mamoe:mirai-core-qqAndroid-common",
"net.mamoe:mirai-core-qqAndroid-jvm",
"net.mamoe:mirai-console",
"net.mamoe:mirai-console-api", // for future
"net.mamoe:mirai-console-terminal",
"net.mamoe:mirai-console-graphical",
"net.mamoe.yamlKt:yamlKt",
"net.mamoe.yamlKt:yamlKt-common",
"net.mamoe.yamlKt:yamlKt-metadata",
"net.mamoe.yamlKt:yamlKt-jvm",
"net.mamoe:kotlin-jvm-blocking-bridge",
"net.mamoe:kotlin-jvm-blocking-bridge-common",
"net.mamoe:kotlin-jvm-blocking-bridge-metadata",
"net.mamoe:kotlin-jvm-blocking-bridge-jvm"
).map { it.toLowerCase() }.map { MiraiConsoleExtension.ExcludedDependency(it.substringBefore(':'), it.substringAfterLast(':')) }.toTypedArray()

View File

@ -0,0 +1,126 @@
/*
* 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
*/
@file:Suppress("unused", "MemberVisibilityCanBePrivate")
package net.mamoe.mirai.console.gradle
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.JavaVersion
/**
* ```
* mirai {
* // 配置
* }
* ```
*/
// must be open
open class MiraiConsoleExtension {
/**
* `true` 时不自动添加 mirai-core 的依赖
*
* 默认: `false`
*/
var noCore: Boolean = false
/**
* `true` 时不自动为 test 模块添加 mirai-core-qqandroid 的依赖.
*
* 默认: `false`
*/
var noTestCoreQQAndroid: Boolean = false
/**
* `true` 时不自动添加 mirai-console 的依赖.
*
* 默认: `false`
*/
var noConsole: Boolean = false
/**
* 自动添加的 mirai-core mirai-core-qqandroid 的版本.
*
* 默认: 与本 Gradle 插件编译时的 mirai-core 版本相同. [VersionConstants.CORE_VERSION]
*/
var coreVersion: String = VersionConstants.CORE_VERSION
/**
* 自动添加的 mirai-console 后端和前端的版本.
*
* 默认: 与本 Gradle 插件版本相同. [VersionConstants.CONSOLE_VERSION]
*/
var consoleVersion: String = VersionConstants.CONSOLE_VERSION
/**
* 自动为 test 模块添加的前端依赖名称
*
* `null` 时不自动为 test 模块添加前端依赖.
*
* 默认: [MiraiConsoleFrontEndKind.TERMINAL]
*/
var useTestConsoleFrontEnd: MiraiConsoleFrontEndKind? = MiraiConsoleFrontEndKind.TERMINAL
/**
* Java Kotlin 编译目标. 至少为 [JavaVersion.VERSION_1_8].
*
* 一般人不需要修改此项.
*
* 默认: [JavaVersion.VERSION_1_8]
*/
var jvmTarget: JavaVersion = JavaVersion.VERSION_1_8
/**
* 默认会配置 Kotlin 编译器参数 "-Xjvm-default=all". 将此项设置为 `false` 可避免配置.
*
* 一般人不需要修改此项.
*
* 默认: `false`
*/
var dontConfigureKotlinJvmDefault: Boolean = false
internal val shadowConfigurations: MutableList<ShadowJar.() -> Unit> = mutableListOf()
internal val excludedDependencies: MutableSet<ExcludedDependency> = mutableSetOf()
internal data class ExcludedDependency(
val group: String,
val name: String
)
/**
* 配置 [ShadowJar] (即打包插件)
*/
fun configureShadow(configure: ShadowJar.() -> Unit) {
shadowConfigurations.add(configure)
}
/**
* 在插件打包时忽略一个依赖
*
* @param notation 格式为 "groupId:name". "org.jetbrains.kotlin:kotlin-stdlib"
*/
fun excludeDependency(notation: String) {
requireNotNull(notation.count { it == ':' } == 1) { "Invalid dependency notation $notation." }
excludedDependencies.add(ExcludedDependency(notation.substringBefore(':'), notation.substringAfter(':')))
}
/**
* 在插件打包时忽略一个依赖
*
* @param group "org.jetbrains.kotlin"
* @param name "kotlin-stdlib"
*/
fun excludeDependency(group: String, name: String) {
excludedDependencies.add(ExcludedDependency(group, name))
}
}
enum class MiraiConsoleFrontEndKind {
TERMINAL,
}

View File

@ -0,0 +1,156 @@
/*
* 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
*/
@file:JvmMultifileClass
@file:JvmName("MiraiConsoleGradlePluginKt")
package net.mamoe.mirai.console.gradle
import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.tasks.compile.JavaCompile
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
class MiraiConsoleGradlePlugin : Plugin<Project> {
companion object {
internal const val BINTRAY_REPOSITORY_URL = "https://dl.bintray.com/him188moe/mirai"
}
private fun KotlinSourceSet.configureSourceSet(project: Project) {
languageSettings.useExperimentalAnnotation("kotlin.RequiresOptIn")
dependencies { configureDependencies(project, this@configureSourceSet) }
}
private fun Project.configureTarget(target: KotlinTarget) {
val miraiExtension = project.miraiExtension
for (compilation in target.compilations) with(compilation) {
kotlinOptions {
if (this !is KotlinJvmOptions) return@kotlinOptions
jvmTarget = miraiExtension.jvmTarget.toString()
if (!miraiExtension.dontConfigureKotlinJvmDefault) freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
}
}
target.compilations.flatMap { it.allKotlinSourceSets }.forEach { sourceSet ->
sourceSet.configureSourceSet(project)
}
}
@Suppress("SpellCheckingInspection")
private fun KotlinDependencyHandler.configureDependencies(project: Project, sourceSet: KotlinSourceSet) {
val miraiExtension = project.miraiExtension
if (!miraiExtension.noCore) compileOnly("net.mamoe:mirai-core:${miraiExtension.coreVersion}")
if (!miraiExtension.noConsole) compileOnly("net.mamoe:mirai-console:${miraiExtension.consoleVersion}")
if (sourceSet.name.endsWith("test", ignoreCase = true)) {
if (!miraiExtension.noCore) api("net.mamoe:mirai-core:${miraiExtension.coreVersion}")
if (!miraiExtension.noConsole) api("net.mamoe:mirai-console:${miraiExtension.consoleVersion}")
if (!miraiExtension.noTestCoreQQAndroid) api("net.mamoe:mirai-core-qqandroid:${miraiExtension.coreVersion}")
when (miraiExtension.useTestConsoleFrontEnd) {
MiraiConsoleFrontEndKind.TERMINAL -> api("net.mamoe:mirai-console-terminal:${miraiExtension.consoleVersion}")
}
}
}
private fun Project.configureCompileTarget() {
extensions.findByType(JavaPluginExtension::class.java)?.apply {
val miraiExtension = miraiExtension
sourceCompatibility = miraiExtension.jvmTarget
targetCompatibility = miraiExtension.jvmTarget
}
tasks.withType(JavaCompile::class.java) {
it.options.encoding = "UTF8"
}
}
private fun Project.registerBuildPluginTasks() {
val miraiExtension = this.miraiExtension
tasks.findByName("shadowJar")?.enabled = false
fun registerBuildPluginTask(target: KotlinTarget, isSinglePlatform: Boolean) {
tasks.create(if (isSinglePlatform) "buildPlugin" else "buildPlugin${target.name.capitalize()}", ShadowJar::class.java).apply shadow@{
group = "mirai"
val compilations = target.compilations.filter { it.name == MAIN_COMPILATION_NAME }
compilations.forEach {
dependsOn(it.compileKotlinTask)
from(it.output)
}
from(project.configurations.getByName("runtimeClasspath").copyRecursive { dependency ->
for (excludedDependency in IGNORED_DEPENDENCIES_IN_SHADOW + miraiExtension.excludedDependencies) {
if (excludedDependency.group == dependency.group
&& excludedDependency.name == dependency.name
) return@copyRecursive false
}
true
})
exclude { file ->
file.name.endsWith(".sf", ignoreCase = true)
}
destinationDirectory.value(project.layout.projectDirectory.dir(project.buildDir.name).dir("mirai"))
miraiExtension.shadowConfigurations.forEach { it.invoke(this@shadow) }
}
}
val targets = kotlinTargets
val isSingleTarget = targets.size == 1
targets.forEach { target ->
registerBuildPluginTask(target, isSingleTarget)
}
}
override fun apply(target: Project): Unit = with(target) {
target.extensions.create("mirai", MiraiConsoleExtension::class.java)
target.plugins.apply(JavaPlugin::class.java)
target.plugins.apply(ShadowPlugin::class.java)
target.repositories.maven { it.setUrl(BINTRAY_REPOSITORY_URL) }
afterEvaluate {
configureCompileTarget()
registerBuildPluginTasks()
kotlinTargets.forEach { configureTarget(it) }
}
}
}
internal val Project.miraiExtension: MiraiConsoleExtension
get() = extensions.findByType(MiraiConsoleExtension::class.java) ?: error("Cannot find MiraiConsoleExtension in project ${this.name}")
internal val Project.kotlinTargets: Collection<KotlinTarget>
get() {
val kotlinExtension = extensions.findByType(KotlinProjectExtension::class.java)
?: error("Kotlin plugin not applied. Please read https://www.kotlincn.net/docs/reference/using-gradle.html")
return when (kotlinExtension) {
is KotlinMultiplatformExtension -> kotlinExtension.targets
is KotlinSingleTargetExtension -> listOf(kotlinExtension.target)
else -> error("[MiraiConsole] Internal error: kotlinExtension is neither KotlinMultiplatformExtension nor KotlinSingleTargetExtension")
}
}

View File

@ -0,0 +1,15 @@
/*
* 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
*/
package net.mamoe.mirai.console.gradle
internal object VersionConstants {
const val CONSOLE_VERSION = "1.0-RC-dev-28" // value is written here automatically during build
const val CORE_VERSION = "1.3.0" // value is written here automatically during build
}