mirror of
https://github.com/mamoe/mirai.git
synced 2026-08-22 14:13:32 +08:00
[build] Fix shadow task dependencies and check-publishing actions
This commit is contained in:
4
.github/workflows/check-publishing.yml
vendored
4
.github/workflows/check-publishing.yml
vendored
@@ -78,7 +78,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Build and Publish Local Artifacts
|
- name: Build and Publish Local Artifacts
|
||||||
if: ${{ env.enableLocalPublishingTest == 'true' }}
|
if: ${{ env.enableLocalPublishingTest == 'true' }}
|
||||||
run: ./gradlew :mirai-deps-test:publishMiraiArtifactsToMavenLocal ${{ env.gradleArgs }} "-Dmirai.build.project.version=2.99.0-deps-test"
|
run: ./gradlew :mirai-deps-test:publishMiraiLocalArtifacts ${{ env.gradleArgs }} "-Dmirai.build.project.version=2.99.0-deps-test"
|
||||||
|
|
||||||
- name: Check Publication
|
- name: Check Publication
|
||||||
if: ${{ env.enableLocalPublishingTest == 'true' }}
|
if: ${{ env.enableLocalPublishingTest == 'true' }}
|
||||||
@@ -204,7 +204,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Build and Publish Local Artifacts
|
- name: Build and Publish Local Artifacts
|
||||||
if: ${{ env.enableLocalPublishingTest == 'true' }}
|
if: ${{ env.enableLocalPublishingTest == 'true' }}
|
||||||
run: ./gradlew :mirai-deps-test:publishMiraiArtifactsToMavenLocal ${{ env.gradleArgs }} "-Dmirai.build.project.version=2.99.0-deps-test"
|
run: ./gradlew :mirai-deps-test:publishMiraiLocalArtifacts ${{ env.gradleArgs }} "-Dmirai.build.project.version=2.99.0-deps-test"
|
||||||
|
|
||||||
- name: Check Publication
|
- name: Check Publication
|
||||||
if: ${{ env.enableLocalPublishingTest == 'true' }}
|
if: ${{ env.enableLocalPublishingTest == 'true' }}
|
||||||
|
|||||||
@@ -87,6 +87,9 @@ allprojects {
|
|||||||
substituteDependenciesUsingExpectedVersion()
|
substituteDependenciesUsingExpectedVersion()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
afterEvaluate {
|
||||||
|
configureShadowDependenciesForPublishing()
|
||||||
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
|
|||||||
@@ -86,14 +86,17 @@ enum class HostArch {
|
|||||||
/// eg. "a;b;!other" means to disable all targets but a or b
|
/// eg. "a;b;!other" means to disable all targets but a or b
|
||||||
val ENABLED_TARGETS by lazy {
|
val ENABLED_TARGETS by lazy {
|
||||||
|
|
||||||
val targets = System.getProperty(
|
val targets = getMiraiTargetFromGradle() // enable all by default
|
||||||
"mirai.target"
|
|
||||||
) ?: rootProject.getLocalProperty("projects.mirai-core.targets")
|
|
||||||
?: "others" // enable all by default
|
|
||||||
|
|
||||||
targets.split(';').toSet()
|
targets.split(';').toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getMiraiTargetFromGradle() =
|
||||||
|
System.getProperty("mirai.target")
|
||||||
|
?: System.getenv("mirai.target")
|
||||||
|
?: rootProject.getLocalProperty("projects.mirai-core.targets")
|
||||||
|
?: "others"
|
||||||
|
|
||||||
fun isTargetEnabled(name: String): Boolean {
|
fun isTargetEnabled(name: String): Boolean {
|
||||||
val isNative = name in POSSIBLE_NATIVE_TARGETS
|
val isNative = name in POSSIBLE_NATIVE_TARGETS
|
||||||
return when {
|
return when {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.google.gson.GsonBuilder
|
|||||||
import org.gradle.api.GradleException
|
import org.gradle.api.GradleException
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.Task
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.api.execution.TaskExecutionGraph
|
||||||
import org.gradle.api.publish.tasks.GenerateModuleMetadata
|
import org.gradle.api.publish.tasks.GenerateModuleMetadata
|
||||||
import org.gradle.kotlin.dsl.create
|
import org.gradle.kotlin.dsl.create
|
||||||
import org.gradle.kotlin.dsl.get
|
import org.gradle.kotlin.dsl.get
|
||||||
@@ -29,20 +30,68 @@ fun Project.configureMppShadow() {
|
|||||||
it.platformType == org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.jvm
|
it.platformType == org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.jvm
|
||||||
&& (it.attributes.getAttribute(MIRAI_PLATFORM_INTERMEDIATE) != true)
|
&& (it.attributes.getAttribute(MIRAI_PLATFORM_INTERMEDIATE) != true)
|
||||||
}) {
|
}) {
|
||||||
configureRelocationForTarget(project)
|
configureRelocationForMppTarget(project)
|
||||||
|
|
||||||
registerRegularShadowTask(this, mapTaskNameForMultipleTargets = true)
|
registerRegularShadowTask(this, mapTaskNameForMultipleTargets = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置 `publish` 和 `shadow` 相关依赖. 对于在本次构建的请求的任务及其直接或间接依赖, 以以下顺序执行:
|
||||||
|
*
|
||||||
|
* 1. 执行全部 `jar` 任务
|
||||||
|
* 2. 执行全部 `relocate` 任务
|
||||||
|
* 3. 执行全部 `publish` 任务
|
||||||
|
*
|
||||||
|
* 这是必要的因为 relocate 任务会覆盖 jar 任务的输出, 而在多模块并行编译时, Kotlin 编译器会依赖 jar 任务的输出. 如果在编译同时修改 JAR 文件, 就会导致 `ZipException`.
|
||||||
|
*
|
||||||
|
* 这也会让 publish 集中执行, Maven Central 不容易出问题.
|
||||||
|
*/
|
||||||
|
fun Project.configureShadowDependenciesForPublishing() {
|
||||||
|
check(this.rootProject === this) {
|
||||||
|
"configureShadowDependenciesForPublishing can only be used on root project."
|
||||||
|
}
|
||||||
|
|
||||||
|
gradle.projectsEvaluated {
|
||||||
|
// Tasks requested to run in this build
|
||||||
|
val allTasks = rootProject.allprojects.asSequence().flatMap { it.tasks }
|
||||||
|
|
||||||
|
val publishTasks = allTasks.filter { it.name.contains("publish", ignoreCase = true) }
|
||||||
|
val relocateTasks = allTasks.filter { it.name.contains("relocate", ignoreCase = true) }
|
||||||
|
val jarTasks = allTasks.filter { it.name.contains("jar", ignoreCase = true) }
|
||||||
|
val compileKotlinTasks = allTasks.filter { it.name.contains("compileKotlin", ignoreCase = true) }
|
||||||
|
val compileTestKotlinTasks = allTasks.filter { it.name.contains("compileTestKotlin", ignoreCase = true) }
|
||||||
|
|
||||||
|
relocateTasks.dependsOn(compileKotlinTasks.toList())
|
||||||
|
relocateTasks.dependsOn(compileTestKotlinTasks.toList())
|
||||||
|
relocateTasks.dependsOn(jarTasks.toList())
|
||||||
|
publishTasks.dependsOn(relocateTasks.toList())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val TaskExecutionGraph.hierarchicalTasks: Sequence<Task>
|
||||||
|
get() = sequence {
|
||||||
|
suspend fun SequenceScope<Task>.addTask(task: Task) {
|
||||||
|
yield(task)
|
||||||
|
for (dependency in getDependencies(task)) {
|
||||||
|
addTask(dependency)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (task in allTasks) {
|
||||||
|
addTask(task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Relocate some dependencies for `.jar`
|
* Relocate some dependencies for `.jar`
|
||||||
* @see RelocationNotes
|
* @see RelocationNotes
|
||||||
*/
|
*/
|
||||||
private fun KotlinTarget.configureRelocationForTarget(project: Project) = project.run {
|
private fun KotlinTarget.configureRelocationForMppTarget(project: Project) = project.run {
|
||||||
val configuration = project.configurations.findByName(SHADOW_RELOCATION_CONFIGURATION_NAME)
|
val configuration = project.configurations.findByName(SHADOW_RELOCATION_CONFIGURATION_NAME)
|
||||||
|
|
||||||
// e.g. relocateJvmDependencies
|
// e.g. relocateJvmDependencies
|
||||||
|
// do not change task name. see `configureShadowDependenciesForPublishing`
|
||||||
val relocateDependencies = tasks.create("relocate${targetName.titlecase()}Dependencies", ShadowJar::class) {
|
val relocateDependencies = tasks.create("relocate${targetName.titlecase()}Dependencies", ShadowJar::class) {
|
||||||
group = "mirai"
|
group = "mirai"
|
||||||
description = "Relocate dependencies to internal package"
|
description = "Relocate dependencies to internal package"
|
||||||
@@ -67,15 +116,13 @@ private fun KotlinTarget.configureRelocationForTarget(project: Project) = projec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relocate before packing Jar. Projects that depends on this project actually (explicitly or implicitly) depends on the Jar.
|
|
||||||
tasks.getByName("${targetName}Jar").dependsOn(relocateDependencies)
|
|
||||||
|
|
||||||
// We will modify Kotlin metadata, so do generate metadata before relocation
|
// We will modify Kotlin metadata, so do generate metadata before relocation
|
||||||
val generateMetadataTask =
|
val generateMetadataTask =
|
||||||
tasks.getByName("generateMetadataFileFor${targetName.capitalize()}Publication") as GenerateModuleMetadata
|
tasks.getByName("generateMetadataFileFor${targetName.capitalize()}Publication") as GenerateModuleMetadata
|
||||||
|
|
||||||
val patchMetadataTask = tasks.create("patchMetadataFileFor${targetName.capitalize()}RelocatedPublication") {
|
val patchMetadataTask = tasks.create("patchMetadataFileFor${targetName.capitalize()}RelocatedPublication") {
|
||||||
dependsOn(generateMetadataTask)
|
dependsOn(generateMetadataTask)
|
||||||
|
dependsOn(relocateDependencies)
|
||||||
|
|
||||||
// remove dependencies in Kotlin module metadata
|
// remove dependencies in Kotlin module metadata
|
||||||
doLast {
|
doLast {
|
||||||
@@ -157,23 +204,15 @@ private fun KotlinTarget.configureRelocationForTarget(project: Project) = projec
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Sequence<Task>.dependsOn(
|
private fun Sequence<Task>.dependsOn(
|
||||||
relocateDependencies: ShadowJar,
|
task: Task,
|
||||||
kotlinTarget: KotlinTarget,
|
) {
|
||||||
): Int {
|
return forEach { it.dependsOn(task) }
|
||||||
return onEach { relocateDependencies.dependsOn(it) }
|
|
||||||
.count().also {
|
|
||||||
check(it > 0) { "[Shadow Relocation] Expected at least one task task matched for target ${kotlinTarget.targetName}." }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Sequence<Task>.mustRunAfter(
|
private fun Sequence<Task>.dependsOn(
|
||||||
relocateDependencies: ShadowJar,
|
tasks: Iterable<Task>,
|
||||||
kotlinTarget: KotlinTarget,
|
) {
|
||||||
): Int {
|
return forEach { it.dependsOn(tasks) }
|
||||||
return onEach { relocateDependencies.mustRunAfter(it) }
|
|
||||||
.count().also {
|
|
||||||
check(it > 0) { "[Shadow Relocation] Expected at least one task task matched for target ${kotlinTarget.targetName}." }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Project.registerRegularShadowTask(target: KotlinTarget, mapTaskNameForMultipleTargets: Boolean): ShadowJar {
|
private fun Project.registerRegularShadowTask(target: KotlinTarget, mapTaskNameForMultipleTargets: Boolean): ShadowJar {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
|
|||||||
object Versions {
|
object Versions {
|
||||||
val project = System.getenv("mirai.build.project.version")?.takeIf { it.isNotBlank() }
|
val project = System.getenv("mirai.build.project.version")?.takeIf { it.isNotBlank() }
|
||||||
?: System.getProperty("mirai.build.project.version")?.takeIf { it.isNotBlank() }
|
?: System.getProperty("mirai.build.project.version")?.takeIf { it.isNotBlank() }
|
||||||
?: /*PROJECT_VERSION_START*/"2.14.0-dev-shadow-1"/*PROJECT_VERSION_END*/
|
?: /*PROJECT_VERSION_START*/"2.14.0-dev-shadow-6"/*PROJECT_VERSION_END*/
|
||||||
|
|
||||||
val core = project
|
val core = project
|
||||||
val console = project
|
val console = project
|
||||||
|
|||||||
@@ -86,19 +86,59 @@ fun generateBuildConfig() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("publishMiraiLocalArtifacts", Exec::class) {
|
// keep this property for Search Everywhere
|
||||||
|
val publishMiraiLocalArtifacts = tasks.register("publishMiraiLocalArtifacts", Exec::class) {
|
||||||
group = "mirai"
|
group = "mirai"
|
||||||
description = "Starts a child process to publish v2.99.0-deps-test artifacts to MavenLocal"
|
description = "Starts a child process to publish v2.99.0-deps-test artifacts to MavenLocal"
|
||||||
|
|
||||||
workingDir(rootProject.projectDir)
|
workingDir(rootProject.projectDir)
|
||||||
|
|
||||||
|
// The following code configures the new Gradle instance to inheriting configuration.
|
||||||
|
// This is important especially for "mirai.target" settings
|
||||||
|
// — On CI machines we didn't configure them to cross-compilation.
|
||||||
|
// Note that IntelliJ listener is also inherited, so you will see normal execution feedbacks in your IDE 'Run' view.
|
||||||
|
environment(System.getenv())
|
||||||
environment("mirai.build.project.version", "2.99.0-deps-test")
|
environment("mirai.build.project.version", "2.99.0-deps-test")
|
||||||
|
environment("mirai.target", getMiraiTargetFromGradle())
|
||||||
|
|
||||||
|
val projectProperties =
|
||||||
|
// gradle.startParameter.projectProperties
|
||||||
|
mapOf<String, String>()
|
||||||
|
.toMutableMap().apply {
|
||||||
|
put("kotlin.compiler.execution.strategy", "in-process")
|
||||||
|
}
|
||||||
|
.map { "-P${it.key}=${it.value}" }
|
||||||
|
.toTypedArray()
|
||||||
|
|
||||||
|
val allowedProperties = arrayOf("org.gradle.parallel")
|
||||||
|
val systemProperties =
|
||||||
|
// gradle.startParameter.systemPropertiesArgs
|
||||||
|
gradle.startParameter.systemPropertiesArgs
|
||||||
|
.filter { it.key in allowedProperties }
|
||||||
|
.map { "-D${it.key}=${it.value}" }
|
||||||
|
.toTypedArray()
|
||||||
|
|
||||||
commandLine(
|
commandLine(
|
||||||
"./gradlew",
|
"./gradlew",
|
||||||
publishMiraiArtifactsToMavenLocal.name,
|
publishMiraiArtifactsToMavenLocal.name,
|
||||||
"--no-daemon",
|
"--no-daemon",
|
||||||
"--stacktrace",
|
"--stacktrace",
|
||||||
"-Pkotlin.compiler.execution.strategy=in-process"
|
"--scan",
|
||||||
)
|
*projectProperties,
|
||||||
|
*systemProperties,
|
||||||
|
) // ignore other Gradle args
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
|
||||||
|
// TODO: 2022/11/22 fix tips
|
||||||
|
logger.info(
|
||||||
|
"[publishMiraiLocalArtifacts] Starting a Gradle daemon to run requested publishing tasks. " +
|
||||||
|
"Your system environment, JVM properties, and Gradle properties are inherited, " +
|
||||||
|
"but note that any other Gradle arguments are IGNORED!"
|
||||||
|
)
|
||||||
|
logger.info("[publishMiraiLocalArtifacts] Oh, and don't worry, the daemon will be stopped after the task finishes so it won't waste your memory!")
|
||||||
|
}
|
||||||
|
|
||||||
standardOutput = System.out
|
standardOutput = System.out
|
||||||
errorOutput = System.err
|
errorOutput = System.err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user