6.7.0 - Alpha11 - 修复 Gradle 构建脚本 Java 与 Kotlin 的 JVM 目标版本一致性问题
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package org.autojs.build
|
||||
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.file.CopySpec
|
||||
@@ -251,16 +252,16 @@ object Utils {
|
||||
val installer = {
|
||||
project.logInfo("[JvmConv] Detected Android plugin in module='${project.path}', installing configuration")
|
||||
|
||||
// Java: Use Toolchain (module-level + task-level), do not set --release.
|
||||
// zh-CN: Java: 使用 Toolchain (模块级 + 任务级), 不要设置 --release.
|
||||
System.getProperty("gradle.java.version.select").let { ver ->
|
||||
configureJavaToolchainLanguageLevel(project, ver)
|
||||
configureJavaToolchainForAllJavaCompile(project, ver)
|
||||
configureKotlinJvmToolchain(project, ver)
|
||||
}
|
||||
|
||||
configureJavaToolchainLanguageLevel(project, versions.javaVersionInt)
|
||||
configureJavaToolchainForAllJavaCompile(project, versions.javaVersionInt)
|
||||
|
||||
// Kotlin: Continue lazy configuration to set jvmTarget.
|
||||
// zh-CN: Kotlin: 继续懒配置设置 jvmTarget.
|
||||
|
||||
configureKotlinJvmTargetLazily(project, versions)
|
||||
System.getProperty("gradle.jvm.target.effective").let { ver ->
|
||||
configureAndroidCompileOptions(project, ver)
|
||||
configureKotlinJvmTargetLazily(project, ver)
|
||||
}
|
||||
|
||||
project.logInfo("[JvmConv] Installed Java toolchain (module+tasks) and Kotlin jvmTarget for '${project.path}'")
|
||||
}
|
||||
@@ -271,7 +272,7 @@ object Utils {
|
||||
|
||||
// Module-level toolchain: Let AGP/Gradle know which JDK language level should be used for this module.
|
||||
// zh-CN: 模块级 Toolchain: 让 AGP/Gradle 知道本模块应使用的 JDK 语言级别.
|
||||
private fun configureJavaToolchainLanguageLevel(project: Project, target: Int) {
|
||||
private fun configureJavaToolchainLanguageLevel(project: Project, target: String) {
|
||||
val javaExt = project.extensions.findByType(JavaPluginExtension::class.java)
|
||||
if (javaExt == null) {
|
||||
project.logWarn("[JvmConv] JavaPluginExtension not found in '${project.path}', skip module-level toolchain")
|
||||
@@ -286,9 +287,24 @@ object Utils {
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureKotlinJvmToolchain(project: Project, target: String) {
|
||||
project.plugins.withId("org.jetbrains.kotlin.android") {
|
||||
project.extensions.findByName("kotlin")?.let { kotlinExt ->
|
||||
runCatching {
|
||||
kotlinExt.javaClass.getMethod("jvmToolchain", Int::class.java)
|
||||
.invoke(kotlinExt, target.toInt())
|
||||
}.onSuccess {
|
||||
project.logInfo("[JvmConv] Kotlin jvmToolchain set to $target for '${project.path}'")
|
||||
}.onFailure {
|
||||
project.logError("[JvmConv] Set Kotlin jvmToolchain failed on '${project.path}': ${it.message}", it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Task-level Toolchain: Specify javaCompiler for all JavaCompile tasks, without setting --release (prohibited by AGP).
|
||||
// zh-CN: 任务级 Toolchain: 对所有 JavaCompile 指定 javaCompiler, 且不要设置 --release (AGP 禁止).
|
||||
private fun configureJavaToolchainForAllJavaCompile(project: Project, target: Int) {
|
||||
private fun configureJavaToolchainForAllJavaCompile(project: Project, target: String) {
|
||||
val toolchains = runCatching {
|
||||
project.extensions.getByType(JavaToolchainService::class.java)
|
||||
}.onFailure {
|
||||
@@ -309,6 +325,37 @@ object Utils {
|
||||
})
|
||||
}
|
||||
|
||||
// 将 Android 的 compileOptions.sourceCompatibility/targetCompatibility 设置为给定目标 (如 "24"), 确保与 Kotlin 一致
|
||||
// zh-CN: 使用反射避免对 AGP 具体类型的直接依赖; 兼容 application/library.
|
||||
private fun configureAndroidCompileOptions(project: Project, target: String) {
|
||||
val androidExt = project.extensions.findByName("android") ?: run {
|
||||
project.logWarn("[JvmConv] Android extension not found in '${project.path}', skip compileOptions alignment")
|
||||
return
|
||||
}
|
||||
runCatching {
|
||||
val compileOptions = androidExt.javaClass.methods
|
||||
.firstOrNull { it.name == "getCompileOptions" && it.parameterTypes.isEmpty() }
|
||||
?.invoke(androidExt) ?: return@runCatching project.logWarn("[JvmConv] compileOptions not found on android extension for '${project.path}'")
|
||||
|
||||
val javaVersionClass = Class.forName("org.gradle.api.JavaVersion")
|
||||
val javaVersion = JavaVersion.toVersion(target)
|
||||
|
||||
val setSource = compileOptions.javaClass.methods.firstOrNull {
|
||||
it.name == "setSourceCompatibility" && it.parameterTypes.size == 1 && it.parameterTypes[0] == javaVersionClass
|
||||
} ?: throw IllegalStateException("setSourceCompatibility(JavaVersion) not found")
|
||||
val setTarget = compileOptions.javaClass.methods.firstOrNull {
|
||||
it.name == "setTargetCompatibility" && it.parameterTypes.size == 1 && it.parameterTypes[0] == javaVersionClass
|
||||
} ?: throw IllegalStateException("setTargetCompatibility(JavaVersion) not found")
|
||||
|
||||
setSource.invoke(compileOptions, javaVersion)
|
||||
setTarget.invoke(compileOptions, javaVersion)
|
||||
|
||||
project.logInfo("[JvmConv] Android compileOptions source/target set to Java $target for '${project.path}'")
|
||||
}.onFailure {
|
||||
project.logError("[JvmConv] Configure Android compileOptions failed on '${project.path}': ${it.message}", it)
|
||||
}
|
||||
}
|
||||
|
||||
// Configure jvmTarget for KotlinCompile tasks:
|
||||
// Use configureEach for lazy configuration on task creation;
|
||||
// Compatible with old and new APIs.
|
||||
@@ -316,8 +363,8 @@ object Utils {
|
||||
// 为 KotlinCompile 任务设置 jvmTarget:
|
||||
// 使用 configureEach, 任务实现时自动应用;
|
||||
// 兼容新旧 API.
|
||||
private fun configureKotlinJvmTargetLazily(project: Project, versions: Versions) {
|
||||
val desiredStr = versions.javaVersionString // e.g. "22"
|
||||
private fun configureKotlinJvmTargetLazily(project: Project, target: String) {
|
||||
val desiredStr = target // e.g. "22"
|
||||
val desiredEnumName = "JVM_${desiredStr}" // e.g. "JVM_22"
|
||||
project.logInfo("[JvmConv] Will configure Kotlin jvmTarget lazily to '$desiredEnumName' in '${project.path}'")
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.autojs.build
|
||||
|
||||
import org.autojs.build.Utils.getOrNull
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.execution.TaskExecutionGraph
|
||||
@@ -10,7 +9,6 @@ import org.gradle.kotlin.dsl.extra
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.util.*
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.text.RegexOption.IGNORE_CASE
|
||||
|
||||
class Versions @JvmOverloads constructor(
|
||||
@@ -18,15 +16,16 @@ class Versions @JvmOverloads constructor(
|
||||
filePath: String = "${project.rootDir}/version.properties",
|
||||
) {
|
||||
private val gradle = project.gradle
|
||||
private val logger = project.logger
|
||||
|
||||
private val currentVersionInt = JavaVersion.current().majorVersion.toInt()
|
||||
|
||||
private val bp = BuildProperties.loadFrom(filePath)
|
||||
|
||||
private val javaVersionMinSuggested: Int = bp.requireInt("JAVA_VERSION_MIN_SUGGESTED")
|
||||
private val javaVersionCurrentInt = JavaVersion.current().majorVersion.toInt()
|
||||
private val javaVersionMinSupported: Int = bp.requireInt("JAVA_VERSION_MIN_SUPPORTED")
|
||||
private val javaVersionMaxSupported: Int = bp.requireInt("JAVA_VERSION_MAX_SUPPORTED")
|
||||
|
||||
private val javaVersionInt: Int = System.getProperty("gradle.java.version.select").toInt()
|
||||
private val javaVersionInfoSuffix: String = System.getProperty("gradle.java.version.suffix", "")
|
||||
|
||||
private var isBuildNumberAutoIncremented = false
|
||||
private val minBuildTimeGap = Utils.hours2Millis(0.75)
|
||||
|
||||
@@ -41,93 +40,12 @@ class Versions @JvmOverloads constructor(
|
||||
val appVersionCode = bp.requireInt("VERSION_BUILD")
|
||||
val vscodeExtRequiredVersion = bp.requireString("VSCODE_EXT_REQUIRED_VERSION")
|
||||
|
||||
private val javaVersionMinSupported: Int = bp.requireInt("JAVA_VERSION_MIN_SUPPORTED")
|
||||
|
||||
var javaVersionInt by Delegates.notNull<Int>()
|
||||
var javaVersionInfoSuffix by Delegates.notNull<String>()
|
||||
|
||||
val javaVersion: JavaVersion
|
||||
get() = JavaVersion.toVersion(javaVersionInt)
|
||||
|
||||
val javaVersionString: String
|
||||
get() = javaVersion.toString()
|
||||
|
||||
init {
|
||||
validateCurrentVersion()
|
||||
determineJavaVersion().also { (javaVersionInt, javaVersionInfoSuffix) ->
|
||||
this.javaVersionInt = javaVersionInt
|
||||
this.javaVersionInfoSuffix = javaVersionInfoSuffix
|
||||
}
|
||||
}
|
||||
|
||||
private fun validateCurrentVersion() {
|
||||
if (gradle.extra.getOrNull<Boolean>(VALIDATED_EXTRA_KEY) == true) {
|
||||
return
|
||||
}
|
||||
if (currentVersionInt < javaVersionMinSupported) {
|
||||
throw GradleException("Current Gradle JDK version [$currentVersionInt] does not meet the minimum requirement which [$javaVersionMinSupported] is needed.")
|
||||
}
|
||||
if (currentVersionInt < javaVersionMinSuggested) {
|
||||
val suffix = if (javaVersionMaxSupported > 0) " (but not higher than [$javaVersionMaxSupported])" else ""
|
||||
logger.error("It is recommended to upgrade current Gradle JDK version [$currentVersionInt] to [$javaVersionMinSuggested] or higher$suffix.")
|
||||
}
|
||||
if (currentVersionInt > javaVersionMaxSupported) {
|
||||
val suffix = if (javaVersionMaxSupported > javaVersionMinSuggested) " or lower (but not lower than [$javaVersionMinSuggested])" else ""
|
||||
logger.error("It is recommended to downgrade current Gradle JDK version [$currentVersionInt] to [$javaVersionMaxSupported]$suffix, as Gradle may be not compatible with JDK [$currentVersionInt] for now.")
|
||||
}
|
||||
gradle.extra.set(VALIDATED_EXTRA_KEY, true)
|
||||
}
|
||||
|
||||
private fun determineJavaVersion(): Pair<Int, String> {
|
||||
var javaVersionInfoSuffix = ""
|
||||
|
||||
gradle.extra.getOrNull<Int>("javaVersionOverriddenByUser")?.let {
|
||||
javaVersionInfoSuffix += " [user-specified]"
|
||||
return it to javaVersionInfoSuffix
|
||||
}
|
||||
|
||||
var versionInt = JavaVersion.current().majorVersion.toInt()
|
||||
|
||||
run tryAdjustJavaVersionByKotlinJvmTarget@{
|
||||
var isJvmCoercive = false
|
||||
|
||||
while (versionInt > javaVersionMinSupported) {
|
||||
if (isJvmTargetAvailable(versionInt)) {
|
||||
break
|
||||
}
|
||||
versionInt -= 1
|
||||
isJvmCoercive = true
|
||||
}
|
||||
|
||||
if (isJvmCoercive) {
|
||||
javaVersionInfoSuffix += " [coercive-jvm-downgraded]"
|
||||
}
|
||||
}
|
||||
|
||||
gradle.extra.getOrNull<Int>("javaVersionCoercedByGradle")?.let {
|
||||
if (versionInt > it) {
|
||||
versionInt = it
|
||||
javaVersionInfoSuffix += " [coercive-gradle-downgraded]"
|
||||
}
|
||||
}
|
||||
return versionInt to javaVersionInfoSuffix
|
||||
}
|
||||
|
||||
private fun isJvmTargetAvailable(target: Int): Boolean {
|
||||
try {
|
||||
// Weak dependency with Kotlin plugin: Use reflection to check if JvmTarget is available;
|
||||
// if reflection fails, treat it as available (to avoid incorrect downgrading).
|
||||
// zh-CN: 与 Kotlin 插件弱依赖: 反射判断 JvmTarget 是否可用; 反射失败则视为可用 (避免误降级).
|
||||
val cls = Class.forName("org.jetbrains.kotlin.gradle.dsl.JvmTarget")
|
||||
cls.enumConstants?.let { values ->
|
||||
return values.any { it?.toString().equals("JVM_$target", true) }
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
logger.error("Failed to check JVM target availability: $e")
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
operator fun get(propertyName: String) = bp[propertyName]
|
||||
|
||||
operator fun get(propertyInfo: List<String>) = bp[propertyInfo]
|
||||
@@ -138,6 +56,7 @@ class Versions @JvmOverloads constructor(
|
||||
val infoVerName = "Version name: $appVersionName"
|
||||
val infoVerCode = "Version code: ${if (isBuildNumberAutoIncremented) "${appVersionCode + 1} [auto-incremented]" else appVersionCode}"
|
||||
val infoVerSdk = "SDK versions: min [$sdkVersionMin] / target [$sdkVersionTarget] / compile [$sdkVersionCompile]"
|
||||
val infoVerJdk = "JDK versions: min [$javaVersionMinSupported] / select [$javaVersionInt] / current [$javaVersionCurrentInt] / max [$javaVersionMaxSupported]"
|
||||
val infoVerJava = "Java version: $javaVersion${
|
||||
when {
|
||||
gradle.extra.getOrNull<Boolean>("isHideConsoleInfoHintSuffix") == true -> ""
|
||||
@@ -145,7 +64,7 @@ class Versions @JvmOverloads constructor(
|
||||
}
|
||||
}"
|
||||
|
||||
val maxLength = arrayOf(title, infoVerName, infoVerCode, infoVerSdk, infoVerJava).maxOf { it.length }
|
||||
val maxLength = arrayOf(title, infoVerName, infoVerCode, infoVerSdk, infoVerJdk, infoVerJava).maxOf { it.length }
|
||||
|
||||
arrayOf(
|
||||
"=".repeat(maxLength),
|
||||
@@ -154,6 +73,7 @@ class Versions @JvmOverloads constructor(
|
||||
infoVerName,
|
||||
infoVerCode,
|
||||
infoVerSdk,
|
||||
infoVerJdk,
|
||||
infoVerJava,
|
||||
"=".repeat(maxLength),
|
||||
"",
|
||||
@@ -203,8 +123,4 @@ class Versions @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val VALIDATED_EXTRA_KEY = "org.autojs.build.Versions.currentValidated"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user