Alexey Tsvetkov
3 years ago
committed by
Alexey Tsvetkov
6 changed files with 188 additions and 7 deletions
@ -0,0 +1,29 @@ |
|||||||
|
package org.jetbrains.compose.desktop.application.internal |
||||||
|
|
||||||
|
import java.io.File |
||||||
|
import java.io.ObjectInputStream |
||||||
|
import java.io.ObjectOutputStream |
||||||
|
import java.io.Serializable |
||||||
|
|
||||||
|
internal data class JavaRuntimeProperties( |
||||||
|
val availableModules: List<String> |
||||||
|
) : Serializable { |
||||||
|
companion object { |
||||||
|
@Suppress("unused") |
||||||
|
private val serialVersionUid: Long = 0 |
||||||
|
|
||||||
|
fun writeToFile(properties: JavaRuntimeProperties, file: File) { |
||||||
|
file.parentFile.mkdirs() |
||||||
|
file.delete() |
||||||
|
file.createNewFile() |
||||||
|
ObjectOutputStream(file.outputStream().buffered()).use { oos -> |
||||||
|
oos.writeObject(properties) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fun readFromFile(file: File): JavaRuntimeProperties = |
||||||
|
ObjectInputStream(file.inputStream().buffered()).use { ois -> |
||||||
|
ois.readObject() as JavaRuntimeProperties |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,141 @@ |
|||||||
|
package org.jetbrains.compose.desktop.application.tasks |
||||||
|
|
||||||
|
import org.gradle.api.file.Directory |
||||||
|
import org.gradle.api.file.RegularFileProperty |
||||||
|
import org.gradle.api.provider.Property |
||||||
|
import org.gradle.api.provider.Provider |
||||||
|
import org.gradle.api.tasks.* |
||||||
|
import org.jetbrains.compose.desktop.application.internal.JavaRuntimeProperties |
||||||
|
import org.jetbrains.compose.desktop.application.internal.executableName |
||||||
|
import org.jetbrains.compose.desktop.application.internal.ioFile |
||||||
|
import org.jetbrains.compose.desktop.application.internal.notNullProperty |
||||||
|
import java.io.File |
||||||
|
|
||||||
|
// __COMPOSE_NATIVE_DISTRIBUTIONS_MIN_JAVA_VERSION__ |
||||||
|
private const val MIN_JAVA_RUNTIME_VERSION = 15 |
||||||
|
|
||||||
|
@CacheableTask |
||||||
|
abstract class AbstractCheckNativeDistributionRuntime : AbstractComposeDesktopTask() { |
||||||
|
@get:PathSensitive(PathSensitivity.ABSOLUTE) |
||||||
|
@get:Input |
||||||
|
val javaHome: Property<String> = objects.notNullProperty() |
||||||
|
|
||||||
|
@get:OutputFile |
||||||
|
val javaRuntimePropertiesFile: RegularFileProperty = objects.fileProperty() |
||||||
|
|
||||||
|
@get:LocalState |
||||||
|
val workingDir: Provider<Directory> = project.layout.buildDirectory.dir("compose/tmp/$name") |
||||||
|
|
||||||
|
@get:Internal |
||||||
|
private val javaExec: File |
||||||
|
get() = getTool("java") |
||||||
|
|
||||||
|
@get:Internal |
||||||
|
private val javacExec: File |
||||||
|
get() = getTool("javac") |
||||||
|
|
||||||
|
private fun getTool(toolName: String): File { |
||||||
|
val javaHomeBin = File(javaHome.get()).resolve("bin") |
||||||
|
val tool = javaHomeBin.resolve(executableName(toolName)) |
||||||
|
check(tool.exists()) { "Could not find $tool at: ${tool.absolutePath}}" } |
||||||
|
return tool |
||||||
|
} |
||||||
|
|
||||||
|
@TaskAction |
||||||
|
fun run() { |
||||||
|
val javaRuntimeVersion = try { |
||||||
|
getJavaRuntimeVersionUnsafe() |
||||||
|
} catch (e: Exception) { |
||||||
|
throw IllegalStateException( |
||||||
|
"Could not infer Java runtime version for Java home directory: ${javaHome.get()}", e |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
check((javaRuntimeVersion?.toIntOrNull() ?: -1) >= MIN_JAVA_RUNTIME_VERSION) { |
||||||
|
"""|Packaging native distributions requires JDK runtime version >= $MIN_JAVA_RUNTIME_VERSION |
||||||
|
|Actual version: '${javaRuntimeVersion ?: "<unknown>"}' |
||||||
|
|Java home: ${javaHome.get()} |
||||||
|
""".trimMargin() |
||||||
|
} |
||||||
|
|
||||||
|
val modules = arrayListOf<String>() |
||||||
|
runExternalTool( |
||||||
|
tool = javaExec, |
||||||
|
args = listOf("--list-modules"), |
||||||
|
forceLogToFile = true, |
||||||
|
processStdout = { stdout -> |
||||||
|
stdout.lineSequence().forEach { line -> |
||||||
|
val moduleName = line.trim().substringBefore("@") |
||||||
|
if (moduleName.isNotBlank()) { |
||||||
|
modules.add(moduleName) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
) |
||||||
|
|
||||||
|
val properties = JavaRuntimeProperties(modules) |
||||||
|
JavaRuntimeProperties.writeToFile(properties, javaRuntimePropertiesFile.ioFile) |
||||||
|
} |
||||||
|
|
||||||
|
private fun getJavaRuntimeVersionUnsafe(): String? { |
||||||
|
val workingDir = workingDir.ioFile |
||||||
|
fileOperations.delete(workingDir) |
||||||
|
fileOperations.mkdir(workingDir) |
||||||
|
|
||||||
|
val printJavaRuntimeClassName = "PrintJavaRuntimeVersion" |
||||||
|
val javaVersionPrefix = "Java runtime version = '" |
||||||
|
val javaVersionSuffix = "'" |
||||||
|
val printJavaRuntimeJava = workingDir.resolve("java/$printJavaRuntimeClassName.java").apply { |
||||||
|
parentFile.mkdirs() |
||||||
|
writeText(""" |
||||||
|
import java.lang.reflect.Method; |
||||||
|
|
||||||
|
public class $printJavaRuntimeClassName { |
||||||
|
public static void main(String[] args) { |
||||||
|
Class<Runtime> runtimeClass = Runtime.class; |
||||||
|
try { |
||||||
|
Method version = runtimeClass.getMethod("version"); |
||||||
|
Object runtimeVer = version.invoke(runtimeClass); |
||||||
|
Class<? extends Object> runtimeVerClass = runtimeVer.getClass(); |
||||||
|
try { |
||||||
|
int feature = (int) runtimeVerClass.getMethod("feature").invoke(runtimeVer); |
||||||
|
printVersionAndHalt((Integer.valueOf(feature)).toString()); |
||||||
|
} catch (NoSuchMethodException e) { |
||||||
|
int major = (int) runtimeVerClass.getMethod("major").invoke(runtimeVer); |
||||||
|
printVersionAndHalt((Integer.valueOf(major)).toString()); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
printVersionAndHalt(System.getProperty("java.version")); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static void printVersionAndHalt(String version) { |
||||||
|
System.out.println("$javaVersionPrefix" + version + "$javaVersionSuffix"); |
||||||
|
Runtime.getRuntime().exit(0); |
||||||
|
} |
||||||
|
} |
||||||
|
""".trimIndent()) |
||||||
|
} |
||||||
|
val classFilesDir = workingDir.resolve("out-classes") |
||||||
|
runExternalTool( |
||||||
|
tool = javacExec, |
||||||
|
args = listOf( |
||||||
|
"-source", "1.8", |
||||||
|
"-target", "1.8", |
||||||
|
"-d", classFilesDir.absolutePath, |
||||||
|
printJavaRuntimeJava.absolutePath |
||||||
|
) |
||||||
|
) |
||||||
|
|
||||||
|
var javaRuntimeVersion: String? = null |
||||||
|
runExternalTool( |
||||||
|
tool = javaExec, |
||||||
|
args = listOf("-cp", classFilesDir.absolutePath, printJavaRuntimeClassName), |
||||||
|
processStdout = { stdout -> |
||||||
|
val m = "$javaVersionPrefix(.+)$javaVersionSuffix".toRegex().find(stdout) |
||||||
|
javaRuntimeVersion = m?.groupValues?.get(1) |
||||||
|
} |
||||||
|
) |
||||||
|
return javaRuntimeVersion |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue