Browse Source

Raise error when Homebrew JDK is used for packaging (#3451)

Resolves #3107
pull/3456/head
Alexey Tsvetkov 9 months ago committed by GitHub
parent
commit
1dc5839ed7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      gradle-plugins/compose/build.gradle.kts
  2. 4
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/ComposeProjectProperties.kt
  3. 1
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureJvmApplication.kt
  4. 56
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractCheckNativeDistributionRuntime.kt
  5. 25
      gradle-plugins/jdk-version-probe/src/main/java/org/jetbrains/compose/desktop/application/internal/JdkVersionProbe.java

1
gradle-plugins/compose/build.gradle.kts

@ -70,6 +70,7 @@ dependencies {
embedded("org.jetbrains.kotlinx:kotlinx-serialization-core:${BuildProperties.serializationVersion}")
embedded("org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:${BuildProperties.serializationVersion}")
embedded(project(":preview-rpc"))
embedded(project(":jdk-version-probe"))
}
val shadow = tasks.named<ShadowJar>("shadowJar") {

4
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/ComposeProjectProperties.kt

@ -20,6 +20,7 @@ internal object ComposeProperties {
internal const val MAC_NOTARIZATION_APPLE_ID = "compose.desktop.mac.notarization.appleID"
internal const val MAC_NOTARIZATION_PASSWORD = "compose.desktop.mac.notarization.password"
internal const val MAC_NOTARIZATION_ASC_PROVIDER = "compose.desktop.mac.notarization.ascProvider"
internal const val CHECK_JDK_VENDOR = "compose.desktop.packaging.checkJdkVendor"
fun isVerbose(providers: ProviderFactory): Provider<Boolean> =
providers.findProperty(VERBOSE).toBooleanProvider(false)
@ -47,4 +48,7 @@ internal object ComposeProperties {
fun macNotarizationAscProvider(providers: ProviderFactory): Provider<String?> =
providers.findProperty(MAC_NOTARIZATION_ASC_PROVIDER)
fun checkJdkVendor(providers: ProviderFactory): Provider<Boolean> =
providers.findProperty(CHECK_JDK_VENDOR).toBooleanProvider(true)
}

1
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/internal/configureJvmApplication.kt

@ -67,6 +67,7 @@ private fun JvmApplicationContext.configureCommonJvmDesktopTasks(): CommonJvmDes
taskNameObject = "runtime"
) {
jdkHome.set(app.javaHomeProvider)
checkJdkVendor.set(ComposeProperties.checkJdkVendor(project.providers))
jdkVersionProbeJar.from(
project.detachedComposeGradleDependency(
artifactId = "gradle-plugin-internal-jdk-version-probe"

56
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/desktop/application/tasks/AbstractCheckNativeDistributionRuntime.kt

@ -10,13 +10,19 @@ import org.gradle.api.file.RegularFile
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.*
import org.jetbrains.compose.desktop.application.internal.ComposeProperties
import org.jetbrains.compose.desktop.application.internal.JvmRuntimeProperties
import org.jetbrains.compose.desktop.application.internal.ExternalToolRunner
import org.jetbrains.compose.desktop.application.internal.JdkVersionProbe
import org.jetbrains.compose.desktop.tasks.AbstractComposeDesktopTask
import org.jetbrains.compose.internal.utils.OS
import org.jetbrains.compose.internal.utils.currentOS
import org.jetbrains.compose.internal.utils.executableName
import org.jetbrains.compose.internal.utils.ioFile
import org.jetbrains.compose.internal.utils.notNullProperty
import org.jetbrains.compose.desktop.application.internal.ExternalToolRunner
import org.jetbrains.compose.desktop.tasks.AbstractComposeDesktopTask
import java.io.ByteArrayInputStream
import java.io.File
import java.util.*
// __COMPOSE_NATIVE_DISTRIBUTIONS_MIN_JAVA_VERSION__
internal const val MIN_JAVA_RUNTIME_VERSION = 17
@ -30,6 +36,9 @@ abstract class AbstractCheckNativeDistributionRuntime : AbstractComposeDesktopTa
@get:InputDirectory
val jdkHome: Property<String> = objects.notNullProperty()
@get:Input
abstract val checkJdkVendor: Property<Boolean>
private val taskDir = project.layout.buildDirectory.dir("compose/tmp/$name")
@get:OutputFile
@ -69,18 +78,37 @@ abstract class AbstractCheckNativeDistributionRuntime : AbstractComposeDesktopTa
val jpackageExecutabke = jdkHome.getJdkTool("jpackage")
ensureToolsExist(javaExecutable, jlinkExecutable, jpackageExecutabke)
val jvmRuntimeVersionString = getJavaRuntimeVersion(javaExecutable)
val jdkRuntimeProperties = getJDKRuntimeProperties(javaExecutable)
val jvmRuntimeVersion = jvmRuntimeVersionString?.toIntOrNull()
?: jdkDistributionProbingError("JDK version '$jvmRuntimeVersionString' has unexpected format")
val jdkMajorVersionString = jdkRuntimeProperties.getProperty(JdkVersionProbe.JDK_MAJOR_VERSION_KEY)
val jdkMajorVersion = jdkMajorVersionString?.toIntOrNull()
?: jdkDistributionProbingError("JDK version '$jdkMajorVersionString' has unexpected format")
check(jvmRuntimeVersion >= MIN_JAVA_RUNTIME_VERSION) {
check(jdkMajorVersion >= MIN_JAVA_RUNTIME_VERSION) {
jdkDistributionProbingError(
"minimum required JDK version is '$MIN_JAVA_RUNTIME_VERSION', " +
"but actual version is '$jvmRuntimeVersion'"
"but actual version is '$jdkMajorVersion'"
)
}
if (checkJdkVendor.get()) {
val vendor = jdkRuntimeProperties.getProperty(JdkVersionProbe.JDK_VENDOR_KEY)
if (vendor == null) {
logger.warn("JDK vendor probe failed: $jdkHome")
} else {
if (currentOS == OS.MacOS && vendor.equals("homebrew", ignoreCase = true)) {
error(
"""
|Homebrew's JDK distribution may cause issues with packaging.
|See: https://github.com/JetBrains/compose-multiplatform/issues/3107
|Possible solutions:
|* Use other vendor's JDK distribution, such as Amazon Corretto;
|* To continue using Homebrew distribution for packaging on your own risk, add "${ComposeProperties.CHECK_JDK_VENDOR}=false" to your gradle.properties
""".trimMargin())
}
}
}
val modules = arrayListOf<String>()
runExternalTool(
tool = javaExecutable,
@ -96,17 +124,21 @@ abstract class AbstractCheckNativeDistributionRuntime : AbstractComposeDesktopTa
}
)
val properties = JvmRuntimeProperties(jvmRuntimeVersion, modules)
val properties = JvmRuntimeProperties(jdkMajorVersion, modules)
JvmRuntimeProperties.writeToFile(properties, javaRuntimePropertiesFile.ioFile)
}
private fun getJavaRuntimeVersion(javaExecutable: File): String? {
var javaRuntimeVersion: String? = null
private fun getJDKRuntimeProperties(javaExecutable: File): Properties {
val jdkProperties = Properties()
runExternalTool(
tool = javaExecutable,
args = listOf("-jar", jdkVersionProbeJar.files.single().absolutePath),
processStdout = { stdout -> javaRuntimeVersion = stdout.trim() }
processStdout = { stdout ->
ByteArrayInputStream(stdout.trim().toByteArray()).use {
jdkProperties.loadFromXML(it)
}
}
)
return javaRuntimeVersion
return jdkProperties
}
}

25
gradle-plugins/jdk-version-probe/src/main/java/org/jetbrains/compose/desktop/application/internal/JdkVersionProbe.java

@ -4,10 +4,22 @@
*/
package org.jetbrains.compose.desktop.application.internal;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Properties;
public class JdkVersionProbe {
public static void main(String[] args) {
public final static String JDK_MAJOR_VERSION_KEY = "jdk.major.version";
public final static String JDK_VENDOR_KEY = "jdk.vendor";
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
properties.setProperty(JDK_MAJOR_VERSION_KEY, getJDKMajorVersion());
properties.setProperty(JDK_VENDOR_KEY, System.getProperty("java.vendor"));
properties.storeToXML(System.out, null);
}
private static String getJDKMajorVersion() {
Class<Runtime> runtimeClass = Runtime.class;
try {
Method version = runtimeClass.getMethod("version");
@ -15,24 +27,19 @@ public class JdkVersionProbe {
Class<?> runtimeVerClass = runtimeVer.getClass();
try {
int feature = (int) runtimeVerClass.getMethod("feature").invoke(runtimeVer);
printVersionAndHalt((Integer.valueOf(feature)).toString());
return (Integer.valueOf(feature)).toString();
} catch (NoSuchMethodException e) {
int major = (int) runtimeVerClass.getMethod("major").invoke(runtimeVer);
printVersionAndHalt((Integer.valueOf(major)).toString());
return (Integer.valueOf(major)).toString();
}
} catch (Exception e) {
String javaVersion = System.getProperty("java.version");
String[] parts = javaVersion.split("\\.");
if (parts.length > 2 && "1".equalsIgnoreCase(parts[0])) {
printVersionAndHalt(parts[1]);
return parts[1];
} else {
throw new IllegalStateException("Could not determine JDK version from string: '" + javaVersion + "'");
}
}
}
private static void printVersionAndHalt(String version) {
System.out.println(version);
Runtime.getRuntime().exit(0);
}
}
Loading…
Cancel
Save