From ee0265013a45f3a25172e4e987ad59bb2b74e830 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Thu, 10 Oct 2024 16:31:07 +0200 Subject: [PATCH 01/31] Add IC for Compose Wasm --- build.gradle.kts | 47 ++++++- buildSrc/src/main/kotlin/CacheAttribute.kt | 10 ++ buildSrc/src/main/kotlin/lambda.kt | 1 + buildSrc/src/main/kotlin/properties.kt | 9 +- cache-maker/Dockerfile | 9 ++ cache-maker/build.gradle.kts | 100 ++++++++++++++ cache-maker/docker-build-incremental-cache.sh | 22 +++ cache-maker/src/main/kotlin/CacheBuilder.kt | 53 +++++++ cache-maker/src/main/kotlin/Main.kt | 15 ++ cache-maker/src/main/resources/File.kt | 61 ++++++++ .../server/common/components/CliUtils.kt | 82 +++++++++++ .../common/components}/KotlinEnvironment.kt | 4 +- .../KotlinEnvironmentConfiguration.kt | 12 +- .../src/main/kotlin/JvmIndexationBuilder.kt | 2 +- indexation/src/main/kotlin/Main.kt | 2 + .../src/main/kotlin/WebIndexationBuilder.kt | 2 +- settings.gradle.kts | 5 +- .../server/compiler/components/CliUtils.kt | 26 +--- .../compiler/components/ErrorAnalyzer.kt | 2 +- .../compiler/components/KotlinCompiler.kt | 4 +- .../compiler/components/KotlinEnvironment.kt | 10 +- .../components/KotlinToJSTranslator.kt | 130 +++++++++++------- .../compiler/components/WasmParameters.kt | 10 ++ .../configuration/ApplicationConfiguration.kt | 16 ++- .../compiler/server/model/bean/CachesFile.kt | 5 + .../server/service/KotlinProjectExecutor.kt | 12 +- 26 files changed, 551 insertions(+), 100 deletions(-) create mode 100644 buildSrc/src/main/kotlin/CacheAttribute.kt create mode 100644 buildSrc/src/main/kotlin/lambda.kt create mode 100644 cache-maker/Dockerfile create mode 100644 cache-maker/build.gradle.kts create mode 100755 cache-maker/docker-build-incremental-cache.sh create mode 100644 cache-maker/src/main/kotlin/CacheBuilder.kt create mode 100644 cache-maker/src/main/kotlin/Main.kt create mode 100644 cache-maker/src/main/resources/File.kt create mode 100644 common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt rename common/src/main/kotlin/{component => com/compiler/server/common/components}/KotlinEnvironment.kt (98%) rename {indexation/src/main/kotlin => common/src/main/kotlin/com/compiler/server/common/components}/KotlinEnvironmentConfiguration.kt (85%) create mode 100644 src/main/kotlin/com/compiler/server/compiler/components/WasmParameters.kt create mode 100644 src/main/kotlin/com/compiler/server/model/bean/CachesFile.kt diff --git a/build.gradle.kts b/build.gradle.kts index 315e08a4..b9a4627e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -41,9 +41,17 @@ allprojects { maven("https://maven.pkg.jetbrains.space/kotlin/p/wasm/experimental") maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") } - afterEvaluate { - dependencies { - dependencies { +} + +setOf( + rootProject, + project(":common"), + project(":executors"), + project(":indexation"), +).forEach { project -> + project.afterEvaluate { + project.dependencies { + project.dependencies { implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.15.2") implementation(libs.kotlin.idea) { isTransitive = false @@ -58,6 +66,31 @@ val resourceDependency: Configuration by configurations.creating { isCanBeConsumed = false } + +val kotlinComposeWasmIcLocalCache: Configuration by configurations.creating { + isTransitive = false + isCanBeResolved = true + isCanBeConsumed = false + attributes { + attribute( + CacheAttribute.cacheAttribute, + CacheAttribute.LOCAL + ) + } +} + +val kotlinComposeWasmIcLambdaCache: Configuration by configurations.creating { + isTransitive = false + isCanBeResolved = true + isCanBeConsumed = false + attributes { + attribute( + CacheAttribute.cacheAttribute, + CacheAttribute.LAMBDA + ) + } +} + dependencies { annotationProcessor("org.springframework:spring-context-indexer") implementation("com.google.code.gson:gson") @@ -85,6 +118,9 @@ dependencies { testImplementation(libs.kotlinx.coroutines.test) resourceDependency(libs.skiko.js.wasm.runtime) + + kotlinComposeWasmIcLocalCache(project(":cache-maker")) + kotlinComposeWasmIcLambdaCache(project(":cache-maker")) } fun buildPropertyFile() { @@ -109,6 +145,7 @@ fun generateProperties(prefix: String = "") = """ libraries.folder.compose-wasm=${prefix + libComposeWasm} libraries.folder.compose-wasm-compiler-plugins=${prefix + libComposeWasmCompilerPlugins} libraries.folder.compiler-plugins=${prefix + compilerPluginsForJVM} + caches.folder.compose-wasm=${prefix + cachesComposeWasm} spring.mvc.pathmatch.matching-strategy=ant_path_matcher server.compression.enabled=true server.compression.mime-types=application/json,text/javascript,application/wasm @@ -120,6 +157,7 @@ tasks.withType { } dependsOn(":executors:jar") dependsOn(":indexation:run") + dependsOn(kotlinComposeWasmIcLocalCache) buildPropertyFile() } println("Using Kotlin compiler ${libs.versions.kotlin.get()}") @@ -131,7 +169,7 @@ tasks.withType { val buildLambda by tasks.creating(Zip::class) { val propertyFile = propertyFile - val propertyFileContent = generateProperties("/var/task/") + val propertyFileContent = generateProperties(lambdaPrefix) from(tasks.compileKotlin) from(tasks.processResources) { @@ -152,6 +190,7 @@ val buildLambda by tasks.creating(Zip::class) { from(libJVMFolder) { into(libJVM) } from(compilerPluginsForJVMFolder) {into(compilerPluginsForJVM)} from(libComposeWasmCompilerPluginsFolder) { into(libComposeWasmCompilerPlugins) } + from(kotlinComposeWasmIcLambdaCache) into("lib") { from(configurations.compileClasspath) { exclude("tomcat-embed-*") } } diff --git a/buildSrc/src/main/kotlin/CacheAttribute.kt b/buildSrc/src/main/kotlin/CacheAttribute.kt new file mode 100644 index 00000000..f77af0c8 --- /dev/null +++ b/buildSrc/src/main/kotlin/CacheAttribute.kt @@ -0,0 +1,10 @@ +import org.gradle.api.attributes.Attribute + +enum class CacheAttribute { + LOCAL, + LAMBDA; + + companion object { + val cacheAttribute = Attribute.of("org.jetbrains.kotlin-compiler-server.cache", CacheAttribute::class.java) + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/lambda.kt b/buildSrc/src/main/kotlin/lambda.kt new file mode 100644 index 00000000..fbb23358 --- /dev/null +++ b/buildSrc/src/main/kotlin/lambda.kt @@ -0,0 +1 @@ +val lambdaPrefix = "/var/task/" \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/properties.kt b/buildSrc/src/main/kotlin/properties.kt index 36e5a253..6c641beb 100644 --- a/buildSrc/src/main/kotlin/properties.kt +++ b/buildSrc/src/main/kotlin/properties.kt @@ -1,6 +1,6 @@ +import org.gradle.accessors.dm.LibrariesForLibs import org.gradle.api.Project import org.gradle.kotlin.dsl.provideDelegate -import org.gradle.accessors.dm.LibrariesForLibs import org.gradle.kotlin.dsl.the val indexes: String by System.getProperties() @@ -25,6 +25,8 @@ val Project.libComposeWasm get() = "$kotlinVersion-compose-wasm" val Project.libComposeWasmCompilerPlugins get() = "$kotlinVersion-compose-wasm-compiler-plugins" +val Project.cachesComposeWasm + get() = "$kotlinVersion-caches-compose-wasm" val Project.libJVMFolder get() = rootProject.layout.projectDirectory.dir(libJVM) @@ -42,4 +44,7 @@ val Project.libComposeWasmFolder get() = rootProject.layout.projectDirectory.dir(libComposeWasm) val Project.libComposeWasmCompilerPluginsFolder - get() = rootProject.layout.projectDirectory.dir(libComposeWasmCompilerPlugins) \ No newline at end of file + get() = rootProject.layout.projectDirectory.dir(libComposeWasmCompilerPlugins) + +val Project.cachesComposeWasmFolder + get() = rootProject.layout.projectDirectory.dir(cachesComposeWasm) \ No newline at end of file diff --git a/cache-maker/Dockerfile b/cache-maker/Dockerfile new file mode 100644 index 00000000..b36ef2b7 --- /dev/null +++ b/cache-maker/Dockerfile @@ -0,0 +1,9 @@ +FROM amazoncorretto:17 + +ARG BASE_DIR + +RUN mkdir -p $BASE_DIR +WORKDIR $BASE_DIR +ADD . $BASE_DIR + +RUN ./gradlew :cache-maker:run diff --git a/cache-maker/build.gradle.kts b/cache-maker/build.gradle.kts new file mode 100644 index 00000000..189345ff --- /dev/null +++ b/cache-maker/build.gradle.kts @@ -0,0 +1,100 @@ +plugins { + kotlin("jvm") + application +} + +dependencies { + implementation(project(":common", configuration = "default")) +} + +application { + mainClass.set("cache.MainKt") +} + +tasks.withType { + dependsOn(":dependencies:copyDependencies") + dependsOn(":dependencies:copyWasmDependencies") + dependsOn(":dependencies:copyComposeWasmCompilerPlugins") + dependsOn(":dependencies:copyComposeWasmDependencies") + + val rootName = project.rootProject.projectDir.toString() + + val kotlinVersion = libs.versions.kotlin.get() + inputs.property("kotlinVersion", kotlinVersion) + + // Adding classpath directories as task input for up-to-date checks + inputs.dir(libWasmFolder) + inputs.dir(libComposeWasmFolder) + inputs.dir(libComposeWasmCompilerPluginsFolder) + + // Adding resulting index files as output for up-to-date checks + val composeCacheComposeWasm = "$rootName${File.separator}$cachesComposeWasm" + outputs.dir(cachesComposeWasmFolder) + + args = listOf( + kotlinVersion, + libJVMFolder.asFile.absolutePath, + composeCacheComposeWasm, + ) +} + +val outputLocalCacheDir = rootDir.resolve(cachesComposeWasm) +val buildCacheLocal by tasks.registering(Exec::class) { + workingDir = rootDir + executable = "${project.name}/docker-build-incremental-cache.sh" + outputs.dir(outputLocalCacheDir) + args = listOf( + rootDir.normalize().absolutePath, // baseDir + rootDir.normalize().absolutePath // targetDir + ) +} + +val outputLambdaCacheDir: Provider = layout.buildDirectory.dir("incremental-cache") +val buildCacheForLambda by tasks.registering(Exec::class) { + workingDir = rootDir + executable = "${project.name}/docker-build-incremental-cache.sh" + + val outputDir = outputLambdaCacheDir + + outputs.dir(outputDir.map { it.dir(cachesComposeWasm) }) + + doFirst { + args = listOf( + lambdaPrefix, // baseDir + outputDir.get().asFile.normalize().absolutePath, // targetDir + ) + } +} + +val kotlinComposeWasmIcLocalCache: Configuration by configurations.creating { + isTransitive = false + isCanBeResolved = false + isCanBeConsumed = true + attributes { + attribute( + CacheAttribute.cacheAttribute, + CacheAttribute.LOCAL + ) + } +} + +val kotlinComposeWasmIcLambdaCache: Configuration by configurations.creating { + isTransitive = false + isCanBeResolved = false + isCanBeConsumed = true + attributes { + attribute( + CacheAttribute.cacheAttribute, + CacheAttribute.LAMBDA + ) + } +} + +artifacts.add(kotlinComposeWasmIcLocalCache.name, outputLocalCacheDir) { + builtBy(buildCacheLocal) +} + +artifacts.add(kotlinComposeWasmIcLambdaCache.name, outputLambdaCacheDir) { + builtBy(buildCacheForLambda) +} + diff --git a/cache-maker/docker-build-incremental-cache.sh b/cache-maker/docker-build-incremental-cache.sh new file mode 100755 index 00000000..0679936b --- /dev/null +++ b/cache-maker/docker-build-incremental-cache.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +kotlinVersion=$(awk '{ if ($1 == "kotlin") { gsub(/"/, "", $2); print $2; } }' FS=' = ' ./gradle/libs.versions.toml) + +baseDir=$1 +targetDir=$2 + +echo "Kotlin Version for the docker: $kotlinVersion" +echo "Base directory: $baseDir" +echo "Target directory: $targetDir" + +image_tag=my-image-name:$(date +%s) + +docker build . --file cache-maker/Dockerfile --tag $image_tag --build-arg BASE_DIR=$baseDir + +container=$(docker create $image_tag) + +docker cp $container:$baseDir/$kotlinVersion-caches-compose-wasm $targetDir + +docker start $container +docker stop $container +docker remove $container \ No newline at end of file diff --git a/cache-maker/src/main/kotlin/CacheBuilder.kt b/cache-maker/src/main/kotlin/CacheBuilder.kt new file mode 100644 index 00000000..8ddf1525 --- /dev/null +++ b/cache-maker/src/main/kotlin/CacheBuilder.kt @@ -0,0 +1,53 @@ +import com.compiler.server.common.components.KotlinEnvironment +import com.compiler.server.common.components.compileWasmArgs +import com.compiler.server.common.components.linkWasmArgs +import com.compiler.server.common.components.usingTempDirectory +import org.jetbrains.kotlin.cli.common.CLICompiler.Companion.doMainNoExit +import org.jetbrains.kotlin.cli.js.K2JSCompiler +import java.io.File +import kotlin.io.path.div + + +class CacheBuilder( + private val kotlinEnvironment: KotlinEnvironment, +) { + fun compileCache(outputForCache: String) { + val moduleName = "playground" + usingTempDirectory { outputDir -> + val resource = this::class.java.classLoader.getResource("File.kt")!!.path + + val klibPath = (outputDir / "klib").toFile().normalize().absolutePath + + val k2JSCompiler = K2JSCompiler() + + doMainNoExit( + k2JSCompiler, + compileWasmArgs( + moduleName, + listOf(resource), + klibPath, + kotlinEnvironment.COMPOSE_WASM_COMPILER_PLUGINS, + kotlinEnvironment.composeWasmCompilerPluginOptions, + kotlinEnvironment.COMPOSE_WASM_LIBRARIES + ).toTypedArray() + ) + + usingTempDirectory { tmpDir -> + val cachesDir = tmpDir.resolve("caches").normalize() + doMainNoExit( + k2JSCompiler, + linkWasmArgs( + moduleName, + klibPath, + kotlinEnvironment.COMPOSE_WASM_LIBRARIES, + cachesDir.normalize(), + outputDir, + false + ).toTypedArray() + ) + + cachesDir.toFile().copyRecursively(File(outputForCache), overwrite = true) + } + } + } +} \ No newline at end of file diff --git a/cache-maker/src/main/kotlin/Main.kt b/cache-maker/src/main/kotlin/Main.kt new file mode 100644 index 00000000..2c35259c --- /dev/null +++ b/cache-maker/src/main/kotlin/Main.kt @@ -0,0 +1,15 @@ +package cache + +import CacheBuilder +import com.compiler.server.common.components.KotlinEnvironmentConfiguration + +fun main(args: Array) { + val version = args[0] + val directory = args[1] + val outputPathCacheComposeWasm = args[2] + val kotlinEnvironment = KotlinEnvironmentConfiguration(version, directory).kotlinEnvironment + + CacheBuilder( + kotlinEnvironment = kotlinEnvironment + ).compileCache(outputPathCacheComposeWasm) +} diff --git a/cache-maker/src/main/resources/File.kt b/cache-maker/src/main/resources/File.kt new file mode 100644 index 00000000..7d82015a --- /dev/null +++ b/cache-maker/src/main/resources/File.kt @@ -0,0 +1,61 @@ +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.Button +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.window.ComposeViewport +import kotlinx.browser.document + +//sampleStart +@OptIn(ExperimentalComposeUiApi::class) +fun main() { + ComposeViewport(document.body!!) { + App() + } +} + +@Composable +fun App() { + MaterialTheme { + var greetingText by remember { mutableStateOf("Hello World!") } + var showImage by remember { mutableStateOf(false) } + var counter by remember { mutableStateOf(0) } + Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { + Button(onClick = { + counter++ + greetingText = "Compose: ${Greeting().greet()}" + showImage = !showImage + }) { + Text(greetingText) + } + AnimatedVisibility(showImage) { + Text(counter.toString()) + } + } + } +} + +private val platform = object : Platform { + + override val name: String + get() = "Web with Kotlin/Wasm" +} + +fun getPlatform(): Platform = platform + +class Greeting { + private val platform = getPlatform() + + fun greet(): String { + return "Hello, ${platform.name}!" + } +} + +interface Platform { + val name: String +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt b/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt new file mode 100644 index 00000000..44c74a54 --- /dev/null +++ b/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt @@ -0,0 +1,82 @@ +package com.compiler.server.common.components + +import java.io.File +import java.nio.file.Path +import java.util.* +import kotlin.io.path.* + +@OptIn(ExperimentalPathApi::class) +fun usingTempDirectory(action: (path: Path) -> T): T { + val path = getTempDirectory() + path.createDirectories() + return try { + action(path) + } finally { + path.deleteRecursively() + } +} + +private fun getTempDirectory(): Path { + val dir = System.getProperty("java.io.tmpdir") + val sessionId = UUID.randomUUID().toString().replace("-", "") + return File(dir).canonicalFile.resolve(sessionId).toPath() +} + +fun compileWasmArgs( + moduleName: String, + filePaths: List, + klibPath: String, + compilerPlugins: List, + compilerPluginOptions: List, + dependencies: List, +): List { + val compilerPluginsArgs: List = compilerPlugins + .takeIf { it.isNotEmpty() } + ?.let { plugins -> + plugins.map { + "-Xplugin=$it" + } + compilerPluginOptions.map { + "-P=$it" + } + } ?: emptyList() + val additionalCompilerArgumentsForKLib: List = listOf( + "-Xreport-all-warnings", + "-Wextra", + "-Xwasm", + "-Xir-produce-klib-dir", + "-libraries=${dependencies.joinToString(PATH_SEPARATOR)}", + "-ir-output-dir=$klibPath", + "-ir-output-name=$moduleName", + ) + compilerPluginsArgs + + return filePaths + additionalCompilerArgumentsForKLib +} + +fun linkWasmArgs( + moduleName: String, + klibPath: String, + dependencies: List, + icDir: Path?, + outputDir: Path, + debugInfo: Boolean, +): List { + return mutableListOf( + "-Xreport-all-warnings", + "-Wextra", + "-Xwasm", + "-Xir-produce-js", + "-Xinclude=$klibPath", + "-libraries=${dependencies.joinToString(PATH_SEPARATOR)}", + "-ir-output-dir=${(outputDir / "wasm").toFile().canonicalPath}", + "-ir-output-name=$moduleName",).also { + if (debugInfo) it.add("-Xwasm-generate-wat") + + if (icDir != null) { + it.add("-Xcache-directory=${icDir.normalize().absolutePathString()}") + } else { + it.add("-Xir-dce") + } + } +} + +val PATH_SEPARATOR: String = File.pathSeparator diff --git a/common/src/main/kotlin/component/KotlinEnvironment.kt b/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironment.kt similarity index 98% rename from common/src/main/kotlin/component/KotlinEnvironment.kt rename to common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironment.kt index b3a995b2..60c8d3bc 100644 --- a/common/src/main/kotlin/component/KotlinEnvironment.kt +++ b/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironment.kt @@ -1,6 +1,7 @@ -package component +package com.compiler.server.common.components import com.intellij.openapi.util.Disposer +import component.CompilerPluginOption import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments import org.jetbrains.kotlin.cli.common.messages.MessageCollector @@ -32,6 +33,7 @@ class KotlinEnvironment( composeWasmCompilerPlugins: List, val compilerPlugins: List = emptyList(), composeWasmCompilerPluginsOptions: List, + val composeWasmCache: File, ) { companion object { /** diff --git a/indexation/src/main/kotlin/KotlinEnvironmentConfiguration.kt b/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironmentConfiguration.kt similarity index 85% rename from indexation/src/main/kotlin/KotlinEnvironmentConfiguration.kt rename to common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironmentConfiguration.kt index 14ce8819..43110fce 100644 --- a/indexation/src/main/kotlin/KotlinEnvironmentConfiguration.kt +++ b/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironmentConfiguration.kt @@ -1,7 +1,6 @@ -package indexation +package com.compiler.server.common.components import component.CompilerPluginOption -import component.KotlinEnvironment import java.io.File class KotlinEnvironmentConfiguration( @@ -14,6 +13,7 @@ class KotlinEnvironmentConfiguration( val wasmFile = File("$fileName-wasm") val composeWasmFile = File("$fileName-compose-wasm") val composeWasmCompilerPluginsFile = File("$fileName-compose-wasm-compiler-plugins") + val composeWasmCachesFile = File("$fileName-caches-compose-wasm") val classPath = listOfNotNull(jvmFile) .flatMap { @@ -39,12 +39,8 @@ class KotlinEnvironmentConfiguration( "generateDecoys", "false" ), - CompilerPluginOption( - "androidx.compose.compiler.plugins.kotlin", - "suppressKotlinVersionCompatibilityCheck", - version - ), - ) + ), + composeWasmCachesFile ) } } diff --git a/indexation/src/main/kotlin/JvmIndexationBuilder.kt b/indexation/src/main/kotlin/JvmIndexationBuilder.kt index 153a89ac..dc603946 100644 --- a/indexation/src/main/kotlin/JvmIndexationBuilder.kt +++ b/indexation/src/main/kotlin/JvmIndexationBuilder.kt @@ -1,7 +1,7 @@ package indexation +import com.compiler.server.common.components.KotlinEnvironment import model.ImportInfo -import component.KotlinEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.CliBindingTrace import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.container.getService diff --git a/indexation/src/main/kotlin/Main.kt b/indexation/src/main/kotlin/Main.kt index 3e3efa90..f0bb1d7f 100644 --- a/indexation/src/main/kotlin/Main.kt +++ b/indexation/src/main/kotlin/Main.kt @@ -1,5 +1,7 @@ package indexation +import com.compiler.server.common.components.KotlinEnvironmentConfiguration + /** * First argument is path to folder with jars * Second argument is path to output file for jvm indexes diff --git a/indexation/src/main/kotlin/WebIndexationBuilder.kt b/indexation/src/main/kotlin/WebIndexationBuilder.kt index a0b409cf..77be751f 100644 --- a/indexation/src/main/kotlin/WebIndexationBuilder.kt +++ b/indexation/src/main/kotlin/WebIndexationBuilder.kt @@ -1,7 +1,7 @@ package indexation +import com.compiler.server.common.components.KotlinEnvironment import model.ImportInfo -import component.KotlinEnvironment import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser import org.jetbrains.kotlin.config.CompilerConfiguration diff --git a/settings.gradle.kts b/settings.gradle.kts index 60d3b651..e01e6e5e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,6 +5,8 @@ pluginManagement { gradlePluginPortal() mavenCentral() maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") + + maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev") } } plugins { @@ -16,4 +18,5 @@ plugins { include(":executors") include(":indexation") include(":common") -include(":dependencies") \ No newline at end of file +include(":dependencies") +include(":cache-maker") \ No newline at end of file diff --git a/src/main/kotlin/com/compiler/server/compiler/components/CliUtils.kt b/src/main/kotlin/com/compiler/server/compiler/components/CliUtils.kt index 7edd8710..6b3d7b04 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/CliUtils.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/CliUtils.kt @@ -12,10 +12,11 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.psi.KtFile -import java.io.File import java.nio.file.Path -import java.util.* -import kotlin.io.path.* +import kotlin.io.path.Path +import kotlin.io.path.div +import kotlin.io.path.pathString +import kotlin.io.path.writeText private fun minusOne(value: Int) = if (value > 0) value - 1 else value @@ -111,23 +112,6 @@ fun CLICompiler<*>.tryCompilation(inputDirectory: Path, inputFiles: List usingTempDirectory(action: (path: Path) -> T): T { - val path = getTempDirectory() - path.createDirectories() - return try { - action(path) - } finally { - path.deleteRecursively() - } -} - -private fun getTempDirectory(): Path { - val dir = System.getProperty("java.io.tmpdir") - val sessionId = UUID.randomUUID().toString().replace("-", "") - return File(dir).canonicalFile.resolve(sessionId).toPath() -} - fun List.writeToIoFiles(inputDir: Path): List { val ioFiles = map { inputDir / it.name } for ((ioFile, ktFile) in ioFiles zip this) { @@ -135,5 +119,3 @@ fun List.writeToIoFiles(inputDir: Path): List { } return ioFiles } - -val PATH_SEPARATOR: String = File.pathSeparator diff --git a/src/main/kotlin/com/compiler/server/compiler/components/ErrorAnalyzer.kt b/src/main/kotlin/com/compiler/server/compiler/components/ErrorAnalyzer.kt index 8591b19e..cae2b53a 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/ErrorAnalyzer.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/ErrorAnalyzer.kt @@ -1,12 +1,12 @@ package com.compiler.server.compiler.components +import com.compiler.server.common.components.KotlinEnvironment import com.compiler.server.model.* import com.intellij.openapi.util.Pair import com.intellij.psi.PsiElement import com.intellij.psi.PsiElementVisitor import com.intellij.psi.PsiErrorElement import com.intellij.psi.PsiFile -import component.KotlinEnvironment import model.Completion import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport diff --git a/src/main/kotlin/com/compiler/server/compiler/components/KotlinCompiler.kt b/src/main/kotlin/com/compiler/server/compiler/components/KotlinCompiler.kt index 47c8e66b..f2a76d0b 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/KotlinCompiler.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/KotlinCompiler.kt @@ -1,12 +1,14 @@ package com.compiler.server.compiler.components +import com.compiler.server.common.components.KotlinEnvironment +import com.compiler.server.common.components.PATH_SEPARATOR +import com.compiler.server.common.components.usingTempDirectory import com.compiler.server.executor.CommandLineArgument import com.compiler.server.executor.JavaExecutor import com.compiler.server.model.JvmExecutionResult import com.compiler.server.model.OutputDirectory import com.compiler.server.model.bean.LibrariesFile import com.compiler.server.model.toExceptionDescriptor -import component.KotlinEnvironment import executors.JUnitExecutors import executors.JavaRunnerExecutor import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler diff --git a/src/main/kotlin/com/compiler/server/compiler/components/KotlinEnvironment.kt b/src/main/kotlin/com/compiler/server/compiler/components/KotlinEnvironment.kt index 4858bb6c..6ef414ec 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/KotlinEnvironment.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/KotlinEnvironment.kt @@ -1,15 +1,16 @@ package com.compiler.server.compiler.components +import com.compiler.server.common.components.KotlinEnvironment +import com.compiler.server.model.bean.CachesFile import com.compiler.server.model.bean.LibrariesFile -import com.compiler.server.model.bean.VersionInfo import component.CompilerPluginOption -import component.KotlinEnvironment import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration class KotlinEnvironmentConfiguration( - val librariesFile: LibrariesFile + val librariesFile: LibrariesFile, + val cachesFile: CachesFile, ) { @Bean fun kotlinEnvironment(): KotlinEnvironment { @@ -39,7 +40,8 @@ class KotlinEnvironmentConfiguration( "generateDecoys", "false" ), - ) + ), + cachesFile.composeWasm ) } } diff --git a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt index d90c983a..43ca3939 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt @@ -1,14 +1,17 @@ package com.compiler.server.compiler.components +import com.compiler.server.common.components.* import com.compiler.server.model.* import com.fasterxml.jackson.databind.ObjectMapper -import component.KotlinEnvironment import org.jetbrains.kotlin.cli.js.K2JSCompiler import org.jetbrains.kotlin.psi.KtFile import org.springframework.stereotype.Service +import java.io.File +import java.nio.file.Path import kotlin.io.path.div import kotlin.io.path.readBytes import kotlin.io.path.readText +import kotlin.time.measureTime @Service class KotlinToJSTranslator( @@ -47,28 +50,38 @@ class KotlinToJSTranslator( files: List, debugInfo: Boolean, projectType: ProjectType, - translate: (List, List, List, List, Boolean) -> CompilationResult + translate: ( + List, + List, + List, + List, + File?, + Boolean, + ) -> CompilationResult ): TranslationResultWithJsCode { return try { - val (dependencies, compilerPlugins, compilerPluginOptions) = when (projectType) { - ProjectType.WASM -> listOf( + val parameters: WasmParameters = when (projectType) { + ProjectType.WASM -> WasmParameters( kotlinEnvironment.WASM_LIBRARIES, emptyList(), - emptyList() + emptyList(), + null ) - ProjectType.COMPOSE_WASM -> listOf( + ProjectType.COMPOSE_WASM -> WasmParameters( kotlinEnvironment.COMPOSE_WASM_LIBRARIES, kotlinEnvironment.COMPOSE_WASM_COMPILER_PLUGINS, - kotlinEnvironment.composeWasmCompilerPluginOptions + kotlinEnvironment.composeWasmCompilerPluginOptions, + kotlinEnvironment.composeWasmCache, ) else -> throw IllegalStateException("Wasm should have wasm or compose-wasm project type") } val compilationResult = translate( files, - dependencies, - compilerPlugins, - compilerPluginOptions, - debugInfo + parameters.dependencies, + parameters.plugins, + parameters.pluginOptions, + parameters.cacheDir, + debugInfo, ) val wasmCompilationOutput = when (compilationResult) { is Compiled -> compilationResult.result @@ -137,6 +150,7 @@ class KotlinToJSTranslator( dependencies: List, compilerPlugins: List, compilerPluginOptions: List, + cacheDir: File?, debugInfo: Boolean, ): CompilationResult = usingTempDirectory { inputDir -> @@ -146,47 +160,63 @@ class KotlinToJSTranslator( val k2JSCompiler = K2JSCompiler() val filePaths = ioFiles.map { it.toFile().canonicalPath } val klibPath = (outputDir / "klib").toFile().canonicalPath - val compilerPluginsArgs: List = compilerPlugins - .takeIf { it.isNotEmpty() } - ?.let { plugins -> - plugins.map { - "-Xplugin=$it" - } + compilerPluginOptions.map { - "-P=$it" - } - } ?: emptyList() - val additionalCompilerArgumentsForKLib: List = listOf( - "-Xreport-all-warnings", - "-Wextra", - "-Xwasm", - "-Xir-produce-klib-dir", - "-libraries=${dependencies.joinToString(PATH_SEPARATOR)}", - "-ir-output-dir=$klibPath", - "-ir-output-name=$moduleName", - ) + compilerPluginsArgs - k2JSCompiler.tryCompilation(inputDir, ioFiles, filePaths + additionalCompilerArgumentsForKLib) - .flatMap { - k2JSCompiler.tryCompilation(inputDir, ioFiles, mutableListOf( - "-Xreport-all-warnings", - "-Wextra", - "-Xwasm", - "-Xir-produce-js", - "-Xir-dce", - "-Xinclude=$klibPath", - "-libraries=${dependencies.joinToString(PATH_SEPARATOR)}", - "-ir-output-dir=${(outputDir / "wasm").toFile().canonicalPath}", - "-ir-output-name=$moduleName", - ).also { if (debugInfo) it.add("-Xwasm-generate-wat") }) - } - .map { - WasmTranslationSuccessfulOutput( - jsCode = (outputDir / "wasm" / "$moduleName.uninstantiated.mjs").readText(), - jsInstantiated = (outputDir / "wasm" / "$moduleName.mjs").readText(), - wasm = (outputDir / "wasm" / "$moduleName.wasm").readBytes(), - wat = if (debugInfo) (outputDir / "wasm" / "$moduleName.wat").readText() else null, + val compileAction: (icDir: Path?) -> CompilationResult = { icDir -> + k2JSCompiler.tryCompilation( + inputDir, + ioFiles, + compileWasmArgs( + moduleName, + filePaths, + klibPath, + compilerPlugins, + compilerPluginOptions, + dependencies ) - } + ) + .flatMap { + k2JSCompiler.tryCompilation( + inputDir, ioFiles, + linkWasmArgs( + moduleName, + klibPath, + dependencies, + icDir, + outputDir, + debugInfo + ) + ) + } + .map { + WasmTranslationSuccessfulOutput( + jsCode = (outputDir / "wasm" / "$moduleName.uninstantiated.mjs").readText(), + jsInstantiated = (outputDir / "wasm" / "$moduleName.mjs").readText(), + wasm = (outputDir / "wasm" / "$moduleName.wasm").readBytes(), + wat = if (debugInfo) (outputDir / "wasm" / "$moduleName.wat").readText() else null, + ) + } + } + + val a: CompilationResult + + val time = measureTime { + a = cacheDir?.let { dir -> + usingTempDirectory { tmpDir -> + val cachesDir = tmpDir.resolve("caches").normalize() + val originalCachesDirExists = dir.exists() + if (originalCachesDirExists) { + dir.copyRecursively(cachesDir.toFile()) + } + val result = compileAction(cachesDir) + if (!originalCachesDirExists) { + cachesDir.toFile().copyRecursively(dir) + } + result + } + } ?: compileAction(null) + } + println("TIME: $time") + a } } } diff --git a/src/main/kotlin/com/compiler/server/compiler/components/WasmParameters.kt b/src/main/kotlin/com/compiler/server/compiler/components/WasmParameters.kt new file mode 100644 index 00000000..2cf0f2fa --- /dev/null +++ b/src/main/kotlin/com/compiler/server/compiler/components/WasmParameters.kt @@ -0,0 +1,10 @@ +package com.compiler.server.compiler.components + +import java.io.File + +data class WasmParameters( + val dependencies: List, + val plugins: List, + val pluginOptions: List, + val cacheDir: File? +) \ No newline at end of file diff --git a/src/main/kotlin/com/compiler/server/configuration/ApplicationConfiguration.kt b/src/main/kotlin/com/compiler/server/configuration/ApplicationConfiguration.kt index 0a342669..9727c7ed 100644 --- a/src/main/kotlin/com/compiler/server/configuration/ApplicationConfiguration.kt +++ b/src/main/kotlin/com/compiler/server/configuration/ApplicationConfiguration.kt @@ -1,5 +1,6 @@ package com.compiler.server.configuration +import com.compiler.server.model.bean.CachesFile import com.compiler.server.model.bean.LibrariesFile import com.compiler.server.model.bean.VersionInfo import org.springframework.beans.factory.annotation.Value @@ -12,10 +13,11 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer import java.io.File @Configuration -@EnableConfigurationProperties(value = [LibrariesFolderProperties::class]) +@EnableConfigurationProperties(value = [LibrariesFolderProperties::class, CachesFolderProperties::class]) class ApplicationConfiguration( @Value("\${kotlin.version}") private val version: String, - private val librariesFolderProperties: LibrariesFolderProperties + private val librariesFolderProperties: LibrariesFolderProperties, + private val cachesFolderProperties: CachesFolderProperties, ) : WebMvcConfigurer { override fun addFormatters(registry: FormatterRegistry) { registry.addConverter(ProjectConverter()) @@ -36,6 +38,11 @@ class ApplicationConfiguration( File(librariesFolderProperties.composeWasmCompilerPlugins), File(librariesFolderProperties.compilerPlugins) ) + + @Bean + fun cachesFiles() = CachesFile( + File(cachesFolderProperties.composeWasm) + ) } @ConfigurationProperties(prefix = "libraries.folder") @@ -46,4 +53,9 @@ class LibrariesFolderProperties { lateinit var composeWasm: String lateinit var composeWasmCompilerPlugins: String lateinit var compilerPlugins: String +} + +@ConfigurationProperties(prefix = "caches.folder") +class CachesFolderProperties { + lateinit var composeWasm: String } \ No newline at end of file diff --git a/src/main/kotlin/com/compiler/server/model/bean/CachesFile.kt b/src/main/kotlin/com/compiler/server/model/bean/CachesFile.kt new file mode 100644 index 00000000..83f11d07 --- /dev/null +++ b/src/main/kotlin/com/compiler/server/model/bean/CachesFile.kt @@ -0,0 +1,5 @@ +package com.compiler.server.model.bean + +import java.io.File + +class CachesFile(val composeWasm: File) \ No newline at end of file diff --git a/src/main/kotlin/com/compiler/server/service/KotlinProjectExecutor.kt b/src/main/kotlin/com/compiler/server/service/KotlinProjectExecutor.kt index d0177c4f..f331563d 100644 --- a/src/main/kotlin/com/compiler/server/service/KotlinProjectExecutor.kt +++ b/src/main/kotlin/com/compiler/server/service/KotlinProjectExecutor.kt @@ -1,15 +1,16 @@ package com.compiler.server.service +import com.compiler.server.common.components.KotlinEnvironment import com.compiler.server.compiler.KotlinFile import com.compiler.server.compiler.components.* import com.compiler.server.model.* import com.compiler.server.model.bean.VersionInfo -import component.KotlinEnvironment import model.Completion import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.psi.KtFile import org.slf4j.LoggerFactory import org.springframework.stereotype.Component +import java.io.File @Component class KotlinProjectExecutor( @@ -101,7 +102,14 @@ class KotlinProjectExecutor( private fun convertWasmWithConverter( project: Project, debugInfo: Boolean, - converter: (List, List, List, List, Boolean) -> CompilationResult + converter: ( + List, + List, + List, + List, + File?, + Boolean, + ) -> CompilationResult ): TranslationResultWithJsCode { return kotlinEnvironment.environment { environment -> val files = getFilesFrom(project, environment).map { it.kotlinFile } From ebc3a6aa4ef47b0b6acb7c6cb94b97ab4a8cea5c Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 5 Nov 2024 14:17:58 +0100 Subject: [PATCH 02/31] No need docker in local case --- cache-maker/Dockerfile | 21 +++++++++++++++++++ cache-maker/build.gradle.kts | 13 ++---------- cache-maker/docker-build-incremental-cache.sh | 2 +- gradle/libs.versions.toml | 2 +- .../components/KotlinToJSTranslator.kt | 9 ++------ 5 files changed, 27 insertions(+), 20 deletions(-) diff --git a/cache-maker/Dockerfile b/cache-maker/Dockerfile index b36ef2b7..abbb2bd2 100644 --- a/cache-maker/Dockerfile +++ b/cache-maker/Dockerfile @@ -1,9 +1,30 @@ FROM amazoncorretto:17 ARG BASE_DIR +ARG KOTLIN_VERSION + +RUN if [ -z "$KOTLIN_VERSION" ]; then \ + echo "Error: KOTLIN_VERSION argument is not set. Use docker-build-incremental-cache.sh to build the image." >&2; \ + exit 1; \ + fi + +ENV KOTLIN_LIB=$KOTLIN_VERSION +ENV KOTLIN_LIB_JS=${KOTLIN_VERSION}-js +ENV KOTLIN_LIB_WASM=${KOTLIN_VERSION}-wasm +ENV KOTLIN_LIB_COMPOSE_WASM=${KOTLIN_VERSION}-compose-wasm +ENV KOTLIN_COMPOSE_WASM_COMPILER_PLUGINS=${KOTLIN_VERSION}-compose-wasm-compiler-plugins +ENV KOTLIN_CACHES_COMPOSE_WASM=${KOTLIN_VERSION}-caches-compose-wasm RUN mkdir -p $BASE_DIR WORKDIR $BASE_DIR ADD . $BASE_DIR +RUN rm -rf $KOTLIN_LIB +RUN rm -rf $KOTLIN_LIB_JS +RUN rm -rf $KOTLIN_LIB_WASM +RUN rm -rf $KOTLIN_LIB_COMPOSE_WASM +RUN rm -rf $KOTLIN_COMPOSE_WASM_COMPILER_PLUGINS +RUN rm -rf $KOTLIN_CACHES_COMPOSE_WASM +RUN ./gradlew clean + RUN ./gradlew :cache-maker:run diff --git a/cache-maker/build.gradle.kts b/cache-maker/build.gradle.kts index 189345ff..9c97ff66 100644 --- a/cache-maker/build.gradle.kts +++ b/cache-maker/build.gradle.kts @@ -11,7 +11,7 @@ application { mainClass.set("cache.MainKt") } -tasks.withType { +val runTask = tasks.named("run") { dependsOn(":dependencies:copyDependencies") dependsOn(":dependencies:copyWasmDependencies") dependsOn(":dependencies:copyComposeWasmCompilerPlugins") @@ -39,15 +39,6 @@ tasks.withType { } val outputLocalCacheDir = rootDir.resolve(cachesComposeWasm) -val buildCacheLocal by tasks.registering(Exec::class) { - workingDir = rootDir - executable = "${project.name}/docker-build-incremental-cache.sh" - outputs.dir(outputLocalCacheDir) - args = listOf( - rootDir.normalize().absolutePath, // baseDir - rootDir.normalize().absolutePath // targetDir - ) -} val outputLambdaCacheDir: Provider = layout.buildDirectory.dir("incremental-cache") val buildCacheForLambda by tasks.registering(Exec::class) { @@ -91,7 +82,7 @@ val kotlinComposeWasmIcLambdaCache: Configuration by configurations.creating { } artifacts.add(kotlinComposeWasmIcLocalCache.name, outputLocalCacheDir) { - builtBy(buildCacheLocal) + builtBy(runTask) } artifacts.add(kotlinComposeWasmIcLambdaCache.name, outputLambdaCacheDir) { diff --git a/cache-maker/docker-build-incremental-cache.sh b/cache-maker/docker-build-incremental-cache.sh index 0679936b..e04ec05c 100755 --- a/cache-maker/docker-build-incremental-cache.sh +++ b/cache-maker/docker-build-incremental-cache.sh @@ -11,7 +11,7 @@ echo "Target directory: $targetDir" image_tag=my-image-name:$(date +%s) -docker build . --file cache-maker/Dockerfile --tag $image_tag --build-arg BASE_DIR=$baseDir +docker build . --file cache-maker/Dockerfile --tag $image_tag --build-arg BASE_DIR=$baseDir --build-arg KOTLIN_VERSION=$kotlinVersion container=$(docker create $image_tag) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ac9ca3a1..afb982c7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "2.1.0" +kotlin = "2.1.20-dev-5634" kotlinIdeVersion = "1.9.20-506" kotlinIdeVersionWithSuffix = "231-1.9.20-506-IJ8109.175" spring-boot = "2.7.10" diff --git a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt index 43ca3939..4ccc9f58 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt @@ -203,15 +203,10 @@ class KotlinToJSTranslator( a = cacheDir?.let { dir -> usingTempDirectory { tmpDir -> val cachesDir = tmpDir.resolve("caches").normalize() - val originalCachesDirExists = dir.exists() - if (originalCachesDirExists) { + if (dir.exists()) { dir.copyRecursively(cachesDir.toFile()) } - val result = compileAction(cachesDir) - if (!originalCachesDirExists) { - cachesDir.toFile().copyRecursively(dir) - } - result + compileAction(cachesDir) } } ?: compileAction(null) } From daaef810d51514cbe473d74d1ab39d5cfacb8e92 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 5 Nov 2024 16:23:59 +0100 Subject: [PATCH 03/31] Remove image after cache build --- cache-maker/docker-build-incremental-cache.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cache-maker/docker-build-incremental-cache.sh b/cache-maker/docker-build-incremental-cache.sh index e04ec05c..2994b49a 100755 --- a/cache-maker/docker-build-incremental-cache.sh +++ b/cache-maker/docker-build-incremental-cache.sh @@ -19,4 +19,6 @@ docker cp $container:$baseDir/$kotlinVersion-caches-compose-wasm $targetDir docker start $container docker stop $container -docker remove $container \ No newline at end of file +docker remove $container + +docker rmi $image_tag \ No newline at end of file From fdbe7e6bdbbe1ff10246df7ebebfbe114ca9f4c5 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 5 Nov 2024 18:50:11 +0100 Subject: [PATCH 04/31] Use lazy argumentProviders instead of args --- cache-maker/build.gradle.kts | 19 ++++++------------- .../compiler/server/cache}/CacheBuilder.kt | 2 ++ .../{ => com/compiler/server/cache}/Main.kt | 3 +-- 3 files changed, 9 insertions(+), 15 deletions(-) rename cache-maker/src/main/kotlin/{ => com/compiler/server/cache}/CacheBuilder.kt (97%) rename cache-maker/src/main/kotlin/{ => com/compiler/server/cache}/Main.kt (92%) diff --git a/cache-maker/build.gradle.kts b/cache-maker/build.gradle.kts index 9c97ff66..79076ea1 100644 --- a/cache-maker/build.gradle.kts +++ b/cache-maker/build.gradle.kts @@ -8,7 +8,7 @@ dependencies { } application { - mainClass.set("cache.MainKt") + mainClass.set("com.compiler.server.cache.MainKt") } val runTask = tasks.named("run") { @@ -17,29 +17,22 @@ val runTask = tasks.named("run") { dependsOn(":dependencies:copyComposeWasmCompilerPlugins") dependsOn(":dependencies:copyComposeWasmDependencies") - val rootName = project.rootProject.projectDir.toString() - val kotlinVersion = libs.versions.kotlin.get() inputs.property("kotlinVersion", kotlinVersion) - // Adding classpath directories as task input for up-to-date checks inputs.dir(libWasmFolder) inputs.dir(libComposeWasmFolder) inputs.dir(libComposeWasmCompilerPluginsFolder) - // Adding resulting index files as output for up-to-date checks - val composeCacheComposeWasm = "$rootName${File.separator}$cachesComposeWasm" outputs.dir(cachesComposeWasmFolder) - args = listOf( + args( kotlinVersion, libJVMFolder.asFile.absolutePath, - composeCacheComposeWasm, + cachesComposeWasmFolder, ) } -val outputLocalCacheDir = rootDir.resolve(cachesComposeWasm) - val outputLambdaCacheDir: Provider = layout.buildDirectory.dir("incremental-cache") val buildCacheForLambda by tasks.registering(Exec::class) { workingDir = rootDir @@ -49,8 +42,8 @@ val buildCacheForLambda by tasks.registering(Exec::class) { outputs.dir(outputDir.map { it.dir(cachesComposeWasm) }) - doFirst { - args = listOf( + argumentProviders.add { + listOf( lambdaPrefix, // baseDir outputDir.get().asFile.normalize().absolutePath, // targetDir ) @@ -81,7 +74,7 @@ val kotlinComposeWasmIcLambdaCache: Configuration by configurations.creating { } } -artifacts.add(kotlinComposeWasmIcLocalCache.name, outputLocalCacheDir) { +artifacts.add(kotlinComposeWasmIcLocalCache.name, cachesComposeWasmFolder) { builtBy(runTask) } diff --git a/cache-maker/src/main/kotlin/CacheBuilder.kt b/cache-maker/src/main/kotlin/com/compiler/server/cache/CacheBuilder.kt similarity index 97% rename from cache-maker/src/main/kotlin/CacheBuilder.kt rename to cache-maker/src/main/kotlin/com/compiler/server/cache/CacheBuilder.kt index 8ddf1525..e5ec4f15 100644 --- a/cache-maker/src/main/kotlin/CacheBuilder.kt +++ b/cache-maker/src/main/kotlin/com/compiler/server/cache/CacheBuilder.kt @@ -1,3 +1,5 @@ +package com.compiler.server.cache + import com.compiler.server.common.components.KotlinEnvironment import com.compiler.server.common.components.compileWasmArgs import com.compiler.server.common.components.linkWasmArgs diff --git a/cache-maker/src/main/kotlin/Main.kt b/cache-maker/src/main/kotlin/com/compiler/server/cache/Main.kt similarity index 92% rename from cache-maker/src/main/kotlin/Main.kt rename to cache-maker/src/main/kotlin/com/compiler/server/cache/Main.kt index 2c35259c..0f1922f6 100644 --- a/cache-maker/src/main/kotlin/Main.kt +++ b/cache-maker/src/main/kotlin/com/compiler/server/cache/Main.kt @@ -1,6 +1,5 @@ -package cache +package com.compiler.server.cache -import CacheBuilder import com.compiler.server.common.components.KotlinEnvironmentConfiguration fun main(args: Array) { From 53c84954c0ae0b65ce06f5f32c96291640be0299 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Mon, 18 Nov 2024 13:24:15 +0100 Subject: [PATCH 05/31] Readonly cache --- .../server/compiler/components/KotlinToJSTranslator.kt | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt index 4ccc9f58..f4025da2 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt @@ -184,7 +184,7 @@ class KotlinToJSTranslator( icDir, outputDir, debugInfo - ) + ) + "-Xwasm-ic-cache-readonly=true" ) } .map { @@ -201,13 +201,7 @@ class KotlinToJSTranslator( val time = measureTime { a = cacheDir?.let { dir -> - usingTempDirectory { tmpDir -> - val cachesDir = tmpDir.resolve("caches").normalize() - if (dir.exists()) { - dir.copyRecursively(cachesDir.toFile()) - } - compileAction(cachesDir) - } + compileAction(dir.toPath()) } ?: compileAction(null) } println("TIME: $time") From aed319e4628caaceeb9197579376dee81fdeff9c Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Mon, 18 Nov 2024 14:18:06 +0100 Subject: [PATCH 06/31] Remove time measure --- .../compiler/components/KotlinToJSTranslator.kt | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt index f4025da2..23ff7de9 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt @@ -11,7 +11,6 @@ import java.nio.file.Path import kotlin.io.path.div import kotlin.io.path.readBytes import kotlin.io.path.readText -import kotlin.time.measureTime @Service class KotlinToJSTranslator( @@ -197,15 +196,9 @@ class KotlinToJSTranslator( } } - val a: CompilationResult - - val time = measureTime { - a = cacheDir?.let { dir -> - compileAction(dir.toPath()) - } ?: compileAction(null) - } - println("TIME: $time") - a + cacheDir?.let { dir -> + compileAction(dir.toPath()) + } ?: compileAction(null) } } } From 873c1ff7a751626de81dc6120bae8b531fa8250e Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Wed, 4 Dec 2024 23:26:11 +0100 Subject: [PATCH 07/31] Fix variant-aware configurations for Gradle --- build.gradle.kts | 8 +++++ buildSrc/src/main/kotlin/CategoryAttribute.kt | 5 +++ cache-maker/build.gradle.kts | 33 +++++++++++-------- 3 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 buildSrc/src/main/kotlin/CategoryAttribute.kt diff --git a/build.gradle.kts b/build.gradle.kts index b9a4627e..627b0cbd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -72,6 +72,10 @@ val kotlinComposeWasmIcLocalCache: Configuration by configurations.creating { isCanBeResolved = true isCanBeConsumed = false attributes { + attribute( + Category.CATEGORY_ATTRIBUTE, + objects.categoryComposeCache + ) attribute( CacheAttribute.cacheAttribute, CacheAttribute.LOCAL @@ -84,6 +88,10 @@ val kotlinComposeWasmIcLambdaCache: Configuration by configurations.creating { isCanBeResolved = true isCanBeConsumed = false attributes { + attribute( + Category.CATEGORY_ATTRIBUTE, + objects.categoryComposeCache + ) attribute( CacheAttribute.cacheAttribute, CacheAttribute.LAMBDA diff --git a/buildSrc/src/main/kotlin/CategoryAttribute.kt b/buildSrc/src/main/kotlin/CategoryAttribute.kt new file mode 100644 index 00000000..a10431af --- /dev/null +++ b/buildSrc/src/main/kotlin/CategoryAttribute.kt @@ -0,0 +1,5 @@ +import org.gradle.api.attributes.Category +import org.gradle.api.model.ObjectFactory + +val ObjectFactory.categoryComposeCache + get() = named(Category::class.java, "compose-cache") \ No newline at end of file diff --git a/cache-maker/build.gradle.kts b/cache-maker/build.gradle.kts index 79076ea1..b8ca9991 100644 --- a/cache-maker/build.gradle.kts +++ b/cache-maker/build.gradle.kts @@ -50,35 +50,42 @@ val buildCacheForLambda by tasks.registering(Exec::class) { } } -val kotlinComposeWasmIcLocalCache: Configuration by configurations.creating { +val kotlinComposeWasmIc: Configuration by configurations.creating { isTransitive = false isCanBeResolved = false isCanBeConsumed = true + attributes { + attribute( + Category.CATEGORY_ATTRIBUTE, + objects.categoryComposeCache + ) + } +} + +kotlinComposeWasmIc.outgoing.variants.create("local") { attributes { attribute( CacheAttribute.cacheAttribute, CacheAttribute.LOCAL ) } + + artifact(cachesComposeWasmFolder) { + type = "directory" + builtBy(runTask) + } } -val kotlinComposeWasmIcLambdaCache: Configuration by configurations.creating { - isTransitive = false - isCanBeResolved = false - isCanBeConsumed = true +kotlinComposeWasmIc.outgoing.variants.create("lambda") { attributes { attribute( CacheAttribute.cacheAttribute, CacheAttribute.LAMBDA ) } -} -artifacts.add(kotlinComposeWasmIcLocalCache.name, cachesComposeWasmFolder) { - builtBy(runTask) -} - -artifacts.add(kotlinComposeWasmIcLambdaCache.name, outputLambdaCacheDir) { - builtBy(buildCacheForLambda) + artifact(outputLambdaCacheDir) { + type = "directory" + builtBy(buildCacheForLambda) + } } - From aaf39de580c1233507bfc43f2c62180d8c76c5b7 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Thu, 5 Dec 2024 00:07:54 +0100 Subject: [PATCH 08/31] Fix sample to be compatible with example in playground --- cache-maker/src/main/resources/File.kt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/cache-maker/src/main/resources/File.kt b/cache-maker/src/main/resources/File.kt index 7d82015a..3ea082c2 100644 --- a/cache-maker/src/main/resources/File.kt +++ b/cache-maker/src/main/resources/File.kt @@ -1,22 +1,24 @@ +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.window.CanvasBasedWindow import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.Button import androidx.compose.material.MaterialTheme import androidx.compose.material.Text -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment -import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier -import androidx.compose.ui.window.ComposeViewport -import kotlinx.browser.document //sampleStart @OptIn(ExperimentalComposeUiApi::class) fun main() { - ComposeViewport(document.body!!) { - App() - } + CanvasBasedWindow { App() } } @Composable From 486f8cdc910f1d8519a194353aa59f1afe39b103 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 21 Jan 2025 13:56:47 +0100 Subject: [PATCH 09/31] First version with typeinfo --- build.gradle.kts | 27 ++---- buildSrc/src/main/kotlin/CacheAttribute.kt | 3 +- cache-maker/Dockerfile | 16 +--- cache-maker/build.gradle.kts | 87 ++++++++----------- cache-maker/docker-build-incremental-cache.sh | 4 +- .../com/compiler/server/cache/CacheBuilder.kt | 55 ------------ .../kotlin/com/compiler/server/cache/Main.kt | 14 --- .../File.kt => wasmJsMain/kotlin/main.kt} | 0 .../server/common/components/CliUtils.kt | 68 +++++++++++---- dependencies/build.gradle.kts | 1 + gradle.properties | 3 +- gradle/libs.versions.toml | 5 +- .../components/KotlinToJSTranslator.kt | 41 +++++++-- .../controllers/ResourceRestController.kt | 21 ++++- 14 files changed, 160 insertions(+), 185 deletions(-) delete mode 100644 cache-maker/src/main/kotlin/com/compiler/server/cache/CacheBuilder.kt delete mode 100644 cache-maker/src/main/kotlin/com/compiler/server/cache/Main.kt rename cache-maker/src/{main/resources/File.kt => wasmJsMain/kotlin/main.kt} (100%) diff --git a/build.gradle.kts b/build.gradle.kts index 627b0cbd..8cff7c83 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -67,7 +67,7 @@ val resourceDependency: Configuration by configurations.creating { } -val kotlinComposeWasmIcLocalCache: Configuration by configurations.creating { +val kotlinComposeWasmStdlibTypeInfo: Configuration by configurations.creating { isTransitive = false isCanBeResolved = true isCanBeConsumed = false @@ -78,23 +78,7 @@ val kotlinComposeWasmIcLocalCache: Configuration by configurations.creating { ) attribute( CacheAttribute.cacheAttribute, - CacheAttribute.LOCAL - ) - } -} - -val kotlinComposeWasmIcLambdaCache: Configuration by configurations.creating { - isTransitive = false - isCanBeResolved = true - isCanBeConsumed = false - attributes { - attribute( - Category.CATEGORY_ATTRIBUTE, - objects.categoryComposeCache - ) - attribute( - CacheAttribute.cacheAttribute, - CacheAttribute.LAMBDA + CacheAttribute.STDLIB ) } } @@ -127,8 +111,7 @@ dependencies { resourceDependency(libs.skiko.js.wasm.runtime) - kotlinComposeWasmIcLocalCache(project(":cache-maker")) - kotlinComposeWasmIcLambdaCache(project(":cache-maker")) + kotlinComposeWasmStdlibTypeInfo(project(":cache-maker")) } fun buildPropertyFile() { @@ -165,7 +148,7 @@ tasks.withType { } dependsOn(":executors:jar") dependsOn(":indexation:run") - dependsOn(kotlinComposeWasmIcLocalCache) + dependsOn(kotlinComposeWasmStdlibTypeInfo) buildPropertyFile() } println("Using Kotlin compiler ${libs.versions.kotlin.get()}") @@ -198,7 +181,7 @@ val buildLambda by tasks.creating(Zip::class) { from(libJVMFolder) { into(libJVM) } from(compilerPluginsForJVMFolder) {into(compilerPluginsForJVM)} from(libComposeWasmCompilerPluginsFolder) { into(libComposeWasmCompilerPlugins) } - from(kotlinComposeWasmIcLambdaCache) + from(kotlinComposeWasmStdlibTypeInfo) { into(cachesComposeWasm) } into("lib") { from(configurations.compileClasspath) { exclude("tomcat-embed-*") } } diff --git a/buildSrc/src/main/kotlin/CacheAttribute.kt b/buildSrc/src/main/kotlin/CacheAttribute.kt index f77af0c8..bd7349d7 100644 --- a/buildSrc/src/main/kotlin/CacheAttribute.kt +++ b/buildSrc/src/main/kotlin/CacheAttribute.kt @@ -1,8 +1,7 @@ import org.gradle.api.attributes.Attribute enum class CacheAttribute { - LOCAL, - LAMBDA; + STDLIB; companion object { val cacheAttribute = Attribute.of("org.jetbrains.kotlin-compiler-server.cache", CacheAttribute::class.java) diff --git a/cache-maker/Dockerfile b/cache-maker/Dockerfile index abbb2bd2..d5738098 100644 --- a/cache-maker/Dockerfile +++ b/cache-maker/Dockerfile @@ -8,23 +8,13 @@ RUN if [ -z "$KOTLIN_VERSION" ]; then \ exit 1; \ fi -ENV KOTLIN_LIB=$KOTLIN_VERSION -ENV KOTLIN_LIB_JS=${KOTLIN_VERSION}-js -ENV KOTLIN_LIB_WASM=${KOTLIN_VERSION}-wasm -ENV KOTLIN_LIB_COMPOSE_WASM=${KOTLIN_VERSION}-compose-wasm -ENV KOTLIN_COMPOSE_WASM_COMPILER_PLUGINS=${KOTLIN_VERSION}-compose-wasm-compiler-plugins -ENV KOTLIN_CACHES_COMPOSE_WASM=${KOTLIN_VERSION}-caches-compose-wasm +ENV KOTLIN_VERSION=$KOTLIN_VERSION RUN mkdir -p $BASE_DIR WORKDIR $BASE_DIR ADD . $BASE_DIR -RUN rm -rf $KOTLIN_LIB -RUN rm -rf $KOTLIN_LIB_JS -RUN rm -rf $KOTLIN_LIB_WASM -RUN rm -rf $KOTLIN_LIB_COMPOSE_WASM -RUN rm -rf $KOTLIN_COMPOSE_WASM_COMPILER_PLUGINS -RUN rm -rf $KOTLIN_CACHES_COMPOSE_WASM +RUN sed -i 's@kotlin = ".*"@kotlin = "'$KOTLIN_VERSION'"@g' gradle/libs.versions.toml RUN ./gradlew clean -RUN ./gradlew :cache-maker:run +RUN ./gradlew :cache-maker:compileProductionExecutableKotlinWasmJs diff --git a/cache-maker/build.gradle.kts b/cache-maker/build.gradle.kts index b8ca9991..d5422e66 100644 --- a/cache-maker/build.gradle.kts +++ b/cache-maker/build.gradle.kts @@ -1,56 +1,55 @@ plugins { - kotlin("jvm") - application + kotlin("multiplatform") } -dependencies { - implementation(project(":common", configuration = "default")) -} +kotlin { + wasmJs { + outputModuleName.set("stdlib") + binaries.executable().forEach { + it.linkTask.configure { + compilerOptions.freeCompilerArgs.add("-Xir-dce=false") + } + } + } -application { - mainClass.set("com.compiler.server.cache.MainKt") + sourceSets { + wasmJsMain { + dependencies { + implementation(libs.bundles.compose) + implementation(libs.kotlinx.coroutines.core.compose.wasm) + } + } + } } -val runTask = tasks.named("run") { - dependsOn(":dependencies:copyDependencies") - dependsOn(":dependencies:copyWasmDependencies") - dependsOn(":dependencies:copyComposeWasmCompilerPlugins") - dependsOn(":dependencies:copyComposeWasmDependencies") - - val kotlinVersion = libs.versions.kotlin.get() - inputs.property("kotlinVersion", kotlinVersion) - - inputs.dir(libWasmFolder) - inputs.dir(libComposeWasmFolder) - inputs.dir(libComposeWasmCompilerPluginsFolder) +val composeWasmStdlibTypeInfo: Provider = layout.buildDirectory + .file("compose-wasm-stdlib-output/stdlib.typeinfo.bin") - outputs.dir(cachesComposeWasmFolder) - - args( - kotlinVersion, - libJVMFolder.asFile.absolutePath, - cachesComposeWasmFolder, - ) -} - -val outputLambdaCacheDir: Provider = layout.buildDirectory.dir("incremental-cache") -val buildCacheForLambda by tasks.registering(Exec::class) { +val buildComposeWasmStdlibModule by tasks.registering(Exec::class) { workingDir = rootDir executable = "${project.name}/docker-build-incremental-cache.sh" - val outputDir = outputLambdaCacheDir + val outputDir = composeWasmStdlibTypeInfo.map { it.asFile.parentFile } - outputs.dir(outputDir.map { it.dir(cachesComposeWasm) }) + inputs.file(layout.projectDirectory.file("Dockerfile")) + inputs.file(layout.projectDirectory.file("docker-build-incremental-cache.sh")) + outputs.dir(outputDir) argumentProviders.add { listOf( lambdaPrefix, // baseDir - outputDir.get().asFile.normalize().absolutePath, // targetDir + outputDir.get().normalize().absolutePath, // targetDir ) } } -val kotlinComposeWasmIc: Configuration by configurations.creating { +val prepareTypeInfoIntoComposeWasmCache by tasks.registering(Sync::class) { + dependsOn(buildComposeWasmStdlibModule) + from(composeWasmStdlibTypeInfo) + into(cachesComposeWasmFolder) +} + +val kotlinComposeWasmStdlibTypeInfo: Configuration by configurations.creating { isTransitive = false isCanBeResolved = false isCanBeConsumed = true @@ -62,30 +61,16 @@ val kotlinComposeWasmIc: Configuration by configurations.creating { } } -kotlinComposeWasmIc.outgoing.variants.create("local") { +kotlinComposeWasmStdlibTypeInfo.outgoing.variants.create("stdlib") { attributes { attribute( CacheAttribute.cacheAttribute, - CacheAttribute.LOCAL + CacheAttribute.STDLIB ) } artifact(cachesComposeWasmFolder) { type = "directory" - builtBy(runTask) - } -} - -kotlinComposeWasmIc.outgoing.variants.create("lambda") { - attributes { - attribute( - CacheAttribute.cacheAttribute, - CacheAttribute.LAMBDA - ) - } - - artifact(outputLambdaCacheDir) { - type = "directory" - builtBy(buildCacheForLambda) + builtBy(prepareTypeInfoIntoComposeWasmCache) } } diff --git a/cache-maker/docker-build-incremental-cache.sh b/cache-maker/docker-build-incremental-cache.sh index 2994b49a..59f24c49 100755 --- a/cache-maker/docker-build-incremental-cache.sh +++ b/cache-maker/docker-build-incremental-cache.sh @@ -1,6 +1,6 @@ #!/bin/sh -kotlinVersion=$(awk '{ if ($1 == "kotlin") { gsub(/"/, "", $2); print $2; } }' FS=' = ' ./gradle/libs.versions.toml) +kotlinVersion=$(awk '{ if ($1 == "kotlinWasmStdlibCompiler") { gsub(/"/, "", $2); print $2; } }' FS=' = ' ./gradle/libs.versions.toml) baseDir=$1 targetDir=$2 @@ -15,7 +15,7 @@ docker build . --file cache-maker/Dockerfile --tag $image_tag --build-arg BASE_D container=$(docker create $image_tag) -docker cp $container:$baseDir/$kotlinVersion-caches-compose-wasm $targetDir +docker cp $container:$baseDir/cache-maker/build/compileSync/wasmJs/main/productionExecutable/kotlin/. $targetDir docker start $container docker stop $container diff --git a/cache-maker/src/main/kotlin/com/compiler/server/cache/CacheBuilder.kt b/cache-maker/src/main/kotlin/com/compiler/server/cache/CacheBuilder.kt deleted file mode 100644 index e5ec4f15..00000000 --- a/cache-maker/src/main/kotlin/com/compiler/server/cache/CacheBuilder.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.compiler.server.cache - -import com.compiler.server.common.components.KotlinEnvironment -import com.compiler.server.common.components.compileWasmArgs -import com.compiler.server.common.components.linkWasmArgs -import com.compiler.server.common.components.usingTempDirectory -import org.jetbrains.kotlin.cli.common.CLICompiler.Companion.doMainNoExit -import org.jetbrains.kotlin.cli.js.K2JSCompiler -import java.io.File -import kotlin.io.path.div - - -class CacheBuilder( - private val kotlinEnvironment: KotlinEnvironment, -) { - fun compileCache(outputForCache: String) { - val moduleName = "playground" - usingTempDirectory { outputDir -> - val resource = this::class.java.classLoader.getResource("File.kt")!!.path - - val klibPath = (outputDir / "klib").toFile().normalize().absolutePath - - val k2JSCompiler = K2JSCompiler() - - doMainNoExit( - k2JSCompiler, - compileWasmArgs( - moduleName, - listOf(resource), - klibPath, - kotlinEnvironment.COMPOSE_WASM_COMPILER_PLUGINS, - kotlinEnvironment.composeWasmCompilerPluginOptions, - kotlinEnvironment.COMPOSE_WASM_LIBRARIES - ).toTypedArray() - ) - - usingTempDirectory { tmpDir -> - val cachesDir = tmpDir.resolve("caches").normalize() - doMainNoExit( - k2JSCompiler, - linkWasmArgs( - moduleName, - klibPath, - kotlinEnvironment.COMPOSE_WASM_LIBRARIES, - cachesDir.normalize(), - outputDir, - false - ).toTypedArray() - ) - - cachesDir.toFile().copyRecursively(File(outputForCache), overwrite = true) - } - } - } -} \ No newline at end of file diff --git a/cache-maker/src/main/kotlin/com/compiler/server/cache/Main.kt b/cache-maker/src/main/kotlin/com/compiler/server/cache/Main.kt deleted file mode 100644 index 0f1922f6..00000000 --- a/cache-maker/src/main/kotlin/com/compiler/server/cache/Main.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.compiler.server.cache - -import com.compiler.server.common.components.KotlinEnvironmentConfiguration - -fun main(args: Array) { - val version = args[0] - val directory = args[1] - val outputPathCacheComposeWasm = args[2] - val kotlinEnvironment = KotlinEnvironmentConfiguration(version, directory).kotlinEnvironment - - CacheBuilder( - kotlinEnvironment = kotlinEnvironment - ).compileCache(outputPathCacheComposeWasm) -} diff --git a/cache-maker/src/main/resources/File.kt b/cache-maker/src/wasmJsMain/kotlin/main.kt similarity index 100% rename from cache-maker/src/main/resources/File.kt rename to cache-maker/src/wasmJsMain/kotlin/main.kt diff --git a/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt b/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt index 44c74a54..8466fc20 100644 --- a/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt +++ b/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt @@ -23,12 +23,14 @@ private fun getTempDirectory(): Path { } fun compileWasmArgs( - moduleName: String, - filePaths: List, - klibPath: String, - compilerPlugins: List, - compilerPluginOptions: List, - dependencies: List, + moduleName: String, + filePaths: List, + klibPath: String, + compilerPlugins: List, + compilerPluginOptions: List, + dependencies: List, + icDir: Path?, + log: (String) -> Unit, ): List { val compilerPluginsArgs: List = compilerPlugins .takeIf { it.isNotEmpty() } @@ -39,7 +41,7 @@ fun compileWasmArgs( "-P=$it" } } ?: emptyList() - val additionalCompilerArgumentsForKLib: List = listOf( + val additionalCompilerArgumentsForKLib: List = mutableListOf( "-Xreport-all-warnings", "-Wextra", "-Xwasm", @@ -47,18 +49,25 @@ fun compileWasmArgs( "-libraries=${dependencies.joinToString(PATH_SEPARATOR)}", "-ir-output-dir=$klibPath", "-ir-output-name=$moduleName", - ) + compilerPluginsArgs + ).also { + if (icDir != null) { + typeInfoArg(icDir, log)?.let { stdlibTypeInfoArg -> + it.add(stdlibTypeInfoArg) + } + } + } + compilerPluginsArgs return filePaths + additionalCompilerArgumentsForKLib } fun linkWasmArgs( - moduleName: String, - klibPath: String, - dependencies: List, - icDir: Path?, - outputDir: Path, - debugInfo: Boolean, + moduleName: String, + klibPath: String, + dependencies: List, + icDir: Path?, + outputDir: Path, + debugInfo: Boolean, + log: (String) -> Unit, ): List { return mutableListOf( "-Xreport-all-warnings", @@ -68,15 +77,42 @@ fun linkWasmArgs( "-Xinclude=$klibPath", "-libraries=${dependencies.joinToString(PATH_SEPARATOR)}", "-ir-output-dir=${(outputDir / "wasm").toFile().canonicalPath}", - "-ir-output-name=$moduleName",).also { + "-ir-output-name=$moduleName", + ).also { if (debugInfo) it.add("-Xwasm-generate-wat") if (icDir != null) { - it.add("-Xcache-directory=${icDir.normalize().absolutePathString()}") + typeInfoArg(icDir, log)?.let { stdlibTypeInfoArg -> + it.add(stdlibTypeInfoArg) + } } else { it.add("-Xir-dce") } } } +private fun typeInfoArg( + icDir: Path, + log: (String) -> Unit, +): String? { + val allTypeInfoFiles = icDir.toFile().listFiles() ?: run { + log("No typeinfo files in $icDir, probably you need to run :cache-maker:prepareTypeInfoIntoComposeWasmCache task") + return null + } + + val stdlibTypeInfo = allTypeInfoFiles + .firstOrNull { file -> file.name.endsWith(".typeinfo.bin") } + + if (stdlibTypeInfo == null) { + log("No typeinfo files in $icDir, probably you need to run :cache-maker:prepareTypeInfoIntoComposeWasmCache task") + return null + } + + if (allTypeInfoFiles.size > 1) { + log("There are more than 1 typeinfo files in $icDir: ${allTypeInfoFiles.joinToString(", ") { it.name }}") + } + + return "-Xwasm-typeinfo-file=${stdlibTypeInfo.normalize().absolutePath}" +} + val PATH_SEPARATOR: String = File.pathSeparator diff --git a/dependencies/build.gradle.kts b/dependencies/build.gradle.kts index 5e9358ec..7bde4e2a 100644 --- a/dependencies/build.gradle.kts +++ b/dependencies/build.gradle.kts @@ -122,6 +122,7 @@ dependencies { // compose kotlinComposeWasmDependency(libs.kotlin.stdlib.wasm.js) kotlinComposeWasmDependency(libs.bundles.compose) + kotlinComposeWasmDependency(libs.kotlinx.coroutines.core.compose.wasm) composeWasmCompilerPlugins(libs.kotlin.compose.compiler.plugin) } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 116440fc..861f7a8d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,4 +4,5 @@ systemProp.indexesJs=indexesJs.json systemProp.indexesWasm=indexesWasm.json systemProp.indexesComposeWasm=indexesComposeWasm.json -org.gradle.configuration-cache=true \ No newline at end of file +org.gradle.configuration-cache=true +org.gradle.jvmargs=-Xmx6048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx6048M" \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index afb982c7..ee1e2fa1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,6 @@ [versions] -kotlin = "2.1.20-dev-5634" +kotlin = "2.2.0-dev-1011" +kotlinWasmStdlibCompiler = "2.2.0-dev-1010" kotlinIdeVersion = "1.9.20-506" kotlinIdeVersionWithSuffix = "231-1.9.20-506-IJ8109.175" spring-boot = "2.7.10" @@ -10,6 +11,7 @@ junit = "4.13.2" logstash-logback-encoder = "7.3" trove4j = "1.0.20221201" kotlinx-coroutines = "1.7.3" +kotlinx-coroutines-compose-wasm = "1.8.1" kotlinx-coroutines-test = "1.6.4" kotlinx-datetime = "0.6.0-RC.2" kotlinx-io = "0.6.0" @@ -39,6 +41,7 @@ kotlin-compiler-ide = { group = "org.jetbrains.kotlin", name = "kotlin-compiler- kotlin-idea = { group = "org.jetbrains.kotlin", name = "idea", version.ref = "kotlinIdeVersionWithSuffix" } kotlin-core = { group = "org.jetbrains.kotlin", name = "core", version.ref = "kotlinIdeVersionWithSuffix" } kotlinx-coroutines-core-jvm = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core-jvm", version.ref = "kotlinx-coroutines" } +kotlinx-coroutines-core-compose-wasm = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core-wasm-js", version.ref = "kotlinx-coroutines-compose-wasm" } kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinx-coroutines-test" } kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version.ref = "kotlinx-datetime" } kotlinx-io-bytestring = { group = "org.jetbrains.kotlinx", name = "kotlinx-io-bytestring", version.ref = "kotlinx-io" } diff --git a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt index 23ff7de9..47b2e908 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt @@ -5,6 +5,7 @@ import com.compiler.server.model.* import com.fasterxml.jackson.databind.ObjectMapper import org.jetbrains.kotlin.cli.js.K2JSCompiler import org.jetbrains.kotlin.psi.KtFile +import org.slf4j.LoggerFactory import org.springframework.stereotype.Service import java.io.File import java.nio.file.Path @@ -16,6 +17,8 @@ import kotlin.io.path.readText class KotlinToJSTranslator( private val kotlinEnvironment: KotlinEnvironment, ) { + private val log = LoggerFactory.getLogger(KotlinToJSTranslator::class.java) + companion object { private const val JS_IR_CODE_BUFFER = "playground.output?.buffer_1;\n" @@ -170,7 +173,9 @@ class KotlinToJSTranslator( klibPath, compilerPlugins, compilerPluginOptions, - dependencies + dependencies, + icDir, + log::warn, ) ) .flatMap { @@ -182,8 +187,9 @@ class KotlinToJSTranslator( dependencies, icDir, outputDir, - debugInfo - ) + "-Xwasm-ic-cache-readonly=true" + debugInfo, + log::warn, + ) ) } .map { @@ -196,9 +202,7 @@ class KotlinToJSTranslator( } } - cacheDir?.let { dir -> - compileAction(dir.toPath()) - } ?: compileAction(null) + compileAction(cacheDir?.toPath()) } } } @@ -221,4 +225,27 @@ data class WasmTranslationSuccessfulOutput( val jsInstantiated: String, val wasm: ByteArray, val wat: String?, -) +) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as WasmTranslationSuccessfulOutput + + if (jsCode != other.jsCode) return false + if (jsInstantiated != other.jsInstantiated) return false + if (!wasm.contentEquals(other.wasm)) return false + if (wat != other.wat) return false + + return true + } + + override fun hashCode(): Int { + var result = jsCode.hashCode() + result = 31 * result + jsInstantiated.hashCode() + result = 31 * result + wasm.contentHashCode() + result = 31 * result + (wat?.hashCode() ?: 0) + return result + } + +} diff --git a/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt b/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt index 93a2bc1f..4ae6d472 100644 --- a/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt +++ b/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt @@ -22,6 +22,26 @@ class ResourceRestController { return cacheableResource("/com/compiler/server/skiko.wasm", MediaType("application", "wasm")) } + @GetMapping("/stdlib.mjs") + fun getStdlibMjs(): ResponseEntity { + val resource = FileSystemResource("/Users/ilya.goncharov/repos/kotlin-compiler-server/COMPOSE/stdlib.uninstantiated.mjs") + val headers = HttpHeaders().apply { + contentType = MediaType("text", "javascript") + } + + return ResponseEntity(resource, headers, HttpStatus.OK) + } + + @GetMapping("/stdlib.wasm") + fun getStdlibWasm(): ResponseEntity { + val resource = FileSystemResource("/Users/ilya.goncharov/repos/kotlin-compiler-server/COMPOSE/stdlib.wasm") + val headers = HttpHeaders().apply { + contentType = MediaType("application", "wasm") + } + + return ResponseEntity(resource, headers, HttpStatus.OK) + } + private fun cacheableResource(path: String, mediaType: MediaType): ResponseEntity { val resourcePath = javaClass.getResource(path)?.path ?: return ResponseEntity.internalServerError().build() @@ -29,7 +49,6 @@ class ResourceRestController { val resource = FileSystemResource(resourcePath) val headers = HttpHeaders().apply { contentType = mediaType - cacheControl = CacheControl.maxAge(365, TimeUnit.DAYS).headerValue } return ResponseEntity(resource, headers, HttpStatus.OK) From e35603b270b55df95a67c832567bb95185caf58e Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 21 Jan 2025 18:27:41 +0100 Subject: [PATCH 10/31] Add resources server --- .gitignore | 1 + build.gradle.kts | 25 ++-- buildSrc/src/main/kotlin/CacheAttribute.kt | 3 +- buildSrc/src/main/kotlin/PropertiesUpdater.kt | 61 ++++++++++ cache-maker/build.gradle.kts | 34 ++++-- resource-server/build.gradle.kts | 115 ++++++++++++++++++ .../compiler/server/ResourceApplication.kt | 11 ++ .../server/configuration/CorsConfiguration.kt | 26 ++++ .../controllers/ResourceRestController.kt | 76 ++++++++++++ settings.gradle.kts | 3 +- .../controllers/ResourceRestController.kt | 55 ++------- 11 files changed, 338 insertions(+), 72 deletions(-) create mode 100644 buildSrc/src/main/kotlin/PropertiesUpdater.kt create mode 100644 resource-server/build.gradle.kts create mode 100644 resource-server/src/main/kotlin/com/compiler/server/ResourceApplication.kt create mode 100644 resource-server/src/main/kotlin/com/compiler/server/configuration/CorsConfiguration.kt create mode 100644 resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt diff --git a/.gitignore b/.gitignore index ac787777..36cb4e42 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ build/ !**/src/main/** !**/src/test/** src/main/resources/application.properties +resource-server/src/main/resources/application.properties # compile artifacts .kotlin/ diff --git a/build.gradle.kts b/build.gradle.kts index 8cff7c83..eebaa4f2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,3 @@ -import org.gradle.kotlin.dsl.support.serviceOf import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -61,11 +60,6 @@ setOf( } } -val resourceDependency: Configuration by configurations.creating { - isCanBeResolved = true - isCanBeConsumed = false -} - val kotlinComposeWasmStdlibTypeInfo: Configuration by configurations.creating { isTransitive = false @@ -78,7 +72,7 @@ val kotlinComposeWasmStdlibTypeInfo: Configuration by configurations.creating { ) attribute( CacheAttribute.cacheAttribute, - CacheAttribute.STDLIB + CacheAttribute.TYPEINFO ) } } @@ -109,8 +103,6 @@ dependencies { } testImplementation(libs.kotlinx.coroutines.test) - resourceDependency(libs.skiko.js.wasm.runtime) - kotlinComposeWasmStdlibTypeInfo(project(":cache-maker")) } @@ -140,8 +132,15 @@ fun generateProperties(prefix: String = "") = """ spring.mvc.pathmatch.matching-strategy=ant_path_matcher server.compression.enabled=true server.compression.mime-types=application/json,text/javascript,application/wasm + skiko.version=${libs.versions.skiko.get()} """.trimIndent() +val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdater::class) { + dependsOn(kotlinComposeWasmStdlibTypeInfo) + propertiesPath.set(rootDir.resolve("src/main/resources/${propertyFile}").absolutePath) + typeInfoFile.set(kotlinComposeWasmStdlibTypeInfo.singleFile) +} + tasks.withType { compilerOptions { freeCompilerArgs.set(listOf("-Xjsr305=strict")) @@ -149,6 +148,7 @@ tasks.withType { dependsOn(":executors:jar") dependsOn(":indexation:run") dependsOn(kotlinComposeWasmStdlibTypeInfo) + dependsOn(composeWasmPropertiesUpdater) buildPropertyFile() } println("Using Kotlin compiler ${libs.versions.kotlin.get()}") @@ -188,12 +188,7 @@ val buildLambda by tasks.creating(Zip::class) { } tasks.named("processResources") { - val archiveOperation = project.serviceOf() - from(resourceDependency.map { - archiveOperation.zipTree(it) - }) { - into("com/compiler/server") - } + dependsOn(composeWasmPropertiesUpdater) } tasks.withType { diff --git a/buildSrc/src/main/kotlin/CacheAttribute.kt b/buildSrc/src/main/kotlin/CacheAttribute.kt index bd7349d7..78af16d3 100644 --- a/buildSrc/src/main/kotlin/CacheAttribute.kt +++ b/buildSrc/src/main/kotlin/CacheAttribute.kt @@ -1,7 +1,8 @@ import org.gradle.api.attributes.Attribute enum class CacheAttribute { - STDLIB; + FULL, + TYPEINFO; companion object { val cacheAttribute = Attribute.of("org.jetbrains.kotlin-compiler-server.cache", CacheAttribute::class.java) diff --git a/buildSrc/src/main/kotlin/PropertiesUpdater.kt b/buildSrc/src/main/kotlin/PropertiesUpdater.kt new file mode 100644 index 00000000..7f235885 --- /dev/null +++ b/buildSrc/src/main/kotlin/PropertiesUpdater.kt @@ -0,0 +1,61 @@ +import org.gradle.api.DefaultTask +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.MapProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.TaskAction +import java.io.File +import java.io.FileInputStream +import java.security.MessageDigest + +abstract class ComposeWasmPropertiesUpdater : DefaultTask() { + + @get:InputFile + abstract val propertiesPath: Property + + @get:InputFile + abstract val typeInfoFile: RegularFileProperty + + @get:Input + abstract val propertiesMap: MapProperty + + @get:OutputFile + val updatedPropertiesFile: RegularFileProperty = project.objects.fileProperty().fileProvider(propertiesPath.map { File(it) }) + + @TaskAction + fun updateProperties() { + val file = File(propertiesPath.get()) + + propertiesMap.get().let { + if (it.isNotEmpty()) { + file.writeText("") + it.forEach { (key, value) -> + file.appendText("$key=$value\n") + } + } + } + + file.appendText( + "\ndependencies.compose.wasm=${hashFileContent(typeInfoFile.get().asFile.absolutePath)}" + ) + } +} + +fun hashFileContent(filePath: String, hashAlgorithm: String = "SHA-256"): String { + val file = File(filePath) + val digest = MessageDigest.getInstance(hashAlgorithm) + + // Read the file content in chunks and update the digest + FileInputStream(file).use { fileInputStream -> + val buffer = ByteArray(1024) + var bytesRead: Int + while (fileInputStream.read(buffer).also { bytesRead = it } != -1) { + digest.update(buffer, 0, bytesRead) + } + } + + // Convert the resulting byte array to a readable hex string + return digest.digest().joinToString("") { "%02x".format(it) } +} \ No newline at end of file diff --git a/cache-maker/build.gradle.kts b/cache-maker/build.gradle.kts index d5422e66..015fb7ab 100644 --- a/cache-maker/build.gradle.kts +++ b/cache-maker/build.gradle.kts @@ -22,25 +22,23 @@ kotlin { } } -val composeWasmStdlibTypeInfo: Provider = layout.buildDirectory - .file("compose-wasm-stdlib-output/stdlib.typeinfo.bin") +val composeWasmStdlib: Provider = layout.buildDirectory + .dir("compose-wasm-stdlib-output") +val composeWasmStdlibTypeInfo: Provider = composeWasmStdlib + .map { it.file("compose-wasm-stdlib-output/stdlib.typeinfo.bin") } val buildComposeWasmStdlibModule by tasks.registering(Exec::class) { + workingDir = rootDir executable = "${project.name}/docker-build-incremental-cache.sh" - val outputDir = composeWasmStdlibTypeInfo.map { it.asFile.parentFile } + val outputDir = composeWasmStdlib inputs.file(layout.projectDirectory.file("Dockerfile")) inputs.file(layout.projectDirectory.file("docker-build-incremental-cache.sh")) outputs.dir(outputDir) - argumentProviders.add { - listOf( - lambdaPrefix, // baseDir - outputDir.get().normalize().absolutePath, // targetDir - ) - } + args(lambdaPrefix, outputDir.get().asFile.normalize().absolutePath) } val prepareTypeInfoIntoComposeWasmCache by tasks.registering(Sync::class) { @@ -65,12 +63,24 @@ kotlinComposeWasmStdlibTypeInfo.outgoing.variants.create("stdlib") { attributes { attribute( CacheAttribute.cacheAttribute, - CacheAttribute.STDLIB + CacheAttribute.FULL + ) + } + + artifact(composeWasmStdlib) { + builtBy(prepareTypeInfoIntoComposeWasmCache) + } +} + +kotlinComposeWasmStdlibTypeInfo.outgoing.variants.create("typeinfo") { + attributes { + attribute( + CacheAttribute.cacheAttribute, + CacheAttribute.TYPEINFO ) } - artifact(cachesComposeWasmFolder) { - type = "directory" + artifact(cachesComposeWasmFolder.file("stdlib.typeinfo.bin")) { builtBy(prepareTypeInfoIntoComposeWasmCache) } } diff --git a/resource-server/build.gradle.kts b/resource-server/build.gradle.kts new file mode 100644 index 00000000..d30f2cc3 --- /dev/null +++ b/resource-server/build.gradle.kts @@ -0,0 +1,115 @@ +import org.gradle.kotlin.dsl.support.serviceOf +import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + alias(libs.plugins.spring.dependency.management) + alias(libs.plugins.spring.boot) + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.kotlin.plugin.spring) +} + +kotlin.jvmToolchain { + languageVersion.set(JavaLanguageVersion.of(17)) + vendor.set(JvmVendorSpec.AMAZON) +} + +val resourceDependency: Configuration by configurations.creating { + isCanBeResolved = true + isCanBeConsumed = false +} + +val kotlinComposeWasmStdlibTypeInfo: Configuration by configurations.creating { + isTransitive = false + isCanBeResolved = true + isCanBeConsumed = false + attributes { + attribute( + Category.CATEGORY_ATTRIBUTE, + objects.categoryComposeCache + ) + attribute( + CacheAttribute.cacheAttribute, + CacheAttribute.TYPEINFO + ) + } +} + +val kotlinComposeWasmStdlib: Configuration by configurations.creating { + isTransitive = false + isCanBeResolved = true + isCanBeConsumed = false + attributes { + attribute( + Category.CATEGORY_ATTRIBUTE, + objects.categoryComposeCache + ) + attribute( + CacheAttribute.cacheAttribute, + CacheAttribute.FULL + ) + } +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web") +// implementation(libs.springfox.boot.starter) +// implementation(libs.aws.springboot.container) +// implementation(libs.junit) +// implementation(libs.logback.logstash.encoder) +// implementation(libs.intellij.trove4j) +// implementation(libs.kotlin.reflect) +// implementation(libs.bundles.kotlin.stdlib) +// implementation(libs.kotlin.test) +// implementation(libs.kotlin.compiler) +// implementation(libs.kotlin.script.runtime) +// implementation(libs.kotlin.compiler.ide) { +// isTransitive = false +// } +// implementation(libs.kotlin.core) +// implementation(project(":executors", configuration = "default")) +// implementation(project(":common", configuration = "default")) +// +// testImplementation("org.springframework.boot:spring-boot-starter-test") { +// exclude(group = "org.junit.vintage", module = "junit-vintage-engine") +// } +// testImplementation(libs.kotlinx.coroutines.test) + + resourceDependency(libs.skiko.js.wasm.runtime) + kotlinComposeWasmStdlib(project(":cache-maker")) + kotlinComposeWasmStdlibTypeInfo(project(":cache-maker")) +} + +val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdater::class) { + dependsOn(kotlinComposeWasmStdlibTypeInfo) + propertiesMap.put("spring.mvc.pathmatch.matching-strategy", "ant_path_matcher") + propertiesMap.put("server.port", "8081") + propertiesMap.put("skiko.version", libs.versions.skiko.get()) + + val applicationPropertiesFile = projectDir.resolve("src/main/resources/application.properties") + val applicationProperties = applicationPropertiesFile.absolutePath + propertiesPath.set(applicationProperties) + + typeInfoFile.set(kotlinComposeWasmStdlibTypeInfo.singleFile) + + if (!applicationPropertiesFile.exists()) { + applicationPropertiesFile.createNewFile() + } +} + +tasks.withType { + dependsOn(composeWasmPropertiesUpdater) +} + +tasks.named("processResources") { + dependsOn(composeWasmPropertiesUpdater) + val archiveOperation = project.serviceOf() + from(resourceDependency.map { + archiveOperation.zipTree(it) + }) { + into("com/compiler/server") + } + from(kotlinComposeWasmStdlib) { + into("com/compiler/server") + } +} \ No newline at end of file diff --git a/resource-server/src/main/kotlin/com/compiler/server/ResourceApplication.kt b/resource-server/src/main/kotlin/com/compiler/server/ResourceApplication.kt new file mode 100644 index 00000000..55362542 --- /dev/null +++ b/resource-server/src/main/kotlin/com/compiler/server/ResourceApplication.kt @@ -0,0 +1,11 @@ +package com.compiler.server + +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +class ResourceApplication + +fun main(args: Array) { + runApplication(*args) +} diff --git a/resource-server/src/main/kotlin/com/compiler/server/configuration/CorsConfiguration.kt b/resource-server/src/main/kotlin/com/compiler/server/configuration/CorsConfiguration.kt new file mode 100644 index 00000000..237ad05f --- /dev/null +++ b/resource-server/src/main/kotlin/com/compiler/server/configuration/CorsConfiguration.kt @@ -0,0 +1,26 @@ +package com.compiler.server.configuration + +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.web.cors.CorsConfiguration +import org.springframework.web.cors.UrlBasedCorsConfigurationSource +import org.springframework.web.filter.CorsFilter + +val ACCESS_CONTROL_ALLOW_ORIGIN_VALUE: String = System.getenv("ACCESS_CONTROL_ALLOW_ORIGIN_VALUE") ?: "*" +val ACCESS_CONTROL_ALLOW_HEADER_VALUE: String = System.getenv("ACCESS_CONTROL_ALLOW_HEADER_VALUE") ?: "*" + +@Configuration +class CorsConfiguration { + @Bean + fun corsFilter(): CorsFilter { + val source = UrlBasedCorsConfigurationSource() + val config = CorsConfiguration().apply { + addAllowedHeader(ACCESS_CONTROL_ALLOW_HEADER_VALUE) + addAllowedOrigin(ACCESS_CONTROL_ALLOW_ORIGIN_VALUE) + addAllowedMethod("GET") + addAllowedMethod("POST") + } + source.registerCorsConfiguration("/**", config) + return CorsFilter(source) + } +} diff --git a/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt b/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt new file mode 100644 index 00000000..6f170333 --- /dev/null +++ b/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt @@ -0,0 +1,76 @@ +package com.compiler.server.controllers + +import org.springframework.beans.factory.annotation.Value +import org.springframework.core.io.FileSystemResource +import org.springframework.core.io.Resource +import org.springframework.http.* +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController +import java.util.concurrent.TimeUnit + + +@RestController +@RequestMapping(value = ["/api/resource", "/api/**/resource"]) +class ResourceRestController( + @Value("\${skiko.version}") private val skikoVersion: String, + @Value("\${dependencies.compose.wasm}") private val dependenciesComposeWasm: String, +) { + @Suppress("unused") + @GetMapping("/skiko-{version}.mjs") + fun getSkikoMjs(@PathVariable version: String): ResponseEntity { + if (version != skikoVersion) { + throw IllegalArgumentException("Unexpected skiko version") + } + return cacheableResource("/com/compiler/server/skiko.mjs", MediaType("text", "javascript")) + } + + @Suppress("unused") + @GetMapping("/skiko-{version}.wasm") + fun getSkikoWasm(@PathVariable version: String): ResponseEntity { + if (version != skikoVersion) { + throw IllegalArgumentException("Unexpected skiko version") + } + return cacheableResource("/com/compiler/server/skiko.wasm", MediaType("application", "wasm")) + } + + @GetMapping("/stdlib-{hash}.mjs") + fun getStdlibMjs(@PathVariable hash: String): ResponseEntity { + if (hash != dependenciesComposeWasm) { + throw IllegalArgumentException("Unexpected stdlib") + } + return cacheableResource("/com/compiler/server/stdlib.uninstantiated.mjs", MediaType("text", "javascript")) + } + + @GetMapping("/stdlib-{hash}.wasm") + fun getStdlibWasm(@PathVariable hash: String): ResponseEntity { + if (hash != dependenciesComposeWasm) { + throw IllegalArgumentException("Unexpected stdlib") + } + return cacheableResource("/com/compiler/server/stdlib.wasm", MediaType("application", "wasm")) + } + + private fun cacheableResource(path: String, mediaType: MediaType): ResponseEntity { + return resource(path, mediaType) { + cacheControl = CacheControl.maxAge(365, TimeUnit.DAYS).headerValue + } + } + + private fun resource( + path: String, + mediaType: MediaType, + headers: HttpHeaders.() -> Unit = {}, + ): ResponseEntity { + val resourcePath = javaClass.getResource(path)?.path + ?: return ResponseEntity.internalServerError().build() + + val resource = FileSystemResource(resourcePath) + val headers = HttpHeaders().apply { + contentType = mediaType + headers() + } + + return ResponseEntity(resource, headers, HttpStatus.OK) + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index e01e6e5e..921f9315 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,4 +19,5 @@ include(":executors") include(":indexation") include(":common") include(":dependencies") -include(":cache-maker") \ No newline at end of file +include(":cache-maker") +include(":resource-server") \ No newline at end of file diff --git a/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt b/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt index 4ae6d472..a01b8611 100644 --- a/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt +++ b/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt @@ -1,56 +1,25 @@ package com.compiler.server.controllers -import org.springframework.core.io.FileSystemResource -import org.springframework.core.io.Resource -import org.springframework.http.* +import org.springframework.beans.factory.annotation.Value import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController -import java.util.concurrent.TimeUnit @RestController @RequestMapping(value = ["/api/resource", "/api/**/resource"]) -class ResourceRestController { - @GetMapping("/skiko.mjs") - fun getSkikoMjs(): ResponseEntity { - return cacheableResource("/com/compiler/server/skiko.mjs", MediaType("text", "javascript")) - } - - @GetMapping("/skiko.wasm") - fun getSkikoWasm(): ResponseEntity { - return cacheableResource("/com/compiler/server/skiko.wasm", MediaType("application", "wasm")) - } - - @GetMapping("/stdlib.mjs") - fun getStdlibMjs(): ResponseEntity { - val resource = FileSystemResource("/Users/ilya.goncharov/repos/kotlin-compiler-server/COMPOSE/stdlib.uninstantiated.mjs") - val headers = HttpHeaders().apply { - contentType = MediaType("text", "javascript") - } - - return ResponseEntity(resource, headers, HttpStatus.OK) - } - - @GetMapping("/stdlib.wasm") - fun getStdlibWasm(): ResponseEntity { - val resource = FileSystemResource("/Users/ilya.goncharov/repos/kotlin-compiler-server/COMPOSE/stdlib.wasm") - val headers = HttpHeaders().apply { - contentType = MediaType("application", "wasm") +class ResourceRestController( + @Value("\${skiko.version}") private val skikoVersion: String, + @Value("\${dependencies.compose.wasm}") private val dependenciesComposeWasm: String, +) { + @Suppress("unused") + @GetMapping("/skiko") + fun getVersionedSkikoMjs(): String { + return skikoVersion } - return ResponseEntity(resource, headers, HttpStatus.OK) - } - - private fun cacheableResource(path: String, mediaType: MediaType): ResponseEntity { - val resourcePath = javaClass.getResource(path)?.path - ?: return ResponseEntity.internalServerError().build() - - val resource = FileSystemResource(resourcePath) - val headers = HttpHeaders().apply { - contentType = mediaType + @GetMapping("/stdlib") + fun getStdlibMjs(): String { + return dependenciesComposeWasm } - - return ResponseEntity(resource, headers, HttpStatus.OK) - } } From 13f28482a0c5e1969af282935633efc06e4e4031 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 21 Jan 2025 19:20:02 +0100 Subject: [PATCH 11/31] Add test of resources server --- resource-server/build.gradle.kts | 32 +++---- .../com/compiler/server/SkikoResourceTest.kt | 83 +++++++++++++++++++ 2 files changed, 94 insertions(+), 21 deletions(-) create mode 100644 resource-server/src/test/kotlin/com/compiler/server/SkikoResourceTest.kt diff --git a/resource-server/build.gradle.kts b/resource-server/build.gradle.kts index d30f2cc3..aab551fe 100644 --- a/resource-server/build.gradle.kts +++ b/resource-server/build.gradle.kts @@ -53,27 +53,9 @@ val kotlinComposeWasmStdlib: Configuration by configurations.creating { dependencies { implementation("org.springframework.boot:spring-boot-starter-web") -// implementation(libs.springfox.boot.starter) -// implementation(libs.aws.springboot.container) -// implementation(libs.junit) -// implementation(libs.logback.logstash.encoder) -// implementation(libs.intellij.trove4j) -// implementation(libs.kotlin.reflect) -// implementation(libs.bundles.kotlin.stdlib) -// implementation(libs.kotlin.test) -// implementation(libs.kotlin.compiler) -// implementation(libs.kotlin.script.runtime) -// implementation(libs.kotlin.compiler.ide) { -// isTransitive = false -// } -// implementation(libs.kotlin.core) -// implementation(project(":executors", configuration = "default")) -// implementation(project(":common", configuration = "default")) -// -// testImplementation("org.springframework.boot:spring-boot-starter-test") { -// exclude(group = "org.junit.vintage", module = "junit-vintage-engine") -// } -// testImplementation(libs.kotlinx.coroutines.test) + testImplementation("org.springframework.boot:spring-boot-starter-test") { + exclude(group = "org.junit.vintage", module = "junit-vintage-engine") + } resourceDependency(libs.skiko.js.wasm.runtime) kotlinComposeWasmStdlib(project(":cache-maker")) @@ -112,4 +94,12 @@ tasks.named("processResources") { from(kotlinComposeWasmStdlib) { into("com/compiler/server") } +} + +tasks.withType { + useJUnitPlatform() + javaLauncher.set(javaToolchains.launcherFor { + languageVersion.set(JavaLanguageVersion.of(17)) + vendor.set(JvmVendorSpec.AMAZON) + }) } \ No newline at end of file diff --git a/resource-server/src/test/kotlin/com/compiler/server/SkikoResourceTest.kt b/resource-server/src/test/kotlin/com/compiler/server/SkikoResourceTest.kt new file mode 100644 index 00000000..cde6a5e7 --- /dev/null +++ b/resource-server/src/test/kotlin/com/compiler/server/SkikoResourceTest.kt @@ -0,0 +1,83 @@ +package com.compiler.server + +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Value +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.http.HttpHeaders +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders +import org.springframework.test.web.servlet.result.MockMvcResultMatchers +import java.util.concurrent.TimeUnit + +@SpringBootTest +@AutoConfigureMockMvc +class SkikoResourceTest { + @Autowired + private lateinit var mockMvc: MockMvc + + @Value("\${skiko.version}") + private lateinit var skikoVersion: String + + @Value("\${dependencies.compose.wasm}") + private lateinit var stdlibHash: String + + @Test + fun `test caching headers for skiko mjs resource`() { + testCachingHeadersForResource( + "/api/resource/skiko-$skikoVersion.mjs", + "text/javascript" + ) + } + + @Test + fun `test caching headers for skiko wasm resource`() { + testCachingHeadersForResource( + "/api/resource/skiko-$skikoVersion.wasm", + "application/wasm" + ) + } + + @Test + fun `test caching headers for stdlib mjs resource`() { + testCachingHeadersForResource( + "/api/resource/stdlib-$stdlibHash.mjs", + "text/javascript" + ) + } + + @Test + fun `test caching headers for stdlib wasm resource`() { + testCachingHeadersForResource( + "/api/resource/stdlib-$stdlibHash.wasm", + "application/wasm" + ) + } + + private fun testCachingHeadersForResource( + resourceUrl: String, + contentType: String + ) { + val expectedCacheControl = "max-age=${TimeUnit.DAYS.toSeconds(365)}" + + mockMvc + .perform(MockMvcRequestBuilders.get(resourceUrl)) + .andExpect(MockMvcResultMatchers.status().isOk) // HTTP 200 status + .andExpect( + MockMvcResultMatchers.header().exists(HttpHeaders.CACHE_CONTROL) + ) + .andExpect( + MockMvcResultMatchers.header().string( + HttpHeaders.CACHE_CONTROL, + expectedCacheControl + ) + ) + .andExpect( + MockMvcResultMatchers.header().string( + HttpHeaders.CONTENT_TYPE, + contentType + ) + ) + } +} \ No newline at end of file From 8f4d761ea0677698a357fb0163de3d6ae5d06b10 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 21 Jan 2025 19:40:47 +0100 Subject: [PATCH 12/31] Add test of resources server --- cache-maker/build.gradle.kts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cache-maker/build.gradle.kts b/cache-maker/build.gradle.kts index 015fb7ab..e51aa022 100644 --- a/cache-maker/build.gradle.kts +++ b/cache-maker/build.gradle.kts @@ -25,10 +25,12 @@ kotlin { val composeWasmStdlib: Provider = layout.buildDirectory .dir("compose-wasm-stdlib-output") val composeWasmStdlibTypeInfo: Provider = composeWasmStdlib - .map { it.file("compose-wasm-stdlib-output/stdlib.typeinfo.bin") } + .map { it.file("stdlib.typeinfo.bin") } val buildComposeWasmStdlibModule by tasks.registering(Exec::class) { + inputs.files(configurations.named("wasmJsRuntimeClasspath")) + workingDir = rootDir executable = "${project.name}/docker-build-incremental-cache.sh" From 443b46551fde5bc54dbc55041b769952205f2562 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 21 Jan 2025 20:04:49 +0100 Subject: [PATCH 13/31] Microfix --- buildSrc/src/main/kotlin/PropertiesUpdater.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/PropertiesUpdater.kt b/buildSrc/src/main/kotlin/PropertiesUpdater.kt index 7f235885..95eb2eed 100644 --- a/buildSrc/src/main/kotlin/PropertiesUpdater.kt +++ b/buildSrc/src/main/kotlin/PropertiesUpdater.kt @@ -12,7 +12,7 @@ import java.security.MessageDigest abstract class ComposeWasmPropertiesUpdater : DefaultTask() { - @get:InputFile + @get:Input abstract val propertiesPath: Property @get:InputFile From 36fb8053579d2693474f50cb3e0ab13c6e56e23d Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 21 Jan 2025 20:38:51 +0100 Subject: [PATCH 14/31] Microfix #2 --- cache-maker/build.gradle.kts | 5 +++++ resource-server/build.gradle.kts | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cache-maker/build.gradle.kts b/cache-maker/build.gradle.kts index e51aa022..184191fc 100644 --- a/cache-maker/build.gradle.kts +++ b/cache-maker/build.gradle.kts @@ -86,3 +86,8 @@ kotlinComposeWasmStdlibTypeInfo.outgoing.variants.create("typeinfo") { builtBy(prepareTypeInfoIntoComposeWasmCache) } } + +// we don't need to build cache-maker +tasks.named("build") { + dependsOn.clear() +} diff --git a/resource-server/build.gradle.kts b/resource-server/build.gradle.kts index aab551fe..b500ae08 100644 --- a/resource-server/build.gradle.kts +++ b/resource-server/build.gradle.kts @@ -72,7 +72,13 @@ val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdat val applicationProperties = applicationPropertiesFile.absolutePath propertiesPath.set(applicationProperties) - typeInfoFile.set(kotlinComposeWasmStdlibTypeInfo.singleFile) + val composeWasmStdlibTypeInfo: FileCollection = kotlinComposeWasmStdlibTypeInfo + + typeInfoFile.fileProvider( + provider { + composeWasmStdlibTypeInfo.singleFile + } + ) if (!applicationPropertiesFile.exists()) { applicationPropertiesFile.createNewFile() From 10cc00e61e2ee2b0d8710eb1455cab6bd742beb8 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 21 Jan 2025 20:55:19 +0100 Subject: [PATCH 15/31] Microfix #3 --- build.gradle.kts | 5 +++++ resource-server/build.gradle.kts | 16 +++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index eebaa4f2..ba6b86dc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,6 +2,8 @@ import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.springframework.boot.gradle.tasks.bundling.BootJar +import java.io.FileInputStream +import java.util.Properties val policy: String by System.getProperties() @@ -166,7 +168,10 @@ val buildLambda by tasks.creating(Zip::class) { from(tasks.processResources) { eachFile { if (name == propertyFile) { + val properties = Properties().apply { load(FileInputStream(file)) } + val composeWasmHash = properties.get("dependencies.compose.wasm") file.writeText(propertyFileContent) + file.appendText("\ndependencies.compose.wasm=$composeWasmHash") } } } diff --git a/resource-server/build.gradle.kts b/resource-server/build.gradle.kts index b500ae08..256d997d 100644 --- a/resource-server/build.gradle.kts +++ b/resource-server/build.gradle.kts @@ -1,6 +1,8 @@ import org.gradle.kotlin.dsl.support.serviceOf import org.gradle.kotlin.dsl.withType import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import java.nio.file.Files +import kotlin.io.path.createFile plugins { alias(libs.plugins.spring.dependency.management) @@ -68,9 +70,13 @@ val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdat propertiesMap.put("server.port", "8081") propertiesMap.put("skiko.version", libs.versions.skiko.get()) - val applicationPropertiesFile = projectDir.resolve("src/main/resources/application.properties") - val applicationProperties = applicationPropertiesFile.absolutePath - propertiesPath.set(applicationProperties) + val applicationPropertiesPath = projectDir.resolve("src/main/resources/application.properties") + + if (!applicationPropertiesPath.exists()) { + applicationPropertiesPath.createNewFile() + } + + propertiesPath.set(applicationPropertiesPath.normalize().absolutePath) val composeWasmStdlibTypeInfo: FileCollection = kotlinComposeWasmStdlibTypeInfo @@ -79,10 +85,6 @@ val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdat composeWasmStdlibTypeInfo.singleFile } ) - - if (!applicationPropertiesFile.exists()) { - applicationPropertiesFile.createNewFile() - } } tasks.withType { From 837348de14bdd3218fcde52a25067b4cdfac33a8 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 21 Jan 2025 20:58:48 +0100 Subject: [PATCH 16/31] Microfix #4 --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 921f9315..33417244 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -20,4 +20,4 @@ include(":indexation") include(":common") include(":dependencies") include(":cache-maker") -include(":resource-server") \ No newline at end of file +//include(":resource-server") \ No newline at end of file From 64faf919eb0cb99762eb0b70fd80c3b002454cec Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 21 Jan 2025 21:07:02 +0100 Subject: [PATCH 17/31] Microfix #5 --- resource-server/build.gradle.kts | 30 +++++++++++++++--------------- settings.gradle.kts | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/resource-server/build.gradle.kts b/resource-server/build.gradle.kts index 256d997d..a790699d 100644 --- a/resource-server/build.gradle.kts +++ b/resource-server/build.gradle.kts @@ -70,21 +70,21 @@ val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdat propertiesMap.put("server.port", "8081") propertiesMap.put("skiko.version", libs.versions.skiko.get()) - val applicationPropertiesPath = projectDir.resolve("src/main/resources/application.properties") - - if (!applicationPropertiesPath.exists()) { - applicationPropertiesPath.createNewFile() - } - - propertiesPath.set(applicationPropertiesPath.normalize().absolutePath) - - val composeWasmStdlibTypeInfo: FileCollection = kotlinComposeWasmStdlibTypeInfo - - typeInfoFile.fileProvider( - provider { - composeWasmStdlibTypeInfo.singleFile - } - ) +// val applicationPropertiesPath = projectDir.resolve("src/main/resources/application.properties") +// +// if (!applicationPropertiesPath.exists()) { +// applicationPropertiesPath.createNewFile() +// } +// +// propertiesPath.set(applicationPropertiesPath.normalize().absolutePath) +// +// val composeWasmStdlibTypeInfo: FileCollection = kotlinComposeWasmStdlibTypeInfo +// +// typeInfoFile.fileProvider( +// provider { +// composeWasmStdlibTypeInfo.singleFile +// } +// ) } tasks.withType { diff --git a/settings.gradle.kts b/settings.gradle.kts index 33417244..921f9315 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -20,4 +20,4 @@ include(":indexation") include(":common") include(":dependencies") include(":cache-maker") -//include(":resource-server") \ No newline at end of file +include(":resource-server") \ No newline at end of file From 697a23007a71bfd1b7cb8d7fa4e9c66458e62aee Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 21 Jan 2025 21:12:36 +0100 Subject: [PATCH 18/31] Microfix #6 --- resource-server/build.gradle.kts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/resource-server/build.gradle.kts b/resource-server/build.gradle.kts index a790699d..fa2f6234 100644 --- a/resource-server/build.gradle.kts +++ b/resource-server/build.gradle.kts @@ -70,12 +70,12 @@ val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdat propertiesMap.put("server.port", "8081") propertiesMap.put("skiko.version", libs.versions.skiko.get()) -// val applicationPropertiesPath = projectDir.resolve("src/main/resources/application.properties") -// -// if (!applicationPropertiesPath.exists()) { -// applicationPropertiesPath.createNewFile() -// } -// + val applicationPropertiesPath = projectDir.resolve("src/main/resources/application.properties") + + if (!applicationPropertiesPath.exists()) { + applicationPropertiesPath.createNewFile() + } + // propertiesPath.set(applicationPropertiesPath.normalize().absolutePath) // // val composeWasmStdlibTypeInfo: FileCollection = kotlinComposeWasmStdlibTypeInfo From 273ac14f49b99b8eb99713b6ac581e6862f63a65 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 21 Jan 2025 21:17:31 +0100 Subject: [PATCH 19/31] Microfix #7 --- resource-server/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resource-server/build.gradle.kts b/resource-server/build.gradle.kts index fa2f6234..46b8f393 100644 --- a/resource-server/build.gradle.kts +++ b/resource-server/build.gradle.kts @@ -73,7 +73,7 @@ val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdat val applicationPropertiesPath = projectDir.resolve("src/main/resources/application.properties") if (!applicationPropertiesPath.exists()) { - applicationPropertiesPath.createNewFile() +// applicationPropertiesPath.createNewFile() } // propertiesPath.set(applicationPropertiesPath.normalize().absolutePath) From ea488cf226c9216526e84a941991e178662cc49c Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 21 Jan 2025 21:24:02 +0100 Subject: [PATCH 20/31] Microfix #8 --- buildSrc/src/main/kotlin/PropertiesUpdater.kt | 2 +- resource-server/build.gradle.kts | 25 ++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/buildSrc/src/main/kotlin/PropertiesUpdater.kt b/buildSrc/src/main/kotlin/PropertiesUpdater.kt index 95eb2eed..e99ffcaa 100644 --- a/buildSrc/src/main/kotlin/PropertiesUpdater.kt +++ b/buildSrc/src/main/kotlin/PropertiesUpdater.kt @@ -26,7 +26,7 @@ abstract class ComposeWasmPropertiesUpdater : DefaultTask() { @TaskAction fun updateProperties() { - val file = File(propertiesPath.get()) + val file = updatedPropertiesFile.get().asFile propertiesMap.get().let { if (it.isNotEmpty()) { diff --git a/resource-server/build.gradle.kts b/resource-server/build.gradle.kts index 46b8f393..b8abf2dd 100644 --- a/resource-server/build.gradle.kts +++ b/resource-server/build.gradle.kts @@ -71,20 +71,21 @@ val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdat propertiesMap.put("skiko.version", libs.versions.skiko.get()) val applicationPropertiesPath = projectDir.resolve("src/main/resources/application.properties") - - if (!applicationPropertiesPath.exists()) { +// +// if (!applicationPropertiesPath.exists()) { +// applicationPropertiesPath.parentFile.mkdirs() // applicationPropertiesPath.createNewFile() - } +// } -// propertiesPath.set(applicationPropertiesPath.normalize().absolutePath) -// -// val composeWasmStdlibTypeInfo: FileCollection = kotlinComposeWasmStdlibTypeInfo -// -// typeInfoFile.fileProvider( -// provider { -// composeWasmStdlibTypeInfo.singleFile -// } -// ) + propertiesPath.set(applicationPropertiesPath.normalize().absolutePath) + + val composeWasmStdlibTypeInfo: FileCollection = kotlinComposeWasmStdlibTypeInfo + + typeInfoFile.fileProvider( + provider { + composeWasmStdlibTypeInfo.singleFile + } + ) } tasks.withType { From af10d266c2a7d980e099b12c4001a1b4a1eb2d1c Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Tue, 21 Jan 2025 21:28:18 +0100 Subject: [PATCH 21/31] Microfix #9 --- resource-server/build.gradle.kts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/resource-server/build.gradle.kts b/resource-server/build.gradle.kts index b8abf2dd..39f187db 100644 --- a/resource-server/build.gradle.kts +++ b/resource-server/build.gradle.kts @@ -71,11 +71,6 @@ val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdat propertiesMap.put("skiko.version", libs.versions.skiko.get()) val applicationPropertiesPath = projectDir.resolve("src/main/resources/application.properties") -// -// if (!applicationPropertiesPath.exists()) { -// applicationPropertiesPath.parentFile.mkdirs() -// applicationPropertiesPath.createNewFile() -// } propertiesPath.set(applicationPropertiesPath.normalize().absolutePath) From 232c8e5ede346f10bcedcb4de9a3a8148edb1191 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Thu, 6 Mar 2025 16:00:35 +0100 Subject: [PATCH 22/31] Fix after version upgrade --- build.gradle.kts | 3 ++ cache-maker/build.gradle.kts | 7 ++-- .../server/common/components/CliUtils.kt | 33 ++----------------- .../common/components/KotlinEnvironment.kt | 7 ++-- gradle/libs.versions.toml | 4 +-- .../src/main/kotlin/WebIndexationBuilder.kt | 3 +- resource-server/build.gradle.kts | 2 ++ .../controllers/ResourceRestController.kt | 4 +-- settings.gradle.kts | 2 ++ .../components/KotlinToJSTranslator.kt | 1 - 10 files changed, 24 insertions(+), 42 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index ba6b86dc..42b29fb2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,6 +33,7 @@ allprojects { maven("https://repo.spring.io/snapshot") maven("https://repo.spring.io/milestone") maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-ide") + maven("https://packages.jetbrains.team/maven/p/kt/dev/") maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev") maven("https://cache-redirector.jetbrains.com/jetbrains.bintray.com/intellij-third-party-dependencies") maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-ide-plugin-dependencies") @@ -186,6 +187,7 @@ val buildLambda by tasks.creating(Zip::class) { from(libJVMFolder) { into(libJVM) } from(compilerPluginsForJVMFolder) {into(compilerPluginsForJVM)} from(libComposeWasmCompilerPluginsFolder) { into(libComposeWasmCompilerPlugins) } + dependsOn(kotlinComposeWasmStdlibTypeInfo) from(kotlinComposeWasmStdlibTypeInfo) { into(cachesComposeWasm) } into("lib") { from(configurations.compileClasspath) { exclude("tomcat-embed-*") } @@ -193,6 +195,7 @@ val buildLambda by tasks.creating(Zip::class) { } tasks.named("processResources") { + dependsOn(kotlinComposeWasmStdlibTypeInfo) dependsOn(composeWasmPropertiesUpdater) } diff --git a/cache-maker/build.gradle.kts b/cache-maker/build.gradle.kts index 184191fc..af331071 100644 --- a/cache-maker/build.gradle.kts +++ b/cache-maker/build.gradle.kts @@ -8,6 +8,7 @@ kotlin { binaries.executable().forEach { it.linkTask.configure { compilerOptions.freeCompilerArgs.add("-Xir-dce=false") + compilerOptions.freeCompilerArgs.add("-Xwasm-multimodule-mode=master") } } } @@ -25,7 +26,7 @@ kotlin { val composeWasmStdlib: Provider = layout.buildDirectory .dir("compose-wasm-stdlib-output") val composeWasmStdlibTypeInfo: Provider = composeWasmStdlib - .map { it.file("stdlib.typeinfo.bin") } + .map { it.file("stdlib_master.wasm") } val buildComposeWasmStdlibModule by tasks.registering(Exec::class) { @@ -70,7 +71,7 @@ kotlinComposeWasmStdlibTypeInfo.outgoing.variants.create("stdlib") { } artifact(composeWasmStdlib) { - builtBy(prepareTypeInfoIntoComposeWasmCache) + builtBy(buildComposeWasmStdlibModule) } } @@ -82,7 +83,7 @@ kotlinComposeWasmStdlibTypeInfo.outgoing.variants.create("typeinfo") { ) } - artifact(cachesComposeWasmFolder.file("stdlib.typeinfo.bin")) { + artifact(composeWasmStdlibTypeInfo) { builtBy(prepareTypeInfoIntoComposeWasmCache) } } diff --git a/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt b/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt index 8466fc20..316ae7b8 100644 --- a/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt +++ b/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt @@ -51,9 +51,7 @@ fun compileWasmArgs( "-ir-output-name=$moduleName", ).also { if (icDir != null) { - typeInfoArg(icDir, log)?.let { stdlibTypeInfoArg -> - it.add(stdlibTypeInfoArg) - } + it.add("-Xwasm-multimodule-mode=slave") } } + compilerPluginsArgs @@ -67,7 +65,6 @@ fun linkWasmArgs( icDir: Path?, outputDir: Path, debugInfo: Boolean, - log: (String) -> Unit, ): List { return mutableListOf( "-Xreport-all-warnings", @@ -82,37 +79,11 @@ fun linkWasmArgs( if (debugInfo) it.add("-Xwasm-generate-wat") if (icDir != null) { - typeInfoArg(icDir, log)?.let { stdlibTypeInfoArg -> - it.add(stdlibTypeInfoArg) - } + it.add("-Xwasm-multimodule-mode=slave") } else { it.add("-Xir-dce") } } } -private fun typeInfoArg( - icDir: Path, - log: (String) -> Unit, -): String? { - val allTypeInfoFiles = icDir.toFile().listFiles() ?: run { - log("No typeinfo files in $icDir, probably you need to run :cache-maker:prepareTypeInfoIntoComposeWasmCache task") - return null - } - - val stdlibTypeInfo = allTypeInfoFiles - .firstOrNull { file -> file.name.endsWith(".typeinfo.bin") } - - if (stdlibTypeInfo == null) { - log("No typeinfo files in $icDir, probably you need to run :cache-maker:prepareTypeInfoIntoComposeWasmCache task") - return null - } - - if (allTypeInfoFiles.size > 1) { - log("There are more than 1 typeinfo files in $icDir: ${allTypeInfoFiles.joinToString(", ") { it.name }}") - } - - return "-Xwasm-typeinfo-file=${stdlibTypeInfo.normalize().absolutePath}" -} - val PATH_SEPARATOR: String = File.pathSeparator diff --git a/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironment.kt b/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironment.kt index 60c8d3bc..a3ab766b 100644 --- a/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironment.kt +++ b/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironment.kt @@ -87,6 +87,8 @@ class KotlinEnvironment( return f(environment) } + val disposable = Disposer.newDisposable() + private val configuration = createConfiguration() val jsConfiguration: CompilerConfiguration = configuration.copy().apply { put(CommonConfigurationKeys.MODULE_NAME, "playground") @@ -111,12 +113,13 @@ class KotlinEnvironment( COMPOSE_WASM_COMPILER_PLUGINS, composeWasmCompilerPluginOptions, emptyList(), - this + this, + disposable ) } private val environment = KotlinCoreEnvironment.createForProduction( - projectDisposable = Disposer.newDisposable(), + projectDisposable = disposable, configuration = configuration.copy(), configFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES ) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ee1e2fa1..a320b7cd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] -kotlin = "2.2.0-dev-1011" -kotlinWasmStdlibCompiler = "2.2.0-dev-1010" +kotlin = "2.2.0-dev-8507" +kotlinWasmStdlibCompiler = "2.2.0-dev-8507" kotlinIdeVersion = "1.9.20-506" kotlinIdeVersionWithSuffix = "231-1.9.20-506-IJ8109.175" spring-boot = "2.7.10" diff --git a/indexation/src/main/kotlin/WebIndexationBuilder.kt b/indexation/src/main/kotlin/WebIndexationBuilder.kt index 77be751f..064658c2 100644 --- a/indexation/src/main/kotlin/WebIndexationBuilder.kt +++ b/indexation/src/main/kotlin/WebIndexationBuilder.kt @@ -29,7 +29,8 @@ class WebIndexationBuilder( compilerPlugins, compilerPluginOptions, emptyList(), - configuration + configuration, + kotlinEnvironment.disposable ) } val sourceModule = prepareAnalyzedSourceModule( diff --git a/resource-server/build.gradle.kts b/resource-server/build.gradle.kts index 39f187db..13b8c21c 100644 --- a/resource-server/build.gradle.kts +++ b/resource-server/build.gradle.kts @@ -84,10 +84,12 @@ val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdat } tasks.withType { + dependsOn(kotlinComposeWasmStdlibTypeInfo) dependsOn(composeWasmPropertiesUpdater) } tasks.named("processResources") { + dependsOn(kotlinComposeWasmStdlibTypeInfo) dependsOn(composeWasmPropertiesUpdater) val archiveOperation = project.serviceOf() from(resourceDependency.map { diff --git a/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt b/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt index 6f170333..be717bd7 100644 --- a/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt +++ b/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt @@ -40,7 +40,7 @@ class ResourceRestController( if (hash != dependenciesComposeWasm) { throw IllegalArgumentException("Unexpected stdlib") } - return cacheableResource("/com/compiler/server/stdlib.uninstantiated.mjs", MediaType("text", "javascript")) + return cacheableResource("/com/compiler/server/stdlib_master.uninstantiated.mjs", MediaType("text", "javascript")) } @GetMapping("/stdlib-{hash}.wasm") @@ -48,7 +48,7 @@ class ResourceRestController( if (hash != dependenciesComposeWasm) { throw IllegalArgumentException("Unexpected stdlib") } - return cacheableResource("/com/compiler/server/stdlib.wasm", MediaType("application", "wasm")) + return cacheableResource("/com/compiler/server/stdlib_master.wasm", MediaType("application", "wasm")) } private fun cacheableResource(path: String, mediaType: MediaType): ResponseEntity { diff --git a/settings.gradle.kts b/settings.gradle.kts index 921f9315..ceecfaf1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,6 +7,8 @@ pluginManagement { maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev") + + maven("https://packages.jetbrains.team/maven/p/kt/dev/") } } plugins { diff --git a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt index 47b2e908..702ff7c2 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt @@ -188,7 +188,6 @@ class KotlinToJSTranslator( icDir, outputDir, debugInfo, - log::warn, ) ) } From 19088f73ae40e22a1096343912a0ec1831ae52e9 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Thu, 6 Mar 2025 18:57:55 +0100 Subject: [PATCH 23/31] Adopt #1 --- build.gradle.kts | 16 ++-- buildSrc/src/main/kotlin/CacheAttribute.kt | 2 +- buildSrc/src/main/kotlin/PropertiesUpdater.kt | 4 +- buildSrc/src/main/kotlin/properties.kt | 7 +- cache-maker/build.gradle.kts | 10 +-- .../server/common/components/CliUtils.kt | 12 +-- .../common/components/KotlinEnvironment.kt | 1 - .../KotlinEnvironmentConfiguration.kt | 2 - resource-server/build.gradle.kts | 21 ++++- .../controllers/ResourceRestController.kt | 20 +---- .../compiler/components/KotlinEnvironment.kt | 3 - .../components/KotlinToJSTranslator.kt | 77 +++++++++---------- .../compiler/components/WasmParameters.kt | 3 - .../configuration/ApplicationConfiguration.kt | 14 +--- .../controllers/CompilerRestController.kt | 12 ++- .../KotlinPlaygroundRestController.kt | 8 +- .../compiler/server/model/bean/CachesFile.kt | 5 -- .../server/service/KotlinProjectExecutor.kt | 32 ++++++-- .../server/generator/TestProjectRunner.kt | 1 + 19 files changed, 114 insertions(+), 136 deletions(-) delete mode 100644 src/main/kotlin/com/compiler/server/model/bean/CachesFile.kt diff --git a/build.gradle.kts b/build.gradle.kts index 42b29fb2..9d2e3912 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -64,7 +64,7 @@ setOf( } -val kotlinComposeWasmStdlibTypeInfo: Configuration by configurations.creating { +val kotlinComposeWasmStdlibWasmFile: Configuration by configurations.creating { isTransitive = false isCanBeResolved = true isCanBeConsumed = false @@ -75,7 +75,7 @@ val kotlinComposeWasmStdlibTypeInfo: Configuration by configurations.creating { ) attribute( CacheAttribute.cacheAttribute, - CacheAttribute.TYPEINFO + CacheAttribute.WASM ) } } @@ -106,7 +106,7 @@ dependencies { } testImplementation(libs.kotlinx.coroutines.test) - kotlinComposeWasmStdlibTypeInfo(project(":cache-maker")) + kotlinComposeWasmStdlibWasmFile(project(":cache-maker")) } fun buildPropertyFile() { @@ -131,7 +131,6 @@ fun generateProperties(prefix: String = "") = """ libraries.folder.compose-wasm=${prefix + libComposeWasm} libraries.folder.compose-wasm-compiler-plugins=${prefix + libComposeWasmCompilerPlugins} libraries.folder.compiler-plugins=${prefix + compilerPluginsForJVM} - caches.folder.compose-wasm=${prefix + cachesComposeWasm} spring.mvc.pathmatch.matching-strategy=ant_path_matcher server.compression.enabled=true server.compression.mime-types=application/json,text/javascript,application/wasm @@ -139,9 +138,9 @@ fun generateProperties(prefix: String = "") = """ """.trimIndent() val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdater::class) { - dependsOn(kotlinComposeWasmStdlibTypeInfo) + dependsOn(kotlinComposeWasmStdlibWasmFile) propertiesPath.set(rootDir.resolve("src/main/resources/${propertyFile}").absolutePath) - typeInfoFile.set(kotlinComposeWasmStdlibTypeInfo.singleFile) + hashableFile.set(kotlinComposeWasmStdlibWasmFile.singleFile) } tasks.withType { @@ -150,7 +149,6 @@ tasks.withType { } dependsOn(":executors:jar") dependsOn(":indexation:run") - dependsOn(kotlinComposeWasmStdlibTypeInfo) dependsOn(composeWasmPropertiesUpdater) buildPropertyFile() } @@ -187,15 +185,13 @@ val buildLambda by tasks.creating(Zip::class) { from(libJVMFolder) { into(libJVM) } from(compilerPluginsForJVMFolder) {into(compilerPluginsForJVM)} from(libComposeWasmCompilerPluginsFolder) { into(libComposeWasmCompilerPlugins) } - dependsOn(kotlinComposeWasmStdlibTypeInfo) - from(kotlinComposeWasmStdlibTypeInfo) { into(cachesComposeWasm) } + dependsOn(kotlinComposeWasmStdlibWasmFile) into("lib") { from(configurations.compileClasspath) { exclude("tomcat-embed-*") } } } tasks.named("processResources") { - dependsOn(kotlinComposeWasmStdlibTypeInfo) dependsOn(composeWasmPropertiesUpdater) } diff --git a/buildSrc/src/main/kotlin/CacheAttribute.kt b/buildSrc/src/main/kotlin/CacheAttribute.kt index 78af16d3..f78422bc 100644 --- a/buildSrc/src/main/kotlin/CacheAttribute.kt +++ b/buildSrc/src/main/kotlin/CacheAttribute.kt @@ -2,7 +2,7 @@ import org.gradle.api.attributes.Attribute enum class CacheAttribute { FULL, - TYPEINFO; + WASM; companion object { val cacheAttribute = Attribute.of("org.jetbrains.kotlin-compiler-server.cache", CacheAttribute::class.java) diff --git a/buildSrc/src/main/kotlin/PropertiesUpdater.kt b/buildSrc/src/main/kotlin/PropertiesUpdater.kt index e99ffcaa..14ddaa06 100644 --- a/buildSrc/src/main/kotlin/PropertiesUpdater.kt +++ b/buildSrc/src/main/kotlin/PropertiesUpdater.kt @@ -16,7 +16,7 @@ abstract class ComposeWasmPropertiesUpdater : DefaultTask() { abstract val propertiesPath: Property @get:InputFile - abstract val typeInfoFile: RegularFileProperty + abstract val hashableFile: RegularFileProperty @get:Input abstract val propertiesMap: MapProperty @@ -38,7 +38,7 @@ abstract class ComposeWasmPropertiesUpdater : DefaultTask() { } file.appendText( - "\ndependencies.compose.wasm=${hashFileContent(typeInfoFile.get().asFile.absolutePath)}" + "\ndependencies.compose.wasm=${hashFileContent(hashableFile.get().asFile.absolutePath)}" ) } } diff --git a/buildSrc/src/main/kotlin/properties.kt b/buildSrc/src/main/kotlin/properties.kt index 6c641beb..3dbab459 100644 --- a/buildSrc/src/main/kotlin/properties.kt +++ b/buildSrc/src/main/kotlin/properties.kt @@ -25,8 +25,6 @@ val Project.libComposeWasm get() = "$kotlinVersion-compose-wasm" val Project.libComposeWasmCompilerPlugins get() = "$kotlinVersion-compose-wasm-compiler-plugins" -val Project.cachesComposeWasm - get() = "$kotlinVersion-caches-compose-wasm" val Project.libJVMFolder get() = rootProject.layout.projectDirectory.dir(libJVM) @@ -44,7 +42,4 @@ val Project.libComposeWasmFolder get() = rootProject.layout.projectDirectory.dir(libComposeWasm) val Project.libComposeWasmCompilerPluginsFolder - get() = rootProject.layout.projectDirectory.dir(libComposeWasmCompilerPlugins) - -val Project.cachesComposeWasmFolder - get() = rootProject.layout.projectDirectory.dir(cachesComposeWasm) \ No newline at end of file + get() = rootProject.layout.projectDirectory.dir(libComposeWasmCompilerPlugins) \ No newline at end of file diff --git a/cache-maker/build.gradle.kts b/cache-maker/build.gradle.kts index af331071..709a0820 100644 --- a/cache-maker/build.gradle.kts +++ b/cache-maker/build.gradle.kts @@ -44,12 +44,6 @@ val buildComposeWasmStdlibModule by tasks.registering(Exec::class) { args(lambdaPrefix, outputDir.get().asFile.normalize().absolutePath) } -val prepareTypeInfoIntoComposeWasmCache by tasks.registering(Sync::class) { - dependsOn(buildComposeWasmStdlibModule) - from(composeWasmStdlibTypeInfo) - into(cachesComposeWasmFolder) -} - val kotlinComposeWasmStdlibTypeInfo: Configuration by configurations.creating { isTransitive = false isCanBeResolved = false @@ -79,12 +73,12 @@ kotlinComposeWasmStdlibTypeInfo.outgoing.variants.create("typeinfo") { attributes { attribute( CacheAttribute.cacheAttribute, - CacheAttribute.TYPEINFO + CacheAttribute.WASM ) } artifact(composeWasmStdlibTypeInfo) { - builtBy(prepareTypeInfoIntoComposeWasmCache) + builtBy(buildComposeWasmStdlibModule) } } diff --git a/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt b/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt index 316ae7b8..00db05bf 100644 --- a/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt +++ b/common/src/main/kotlin/com/compiler/server/common/components/CliUtils.kt @@ -29,8 +29,6 @@ fun compileWasmArgs( compilerPlugins: List, compilerPluginOptions: List, dependencies: List, - icDir: Path?, - log: (String) -> Unit, ): List { val compilerPluginsArgs: List = compilerPlugins .takeIf { it.isNotEmpty() } @@ -49,11 +47,7 @@ fun compileWasmArgs( "-libraries=${dependencies.joinToString(PATH_SEPARATOR)}", "-ir-output-dir=$klibPath", "-ir-output-name=$moduleName", - ).also { - if (icDir != null) { - it.add("-Xwasm-multimodule-mode=slave") - } - } + compilerPluginsArgs + ) + compilerPluginsArgs return filePaths + additionalCompilerArgumentsForKLib } @@ -62,7 +56,7 @@ fun linkWasmArgs( moduleName: String, klibPath: String, dependencies: List, - icDir: Path?, + multiModule: Boolean, outputDir: Path, debugInfo: Boolean, ): List { @@ -78,7 +72,7 @@ fun linkWasmArgs( ).also { if (debugInfo) it.add("-Xwasm-generate-wat") - if (icDir != null) { + if (multiModule) { it.add("-Xwasm-multimodule-mode=slave") } else { it.add("-Xir-dce") diff --git a/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironment.kt b/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironment.kt index a3ab766b..685157ed 100644 --- a/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironment.kt +++ b/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironment.kt @@ -33,7 +33,6 @@ class KotlinEnvironment( composeWasmCompilerPlugins: List, val compilerPlugins: List = emptyList(), composeWasmCompilerPluginsOptions: List, - val composeWasmCache: File, ) { companion object { /** diff --git a/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironmentConfiguration.kt b/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironmentConfiguration.kt index 43110fce..b93fb7c9 100644 --- a/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironmentConfiguration.kt +++ b/common/src/main/kotlin/com/compiler/server/common/components/KotlinEnvironmentConfiguration.kt @@ -13,7 +13,6 @@ class KotlinEnvironmentConfiguration( val wasmFile = File("$fileName-wasm") val composeWasmFile = File("$fileName-compose-wasm") val composeWasmCompilerPluginsFile = File("$fileName-compose-wasm-compiler-plugins") - val composeWasmCachesFile = File("$fileName-caches-compose-wasm") val classPath = listOfNotNull(jvmFile) .flatMap { @@ -40,7 +39,6 @@ class KotlinEnvironmentConfiguration( "false" ), ), - composeWasmCachesFile ) } } diff --git a/resource-server/build.gradle.kts b/resource-server/build.gradle.kts index 13b8c21c..695799a1 100644 --- a/resource-server/build.gradle.kts +++ b/resource-server/build.gradle.kts @@ -1,8 +1,8 @@ import org.gradle.kotlin.dsl.support.serviceOf import org.gradle.kotlin.dsl.withType import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import java.nio.file.Files -import kotlin.io.path.createFile +import java.io.FileInputStream +import java.util.Properties plugins { alias(libs.plugins.spring.dependency.management) @@ -32,7 +32,7 @@ val kotlinComposeWasmStdlibTypeInfo: Configuration by configurations.creating { ) attribute( CacheAttribute.cacheAttribute, - CacheAttribute.TYPEINFO + CacheAttribute.WASM ) } } @@ -76,7 +76,7 @@ val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdat val composeWasmStdlibTypeInfo: FileCollection = kotlinComposeWasmStdlibTypeInfo - typeInfoFile.fileProvider( + hashableFile.fileProvider( provider { composeWasmStdlibTypeInfo.singleFile } @@ -88,6 +88,8 @@ tasks.withType { dependsOn(composeWasmPropertiesUpdater) } +val skikoVersion = libs.versions.skiko + tasks.named("processResources") { dependsOn(kotlinComposeWasmStdlibTypeInfo) dependsOn(composeWasmPropertiesUpdater) @@ -96,9 +98,20 @@ tasks.named("processResources") { archiveOperation.zipTree(it) }) { into("com/compiler/server") + rename("skiko\\.(.*)", "skiko-${skikoVersion.get()}.\$1") } + + val propertiesFile = composeWasmPropertiesUpdater.flatMap { it.updatedPropertiesFile } + from(kotlinComposeWasmStdlib) { into("com/compiler/server") + val properties = FileInputStream(propertiesFile.get().asFile).use { + Properties().apply { + load(it) + } + } + + rename("stdlib_master\\.(.*)", "stdlib-${properties["dependencies.compose.wasm"]}.\$1") } } diff --git a/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt b/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt index be717bd7..28f2bce4 100644 --- a/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt +++ b/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt @@ -20,35 +20,23 @@ class ResourceRestController( @Suppress("unused") @GetMapping("/skiko-{version}.mjs") fun getSkikoMjs(@PathVariable version: String): ResponseEntity { - if (version != skikoVersion) { - throw IllegalArgumentException("Unexpected skiko version") - } - return cacheableResource("/com/compiler/server/skiko.mjs", MediaType("text", "javascript")) + return cacheableResource("/com/compiler/server/skiko-$version.mjs", MediaType("text", "javascript")) } @Suppress("unused") @GetMapping("/skiko-{version}.wasm") fun getSkikoWasm(@PathVariable version: String): ResponseEntity { - if (version != skikoVersion) { - throw IllegalArgumentException("Unexpected skiko version") - } - return cacheableResource("/com/compiler/server/skiko.wasm", MediaType("application", "wasm")) + return cacheableResource("/com/compiler/server/skiko-$version.wasm", MediaType("application", "wasm")) } @GetMapping("/stdlib-{hash}.mjs") fun getStdlibMjs(@PathVariable hash: String): ResponseEntity { - if (hash != dependenciesComposeWasm) { - throw IllegalArgumentException("Unexpected stdlib") - } - return cacheableResource("/com/compiler/server/stdlib_master.uninstantiated.mjs", MediaType("text", "javascript")) + return cacheableResource("/com/compiler/server/stdlib-$hash.uninstantiated.mjs", MediaType("text", "javascript")) } @GetMapping("/stdlib-{hash}.wasm") fun getStdlibWasm(@PathVariable hash: String): ResponseEntity { - if (hash != dependenciesComposeWasm) { - throw IllegalArgumentException("Unexpected stdlib") - } - return cacheableResource("/com/compiler/server/stdlib_master.wasm", MediaType("application", "wasm")) + return cacheableResource("/com/compiler/server/stdlib-$hash.wasm", MediaType("application", "wasm")) } private fun cacheableResource(path: String, mediaType: MediaType): ResponseEntity { diff --git a/src/main/kotlin/com/compiler/server/compiler/components/KotlinEnvironment.kt b/src/main/kotlin/com/compiler/server/compiler/components/KotlinEnvironment.kt index 6ef414ec..5704082c 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/KotlinEnvironment.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/KotlinEnvironment.kt @@ -1,7 +1,6 @@ package com.compiler.server.compiler.components import com.compiler.server.common.components.KotlinEnvironment -import com.compiler.server.model.bean.CachesFile import com.compiler.server.model.bean.LibrariesFile import component.CompilerPluginOption import org.springframework.context.annotation.Bean @@ -10,7 +9,6 @@ import org.springframework.context.annotation.Configuration @Configuration class KotlinEnvironmentConfiguration( val librariesFile: LibrariesFile, - val cachesFile: CachesFile, ) { @Bean fun kotlinEnvironment(): KotlinEnvironment { @@ -41,7 +39,6 @@ class KotlinEnvironmentConfiguration( "false" ), ), - cachesFile.composeWasm ) } } diff --git a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt index 702ff7c2..dcaf3958 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt @@ -51,13 +51,14 @@ class KotlinToJSTranslator( fun translateWasm( files: List, debugInfo: Boolean, + multiModule: Boolean, projectType: ProjectType, translate: ( List, List, List, List, - File?, + Boolean, Boolean, ) -> CompilationResult ): TranslationResultWithJsCode { @@ -67,13 +68,11 @@ class KotlinToJSTranslator( kotlinEnvironment.WASM_LIBRARIES, emptyList(), emptyList(), - null ) ProjectType.COMPOSE_WASM -> WasmParameters( kotlinEnvironment.COMPOSE_WASM_LIBRARIES, kotlinEnvironment.COMPOSE_WASM_COMPILER_PLUGINS, kotlinEnvironment.composeWasmCompilerPluginOptions, - kotlinEnvironment.composeWasmCache, ) else -> throw IllegalStateException("Wasm should have wasm or compose-wasm project type") } @@ -82,7 +81,7 @@ class KotlinToJSTranslator( parameters.dependencies, parameters.plugins, parameters.pluginOptions, - parameters.cacheDir, + multiModule, debugInfo, ) val wasmCompilationOutput = when (compilationResult) { @@ -152,7 +151,7 @@ class KotlinToJSTranslator( dependencies: List, compilerPlugins: List, compilerPluginOptions: List, - cacheDir: File?, + multiModule: Boolean, debugInfo: Boolean, ): CompilationResult = usingTempDirectory { inputDir -> @@ -163,45 +162,39 @@ class KotlinToJSTranslator( val filePaths = ioFiles.map { it.toFile().canonicalPath } val klibPath = (outputDir / "klib").toFile().canonicalPath - val compileAction: (icDir: Path?) -> CompilationResult = { icDir -> - k2JSCompiler.tryCompilation( - inputDir, - ioFiles, - compileWasmArgs( - moduleName, - filePaths, - klibPath, - compilerPlugins, - compilerPluginOptions, - dependencies, - icDir, - log::warn, - ) + k2JSCompiler.tryCompilation( + inputDir, + ioFiles, + compileWasmArgs( + moduleName, + filePaths, + klibPath, + compilerPlugins, + compilerPluginOptions, + dependencies, ) - .flatMap { - k2JSCompiler.tryCompilation( - inputDir, ioFiles, - linkWasmArgs( - moduleName, - klibPath, - dependencies, - icDir, - outputDir, - debugInfo, - ) - ) - } - .map { - WasmTranslationSuccessfulOutput( - jsCode = (outputDir / "wasm" / "$moduleName.uninstantiated.mjs").readText(), - jsInstantiated = (outputDir / "wasm" / "$moduleName.mjs").readText(), - wasm = (outputDir / "wasm" / "$moduleName.wasm").readBytes(), - wat = if (debugInfo) (outputDir / "wasm" / "$moduleName.wat").readText() else null, + ) + .flatMap { + k2JSCompiler.tryCompilation( + inputDir, ioFiles, + linkWasmArgs( + moduleName, + klibPath, + dependencies, + multiModule, + outputDir, + debugInfo, ) - } - } - - compileAction(cacheDir?.toPath()) + ) + } + .map { + WasmTranslationSuccessfulOutput( + jsCode = (outputDir / "wasm" / "$moduleName.uninstantiated.mjs").readText(), + jsInstantiated = (outputDir / "wasm" / "$moduleName.mjs").readText(), + wasm = (outputDir / "wasm" / "$moduleName.wasm").readBytes(), + wat = if (debugInfo) (outputDir / "wasm" / "$moduleName.wat").readText() else null, + ) + } } } } diff --git a/src/main/kotlin/com/compiler/server/compiler/components/WasmParameters.kt b/src/main/kotlin/com/compiler/server/compiler/components/WasmParameters.kt index 2cf0f2fa..4c7f4361 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/WasmParameters.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/WasmParameters.kt @@ -1,10 +1,7 @@ package com.compiler.server.compiler.components -import java.io.File - data class WasmParameters( val dependencies: List, val plugins: List, val pluginOptions: List, - val cacheDir: File? ) \ No newline at end of file diff --git a/src/main/kotlin/com/compiler/server/configuration/ApplicationConfiguration.kt b/src/main/kotlin/com/compiler/server/configuration/ApplicationConfiguration.kt index 9727c7ed..09c7ecaa 100644 --- a/src/main/kotlin/com/compiler/server/configuration/ApplicationConfiguration.kt +++ b/src/main/kotlin/com/compiler/server/configuration/ApplicationConfiguration.kt @@ -1,6 +1,5 @@ package com.compiler.server.configuration -import com.compiler.server.model.bean.CachesFile import com.compiler.server.model.bean.LibrariesFile import com.compiler.server.model.bean.VersionInfo import org.springframework.beans.factory.annotation.Value @@ -13,11 +12,10 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer import java.io.File @Configuration -@EnableConfigurationProperties(value = [LibrariesFolderProperties::class, CachesFolderProperties::class]) +@EnableConfigurationProperties(value = [LibrariesFolderProperties::class]) class ApplicationConfiguration( @Value("\${kotlin.version}") private val version: String, private val librariesFolderProperties: LibrariesFolderProperties, - private val cachesFolderProperties: CachesFolderProperties, ) : WebMvcConfigurer { override fun addFormatters(registry: FormatterRegistry) { registry.addConverter(ProjectConverter()) @@ -38,11 +36,6 @@ class ApplicationConfiguration( File(librariesFolderProperties.composeWasmCompilerPlugins), File(librariesFolderProperties.compilerPlugins) ) - - @Bean - fun cachesFiles() = CachesFile( - File(cachesFolderProperties.composeWasm) - ) } @ConfigurationProperties(prefix = "libraries.folder") @@ -53,9 +46,4 @@ class LibrariesFolderProperties { lateinit var composeWasm: String lateinit var composeWasmCompilerPlugins: String lateinit var compilerPlugins: String -} - -@ConfigurationProperties(prefix = "caches.folder") -class CachesFolderProperties { - lateinit var composeWasm: String } \ No newline at end of file diff --git a/src/main/kotlin/com/compiler/server/controllers/CompilerRestController.kt b/src/main/kotlin/com/compiler/server/controllers/CompilerRestController.kt index 92c219c5..422d6617 100644 --- a/src/main/kotlin/com/compiler/server/controllers/CompilerRestController.kt +++ b/src/main/kotlin/com/compiler/server/controllers/CompilerRestController.kt @@ -32,8 +32,16 @@ class CompilerRestController(private val kotlinProjectExecutor: KotlinProjectExe ): TranslationResultWithJsCode { return when (KotlinTranslatableCompiler.valueOf(compiler.uppercase().replace("-", "_"))) { KotlinTranslatableCompiler.JS -> kotlinProjectExecutor.convertToJsIr(project) - KotlinTranslatableCompiler.WASM -> kotlinProjectExecutor.convertToWasm(project, debugInfo) - KotlinTranslatableCompiler.COMPOSE_WASM -> kotlinProjectExecutor.convertToWasm(project, debugInfo) + KotlinTranslatableCompiler.WASM -> kotlinProjectExecutor.convertToWasm( + project, + debugInfo, + multiModule = false, + ) + KotlinTranslatableCompiler.COMPOSE_WASM -> kotlinProjectExecutor.convertToWasm( + project, + debugInfo, + multiModule = true, + ) } } diff --git a/src/main/kotlin/com/compiler/server/controllers/KotlinPlaygroundRestController.kt b/src/main/kotlin/com/compiler/server/controllers/KotlinPlaygroundRestController.kt index ffcc3d6f..32e659e4 100644 --- a/src/main/kotlin/com/compiler/server/controllers/KotlinPlaygroundRestController.kt +++ b/src/main/kotlin/com/compiler/server/controllers/KotlinPlaygroundRestController.kt @@ -46,9 +46,15 @@ class KotlinPlaygroundRestController(private val kotlinProjectExecutor: KotlinPr kotlinProjectExecutor.convertToJsIr( project, ) - ProjectType.WASM, ProjectType.COMPOSE_WASM -> kotlinProjectExecutor.convertToWasm( + ProjectType.WASM -> kotlinProjectExecutor.convertToWasm( project, debugInfo = false, + multiModule = false, + ) + ProjectType.COMPOSE_WASM -> kotlinProjectExecutor.convertToWasm( + project, + debugInfo = false, + multiModule = true, ) ProjectType.JUNIT -> kotlinProjectExecutor.test(project, addByteCode) } diff --git a/src/main/kotlin/com/compiler/server/model/bean/CachesFile.kt b/src/main/kotlin/com/compiler/server/model/bean/CachesFile.kt deleted file mode 100644 index 83f11d07..00000000 --- a/src/main/kotlin/com/compiler/server/model/bean/CachesFile.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.compiler.server.model.bean - -import java.io.File - -class CachesFile(val composeWasm: File) \ No newline at end of file diff --git a/src/main/kotlin/com/compiler/server/service/KotlinProjectExecutor.kt b/src/main/kotlin/com/compiler/server/service/KotlinProjectExecutor.kt index f331563d..f5a5dbbc 100644 --- a/src/main/kotlin/com/compiler/server/service/KotlinProjectExecutor.kt +++ b/src/main/kotlin/com/compiler/server/service/KotlinProjectExecutor.kt @@ -49,8 +49,17 @@ class KotlinProjectExecutor( return kotlinCompiler.compile(files) } - fun convertToWasm(project: Project, debugInfo: Boolean): TranslationResultWithJsCode { - return convertWasmWithConverter(project, debugInfo, kotlinToJSTranslator::doTranslateWithWasm) + fun convertToWasm( + project: Project, + debugInfo: Boolean, + multiModule: Boolean, + ): TranslationResultWithJsCode { + return convertWasmWithConverter( + project, + debugInfo, + multiModule, + kotlinToJSTranslator::doTranslateWithWasm + ) } fun complete(project: Project, line: Int, character: Int): List { @@ -72,11 +81,16 @@ class KotlinProjectExecutor( convertToJsIr( project, ).compilerDiagnostics - ProjectType.WASM, ProjectType.COMPOSE_WASM -> - convertToWasm( - project, - debugInfo = false, - ).compilerDiagnostics + ProjectType.WASM -> convertToWasm( + project, + debugInfo = false, + multiModule = false, + ).compilerDiagnostics + ProjectType.COMPOSE_WASM -> convertToWasm( + project, + debugInfo = false, + multiModule = true, + ).compilerDiagnostics } } catch (e: Exception) { log.warn("Exception in getting highlight. Project: $project", e) @@ -102,12 +116,13 @@ class KotlinProjectExecutor( private fun convertWasmWithConverter( project: Project, debugInfo: Boolean, + multiModule: Boolean, converter: ( List, List, List, List, - File?, + Boolean, Boolean, ) -> CompilationResult ): TranslationResultWithJsCode { @@ -116,6 +131,7 @@ class KotlinProjectExecutor( kotlinToJSTranslator.translateWasm( files, debugInfo, + multiModule, project.confType, converter ) diff --git a/src/test/kotlin/com/compiler/server/generator/TestProjectRunner.kt b/src/test/kotlin/com/compiler/server/generator/TestProjectRunner.kt index 16991de6..d9451a84 100644 --- a/src/test/kotlin/com/compiler/server/generator/TestProjectRunner.kt +++ b/src/test/kotlin/com/compiler/server/generator/TestProjectRunner.kt @@ -188,6 +188,7 @@ class TestProjectRunner { val result = kotlinProjectExecutor.convertToWasm( project, debugInfo = true, + multiModule = false, ) if (result !is TranslationWasmResult) { From 78ce52783362a578cfd6afaba8a2a22ec73fc139 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Thu, 6 Mar 2025 19:52:09 +0100 Subject: [PATCH 24/31] Adopt #2 --- build.gradle.kts | 90 +++++++++---------- buildSrc/src/main/kotlin/PropertiesUpdater.kt | 10 +-- resource-server/build.gradle.kts | 41 +++++---- 3 files changed, 68 insertions(+), 73 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 9d2e3912..f5732442 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,8 +2,6 @@ import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.springframework.boot.gradle.tasks.bundling.BootJar -import java.io.FileInputStream -import java.util.Properties val policy: String by System.getProperties() @@ -63,8 +61,7 @@ setOf( } } - -val kotlinComposeWasmStdlibWasmFile: Configuration by configurations.creating { +val kotlinComposeWasmStdlibFile: Configuration by configurations.creating { isTransitive = false isCanBeResolved = true isCanBeConsumed = false @@ -106,41 +103,46 @@ dependencies { } testImplementation(libs.kotlinx.coroutines.test) - kotlinComposeWasmStdlibWasmFile(project(":cache-maker")) + kotlinComposeWasmStdlibFile(project(":cache-maker")) } -fun buildPropertyFile() { - rootDir.resolve("src/main/resources/${propertyFile}").apply { - println("Generate properties into $absolutePath") - parentFile.mkdirs() - writeText(generateProperties()) +fun Project.generateProperties( + prefix: String = "", +): Map = mapOf( + "kotlin.version" to kotlinVersion, + "policy.file" to prefix + policy, + "indexes.file" to prefix + indexes, + "indexesJs.file" to prefix + indexesJs, + "indexesWasm.file" to prefix + indexesWasm, + "indexesComposeWasm.file" to prefix + indexesComposeWasm, + "libraries.folder.jvm" to prefix + libJVM, + "libraries.folder.js" to prefix + libJS, + "libraries.folder.wasm" to prefix + libWasm, + "libraries.folder.compose-wasm" to prefix + libComposeWasm, + "libraries.folder.compose-wasm-compiler-plugins" to prefix + libComposeWasmCompilerPlugins, + "libraries.folder.compiler-plugins" to prefix + compilerPluginsForJVM, + "spring.mvc.pathmatch.matching-strategy" to "ant_path_matcher", + "server.compression.enabled" to "true", + "server.compression.mime-types" to "application/json,text/javascript,application/wasm", + "skiko.version" to libs.versions.skiko.get(), +) + +val propertiesGenerator by tasks.registering(PropertiesGenerator::class) { + dependsOn(kotlinComposeWasmStdlibFile) + propertiesFile.fileValue(rootDir.resolve("src/main/resources/${propertyFile}")) + hashableFile.set(kotlinComposeWasmStdlibFile.singleFile) + generateProperties().forEach { (name, value) -> + propertiesMap.put(name, value) } } -fun generateProperties(prefix: String = "") = """ - # this file is autogenerated by build.gradle.kts - kotlin.version=${kotlinVersion} - policy.file=${prefix + policy} - indexes.file=${prefix + indexes} - indexesJs.file=${prefix + indexesJs} - indexesWasm.file=${prefix + indexesWasm} - indexesComposeWasm.file=${prefix + indexesComposeWasm} - libraries.folder.jvm=${prefix + libJVM} - libraries.folder.js=${prefix + libJS} - libraries.folder.wasm=${prefix + libWasm} - libraries.folder.compose-wasm=${prefix + libComposeWasm} - libraries.folder.compose-wasm-compiler-plugins=${prefix + libComposeWasmCompilerPlugins} - libraries.folder.compiler-plugins=${prefix + compilerPluginsForJVM} - spring.mvc.pathmatch.matching-strategy=ant_path_matcher - server.compression.enabled=true - server.compression.mime-types=application/json,text/javascript,application/wasm - skiko.version=${libs.versions.skiko.get()} -""".trimIndent() - -val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdater::class) { - dependsOn(kotlinComposeWasmStdlibWasmFile) - propertiesPath.set(rootDir.resolve("src/main/resources/${propertyFile}").absolutePath) - hashableFile.set(kotlinComposeWasmStdlibWasmFile.singleFile) +val lambdaPropertiesGenerator by tasks.registering(PropertiesGenerator::class) { + dependsOn(kotlinComposeWasmStdlibFile) + propertiesFile.set(layout.buildDirectory.file("tmp/propertiesGenerator/${propertyFile}")) + hashableFile.set(kotlinComposeWasmStdlibFile.singleFile) + generateProperties(lambdaPrefix).forEach { (name, value) -> + propertiesMap.put(name, value) + } } tasks.withType { @@ -149,8 +151,7 @@ tasks.withType { } dependsOn(":executors:jar") dependsOn(":indexation:run") - dependsOn(composeWasmPropertiesUpdater) - buildPropertyFile() + dependsOn(propertiesGenerator) } println("Using Kotlin compiler ${libs.versions.kotlin.get()}") @@ -161,19 +162,12 @@ tasks.withType { val buildLambda by tasks.creating(Zip::class) { val propertyFile = propertyFile - val propertyFileContent = generateProperties(lambdaPrefix) from(tasks.compileKotlin) from(tasks.processResources) { - eachFile { - if (name == propertyFile) { - val properties = Properties().apply { load(FileInputStream(file)) } - val composeWasmHash = properties.get("dependencies.compose.wasm") - file.writeText(propertyFileContent) - file.appendText("\ndependencies.compose.wasm=$composeWasmHash") - } - } + exclude(propertyFile) } + from(lambdaPropertiesGenerator) from(policy) from(indexes) from(indexesJs) @@ -183,16 +177,16 @@ val buildLambda by tasks.creating(Zip::class) { from(libWasmFolder) { into(libWasm) } from(libComposeWasmFolder) { into(libComposeWasm) } from(libJVMFolder) { into(libJVM) } - from(compilerPluginsForJVMFolder) {into(compilerPluginsForJVM)} + from(compilerPluginsForJVMFolder) { into(compilerPluginsForJVM) } from(libComposeWasmCompilerPluginsFolder) { into(libComposeWasmCompilerPlugins) } - dependsOn(kotlinComposeWasmStdlibWasmFile) + dependsOn(kotlinComposeWasmStdlibFile) into("lib") { from(configurations.compileClasspath) { exclude("tomcat-embed-*") } } } tasks.named("processResources") { - dependsOn(composeWasmPropertiesUpdater) + dependsOn(propertiesGenerator) } tasks.withType { diff --git a/buildSrc/src/main/kotlin/PropertiesUpdater.kt b/buildSrc/src/main/kotlin/PropertiesUpdater.kt index 14ddaa06..b93405e8 100644 --- a/buildSrc/src/main/kotlin/PropertiesUpdater.kt +++ b/buildSrc/src/main/kotlin/PropertiesUpdater.kt @@ -1,7 +1,6 @@ import org.gradle.api.DefaultTask import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.MapProperty -import org.gradle.api.provider.Property import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.OutputFile @@ -10,10 +9,7 @@ import java.io.File import java.io.FileInputStream import java.security.MessageDigest -abstract class ComposeWasmPropertiesUpdater : DefaultTask() { - - @get:Input - abstract val propertiesPath: Property +abstract class PropertiesGenerator : DefaultTask() { @get:InputFile abstract val hashableFile: RegularFileProperty @@ -22,11 +18,11 @@ abstract class ComposeWasmPropertiesUpdater : DefaultTask() { abstract val propertiesMap: MapProperty @get:OutputFile - val updatedPropertiesFile: RegularFileProperty = project.objects.fileProperty().fileProvider(propertiesPath.map { File(it) }) + abstract val propertiesFile: RegularFileProperty @TaskAction fun updateProperties() { - val file = updatedPropertiesFile.get().asFile + val file = propertiesFile.get().asFile propertiesMap.get().let { if (it.isNotEmpty()) { diff --git a/resource-server/build.gradle.kts b/resource-server/build.gradle.kts index 695799a1..19a40407 100644 --- a/resource-server/build.gradle.kts +++ b/resource-server/build.gradle.kts @@ -1,8 +1,7 @@ import org.gradle.kotlin.dsl.support.serviceOf -import org.gradle.kotlin.dsl.withType import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import java.io.FileInputStream -import java.util.Properties +import java.util.* plugins { alias(libs.plugins.spring.dependency.management) @@ -21,7 +20,7 @@ val resourceDependency: Configuration by configurations.creating { isCanBeConsumed = false } -val kotlinComposeWasmStdlibTypeInfo: Configuration by configurations.creating { +val kotlinComposeWasmStdlibFile: Configuration by configurations.creating { isTransitive = false isCanBeResolved = true isCanBeConsumed = false @@ -61,20 +60,20 @@ dependencies { resourceDependency(libs.skiko.js.wasm.runtime) kotlinComposeWasmStdlib(project(":cache-maker")) - kotlinComposeWasmStdlibTypeInfo(project(":cache-maker")) + kotlinComposeWasmStdlibFile(project(":cache-maker")) } -val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdater::class) { - dependsOn(kotlinComposeWasmStdlibTypeInfo) +val propertiesGenerator by tasks.registering(PropertiesGenerator::class) { + dependsOn(kotlinComposeWasmStdlibFile) propertiesMap.put("spring.mvc.pathmatch.matching-strategy", "ant_path_matcher") propertiesMap.put("server.port", "8081") propertiesMap.put("skiko.version", libs.versions.skiko.get()) val applicationPropertiesPath = projectDir.resolve("src/main/resources/application.properties") - propertiesPath.set(applicationPropertiesPath.normalize().absolutePath) + propertiesFile.fileValue(applicationPropertiesPath) - val composeWasmStdlibTypeInfo: FileCollection = kotlinComposeWasmStdlibTypeInfo + val composeWasmStdlibTypeInfo: FileCollection = kotlinComposeWasmStdlibFile hashableFile.fileProvider( provider { @@ -84,15 +83,15 @@ val composeWasmPropertiesUpdater by tasks.registering(ComposeWasmPropertiesUpdat } tasks.withType { - dependsOn(kotlinComposeWasmStdlibTypeInfo) - dependsOn(composeWasmPropertiesUpdater) + dependsOn(kotlinComposeWasmStdlibFile) + dependsOn(propertiesGenerator) } val skikoVersion = libs.versions.skiko tasks.named("processResources") { - dependsOn(kotlinComposeWasmStdlibTypeInfo) - dependsOn(composeWasmPropertiesUpdater) + dependsOn(kotlinComposeWasmStdlibFile) + dependsOn(propertiesGenerator) val archiveOperation = project.serviceOf() from(resourceDependency.map { archiveOperation.zipTree(it) @@ -101,17 +100,23 @@ tasks.named("processResources") { rename("skiko\\.(.*)", "skiko-${skikoVersion.get()}.\$1") } - val propertiesFile = composeWasmPropertiesUpdater.flatMap { it.updatedPropertiesFile } + val propertiesFile = propertiesGenerator.flatMap { it.propertiesFile } from(kotlinComposeWasmStdlib) { into("com/compiler/server") - val properties = FileInputStream(propertiesFile.get().asFile).use { - Properties().apply { - load(it) + + rename { original -> + val properties = FileInputStream(propertiesFile.get().asFile).use { + Properties().apply { + load(it) + } } - } + val regex = Regex("stdlib_master\\.(.*)") + regex.find(original)?.groupValues?.get(1)?.let { extension -> + "stdlib-${properties["dependencies.compose.wasm"]}.$extension" + } ?: original - rename("stdlib_master\\.(.*)", "stdlib-${properties["dependencies.compose.wasm"]}.\$1") + } } } From 00c3a1cf8328b3071f773c9127abe9087e782d43 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Fri, 7 Mar 2025 13:05:53 +0100 Subject: [PATCH 25/31] Adopt #3 --- build.gradle.kts | 31 +++++++++- buildSrc/src/main/kotlin/CategoryAttribute.kt | 5 +- cache-maker/Dockerfile | 20 ------- cache-maker/build.gradle.kts | 58 +++++++++++-------- cache-maker/docker-build-incremental-cache.sh | 24 -------- gradle/libs.versions.toml | 1 - resource-server/build.gradle.kts | 38 ++++++++++-- 7 files changed, 98 insertions(+), 79 deletions(-) delete mode 100644 cache-maker/Dockerfile delete mode 100755 cache-maker/docker-build-incremental-cache.sh diff --git a/build.gradle.kts b/build.gradle.kts index f5732442..751c1ec5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -77,6 +77,18 @@ val kotlinComposeWasmStdlibFile: Configuration by configurations.creating { } } +val composeWasmStaticResources: Configuration by configurations.creating { + isTransitive = false + isCanBeResolved = true + isCanBeConsumed = false + attributes { + attribute( + Category.CATEGORY_ATTRIBUTE, + objects.categoryComposeWasmResources + ) + } +} + dependencies { annotationProcessor("org.springframework:spring-context-indexer") implementation("com.google.code.gson:gson") @@ -104,6 +116,7 @@ dependencies { testImplementation(libs.kotlinx.coroutines.test) kotlinComposeWasmStdlibFile(project(":cache-maker")) + composeWasmStaticResources(project(":resource-server")) } fun Project.generateProperties( @@ -130,7 +143,11 @@ fun Project.generateProperties( val propertiesGenerator by tasks.registering(PropertiesGenerator::class) { dependsOn(kotlinComposeWasmStdlibFile) propertiesFile.fileValue(rootDir.resolve("src/main/resources/${propertyFile}")) - hashableFile.set(kotlinComposeWasmStdlibFile.singleFile) + hashableFile.fileProvider( + provider { + kotlinComposeWasmStdlibFile.singleFile + } + ) generateProperties().forEach { (name, value) -> propertiesMap.put(name, value) } @@ -139,7 +156,12 @@ val propertiesGenerator by tasks.registering(PropertiesGenerator::class) { val lambdaPropertiesGenerator by tasks.registering(PropertiesGenerator::class) { dependsOn(kotlinComposeWasmStdlibFile) propertiesFile.set(layout.buildDirectory.file("tmp/propertiesGenerator/${propertyFile}")) - hashableFile.set(kotlinComposeWasmStdlibFile.singleFile) + hashableFile.fileProvider( + provider { + kotlinComposeWasmStdlibFile.singleFile + } + ) + generateProperties(lambdaPrefix).forEach { (name, value) -> propertiesMap.put(name, value) } @@ -185,6 +207,11 @@ val buildLambda by tasks.creating(Zip::class) { } } +val prepareComposeWasmResources by tasks.registering(Sync::class) { + from(composeWasmStaticResources) + into(layout.buildDirectory.dir("compose-wasm-resources")) +} + tasks.named("processResources") { dependsOn(propertiesGenerator) } diff --git a/buildSrc/src/main/kotlin/CategoryAttribute.kt b/buildSrc/src/main/kotlin/CategoryAttribute.kt index a10431af..e4f1847e 100644 --- a/buildSrc/src/main/kotlin/CategoryAttribute.kt +++ b/buildSrc/src/main/kotlin/CategoryAttribute.kt @@ -2,4 +2,7 @@ import org.gradle.api.attributes.Category import org.gradle.api.model.ObjectFactory val ObjectFactory.categoryComposeCache - get() = named(Category::class.java, "compose-cache") \ No newline at end of file + get() = named(Category::class.java, "compose-cache") + +val ObjectFactory.categoryComposeWasmResources + get() = named(Category::class.java, "compose-wasm-resources") \ No newline at end of file diff --git a/cache-maker/Dockerfile b/cache-maker/Dockerfile deleted file mode 100644 index d5738098..00000000 --- a/cache-maker/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM amazoncorretto:17 - -ARG BASE_DIR -ARG KOTLIN_VERSION - -RUN if [ -z "$KOTLIN_VERSION" ]; then \ - echo "Error: KOTLIN_VERSION argument is not set. Use docker-build-incremental-cache.sh to build the image." >&2; \ - exit 1; \ - fi - -ENV KOTLIN_VERSION=$KOTLIN_VERSION - -RUN mkdir -p $BASE_DIR -WORKDIR $BASE_DIR -ADD . $BASE_DIR - -RUN sed -i 's@kotlin = ".*"@kotlin = "'$KOTLIN_VERSION'"@g' gradle/libs.versions.toml -RUN ./gradlew clean - -RUN ./gradlew :cache-maker:compileProductionExecutableKotlinWasmJs diff --git a/cache-maker/build.gradle.kts b/cache-maker/build.gradle.kts index 709a0820..c6a078de 100644 --- a/cache-maker/build.gradle.kts +++ b/cache-maker/build.gradle.kts @@ -1,3 +1,11 @@ +@file:OptIn(ExperimentalWasmDsl::class) + +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.targets.js.binaryen.BinaryenExec +import org.jetbrains.kotlin.gradle.targets.js.binaryen.BinaryenRootEnvSpec +import org.jetbrains.kotlin.gradle.targets.js.ir.JsIrBinary +import org.jetbrains.kotlin.gradle.targets.js.ir.WasmBinary + plugins { kotlin("multiplatform") } @@ -5,11 +13,20 @@ plugins { kotlin { wasmJs { outputModuleName.set("stdlib") - binaries.executable().forEach { - it.linkTask.configure { + binaries.executable().forEach { binary: JsIrBinary -> + binary.linkTask.configure { compilerOptions.freeCompilerArgs.add("-Xir-dce=false") compilerOptions.freeCompilerArgs.add("-Xwasm-multimodule-mode=master") } + + (binary as WasmBinary).optimizeTask.configure { + inputFileProperty.fileProvider( + binary.mainFile.map { + val file = it.asFile + file.resolveSibling("${file.nameWithoutExtension}_master.wasm") + } + ) + } } } @@ -23,28 +40,19 @@ kotlin { } } -val composeWasmStdlib: Provider = layout.buildDirectory - .dir("compose-wasm-stdlib-output") -val composeWasmStdlibTypeInfo: Provider = composeWasmStdlib - .map { it.file("stdlib_master.wasm") } - -val buildComposeWasmStdlibModule by tasks.registering(Exec::class) { - - inputs.files(configurations.named("wasmJsRuntimeClasspath")) - - workingDir = rootDir - executable = "${project.name}/docker-build-incremental-cache.sh" - - val outputDir = composeWasmStdlib +val compileProductionExecutableKotlinWasmJsOptimize: TaskProvider by tasks.existing(BinaryenExec::class) { +} - inputs.file(layout.projectDirectory.file("Dockerfile")) - inputs.file(layout.projectDirectory.file("docker-build-incremental-cache.sh")) - outputs.dir(outputDir) +val composeWasmStdlib: Provider = compileProductionExecutableKotlinWasmJsOptimize + .flatMap { it.outputDirectory.locationOnly } +val composeWasmStdlibFile: Provider = composeWasmStdlib + .map { it.file("stdlib_master.wasm") } - args(lambdaPrefix, outputDir.get().asFile.normalize().absolutePath) +rootProject.plugins.withType { + rootProject.the().version = "122" } -val kotlinComposeWasmStdlibTypeInfo: Configuration by configurations.creating { +val kotlinComposeWasmStdlibFile: Configuration by configurations.creating { isTransitive = false isCanBeResolved = false isCanBeConsumed = true @@ -56,7 +64,7 @@ val kotlinComposeWasmStdlibTypeInfo: Configuration by configurations.creating { } } -kotlinComposeWasmStdlibTypeInfo.outgoing.variants.create("stdlib") { +kotlinComposeWasmStdlibFile.outgoing.variants.create("stdlib") { attributes { attribute( CacheAttribute.cacheAttribute, @@ -65,11 +73,11 @@ kotlinComposeWasmStdlibTypeInfo.outgoing.variants.create("stdlib") { } artifact(composeWasmStdlib) { - builtBy(buildComposeWasmStdlibModule) + builtBy(compileProductionExecutableKotlinWasmJsOptimize) } } -kotlinComposeWasmStdlibTypeInfo.outgoing.variants.create("typeinfo") { +kotlinComposeWasmStdlibFile.outgoing.variants.create("wasm-file") { attributes { attribute( CacheAttribute.cacheAttribute, @@ -77,8 +85,8 @@ kotlinComposeWasmStdlibTypeInfo.outgoing.variants.create("typeinfo") { ) } - artifact(composeWasmStdlibTypeInfo) { - builtBy(buildComposeWasmStdlibModule) + artifact(composeWasmStdlibFile) { + builtBy(compileProductionExecutableKotlinWasmJsOptimize) } } diff --git a/cache-maker/docker-build-incremental-cache.sh b/cache-maker/docker-build-incremental-cache.sh deleted file mode 100755 index 59f24c49..00000000 --- a/cache-maker/docker-build-incremental-cache.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -kotlinVersion=$(awk '{ if ($1 == "kotlinWasmStdlibCompiler") { gsub(/"/, "", $2); print $2; } }' FS=' = ' ./gradle/libs.versions.toml) - -baseDir=$1 -targetDir=$2 - -echo "Kotlin Version for the docker: $kotlinVersion" -echo "Base directory: $baseDir" -echo "Target directory: $targetDir" - -image_tag=my-image-name:$(date +%s) - -docker build . --file cache-maker/Dockerfile --tag $image_tag --build-arg BASE_DIR=$baseDir --build-arg KOTLIN_VERSION=$kotlinVersion - -container=$(docker create $image_tag) - -docker cp $container:$baseDir/cache-maker/build/compileSync/wasmJs/main/productionExecutable/kotlin/. $targetDir - -docker start $container -docker stop $container -docker remove $container - -docker rmi $image_tag \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a320b7cd..9da20cca 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,5 @@ [versions] kotlin = "2.2.0-dev-8507" -kotlinWasmStdlibCompiler = "2.2.0-dev-8507" kotlinIdeVersion = "1.9.20-506" kotlinIdeVersionWithSuffix = "231-1.9.20-506-IJ8109.175" spring-boot = "2.7.10" diff --git a/resource-server/build.gradle.kts b/resource-server/build.gradle.kts index 19a40407..ebba15f2 100644 --- a/resource-server/build.gradle.kts +++ b/resource-server/build.gradle.kts @@ -73,11 +73,11 @@ val propertiesGenerator by tasks.registering(PropertiesGenerator::class) { propertiesFile.fileValue(applicationPropertiesPath) - val composeWasmStdlibTypeInfo: FileCollection = kotlinComposeWasmStdlibFile + val composeWasmStdlibFile: FileCollection = kotlinComposeWasmStdlibFile hashableFile.fileProvider( provider { - composeWasmStdlibTypeInfo.singleFile + composeWasmStdlibFile.singleFile } ) } @@ -89,21 +89,24 @@ tasks.withType { val skikoVersion = libs.versions.skiko -tasks.named("processResources") { +val prepareComposeWasmResources by tasks.registering(Sync::class) { dependsOn(kotlinComposeWasmStdlibFile) dependsOn(propertiesGenerator) val archiveOperation = project.serviceOf() + + into(layout.buildDirectory.dir("tmp/prepareResources")) + from(resourceDependency.map { archiveOperation.zipTree(it) }) { - into("com/compiler/server") rename("skiko\\.(.*)", "skiko-${skikoVersion.get()}.\$1") + include("skiko.mjs", "skiko.wasm") } val propertiesFile = propertiesGenerator.flatMap { it.propertiesFile } from(kotlinComposeWasmStdlib) { - into("com/compiler/server") + include("stdlib_master.uninstantiated.mjs", "stdlib_master.wasm") rename { original -> val properties = FileInputStream(propertiesFile.get().asFile).use { @@ -111,7 +114,7 @@ tasks.named("processResources") { load(it) } } - val regex = Regex("stdlib_master\\.(.*)") + val regex = Regex("stdlib_master\\.uninstantiated\\.(.*)") regex.find(original)?.groupValues?.get(1)?.let { extension -> "stdlib-${properties["dependencies.compose.wasm"]}.$extension" } ?: original @@ -120,10 +123,33 @@ tasks.named("processResources") { } } +tasks.named("processResources") { + dependsOn(prepareComposeWasmResources) + from(prepareComposeWasmResources) { + into("com/compiler/server") + } +} + tasks.withType { useJUnitPlatform() javaLauncher.set(javaToolchains.launcherFor { languageVersion.set(JavaLanguageVersion.of(17)) vendor.set(JvmVendorSpec.AMAZON) }) +} + +val composeWasmStaticResources: Configuration by configurations.creating { + isTransitive = false + isCanBeResolved = false + isCanBeConsumed = true + attributes { + attribute( + Category.CATEGORY_ATTRIBUTE, + objects.categoryComposeWasmResources + ) + } + + outgoing.artifact(prepareComposeWasmResources) { + builtBy(prepareComposeWasmResources) + } } \ No newline at end of file From 3d4553074970e39e5d96c7f23dcb05a829b38607 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Fri, 7 Mar 2025 13:56:29 +0100 Subject: [PATCH 26/31] Adopt #4 --- build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index 751c1ec5..9c6661ce 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -205,6 +205,8 @@ val buildLambda by tasks.creating(Zip::class) { into("lib") { from(configurations.compileClasspath) { exclude("tomcat-embed-*") } } + + dependsOn(prepareComposeWasmResources) } val prepareComposeWasmResources by tasks.registering(Sync::class) { From 8e79d8bbf197de28a229b79d6d3e144ac4c645f4 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Fri, 7 Mar 2025 14:01:08 +0100 Subject: [PATCH 27/31] Adopt #5 --- build.gradle.kts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 9c6661ce..ecdf5dcf 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -182,6 +182,11 @@ tasks.withType { requiresUnpack("**/kotlinx-*.jar") } +val prepareComposeWasmResources by tasks.registering(Sync::class) { + from(composeWasmStaticResources) + into(layout.buildDirectory.dir("compose-wasm-resources")) +} + val buildLambda by tasks.creating(Zip::class) { val propertyFile = propertyFile @@ -209,11 +214,6 @@ val buildLambda by tasks.creating(Zip::class) { dependsOn(prepareComposeWasmResources) } -val prepareComposeWasmResources by tasks.registering(Sync::class) { - from(composeWasmStaticResources) - into(layout.buildDirectory.dir("compose-wasm-resources")) -} - tasks.named("processResources") { dependsOn(propertiesGenerator) } From 9cc42aa6283fef9663a68df61d29dc9513fcb979 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Fri, 7 Mar 2025 14:56:13 +0100 Subject: [PATCH 28/31] One request for resources --- .../server/controllers/ResourceRestController.kt | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt b/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt index a01b8611..fcb609bc 100644 --- a/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt +++ b/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt @@ -13,13 +13,11 @@ class ResourceRestController( @Value("\${dependencies.compose.wasm}") private val dependenciesComposeWasm: String, ) { @Suppress("unused") - @GetMapping("/skiko") - fun getVersionedSkikoMjs(): String { - return skikoVersion - } - - @GetMapping("/stdlib") - fun getStdlibMjs(): String { - return dependenciesComposeWasm + @GetMapping("/compose-wasm-versions") + fun getVersions(): Map { + return mapOf( + "skiko" to skikoVersion, + "stdlib" to dependenciesComposeWasm + ) } } From e8cfa899506f4c407b179ba1fa9880d57233a2bb Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Fri, 7 Mar 2025 14:59:17 +0100 Subject: [PATCH 29/31] Fix resource server --- .../com/compiler/server/controllers/ResourceRestController.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt b/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt index 28f2bce4..5f6a454d 100644 --- a/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt +++ b/resource-server/src/main/kotlin/com/compiler/server/controllers/ResourceRestController.kt @@ -31,7 +31,7 @@ class ResourceRestController( @GetMapping("/stdlib-{hash}.mjs") fun getStdlibMjs(@PathVariable hash: String): ResponseEntity { - return cacheableResource("/com/compiler/server/stdlib-$hash.uninstantiated.mjs", MediaType("text", "javascript")) + return cacheableResource("/com/compiler/server/stdlib-$hash.mjs", MediaType("text", "javascript")) } @GetMapping("/stdlib-{hash}.wasm") From af8bc3fefa6bdec989c97596f78f8ab99a3a647d Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Fri, 7 Mar 2025 15:06:36 +0100 Subject: [PATCH 30/31] Fix stdlib.wasm file with hash --- resource-server/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resource-server/build.gradle.kts b/resource-server/build.gradle.kts index ebba15f2..f7b4df08 100644 --- a/resource-server/build.gradle.kts +++ b/resource-server/build.gradle.kts @@ -114,8 +114,8 @@ val prepareComposeWasmResources by tasks.registering(Sync::class) { load(it) } } - val regex = Regex("stdlib_master\\.uninstantiated\\.(.*)") - regex.find(original)?.groupValues?.get(1)?.let { extension -> + val regex = Regex("stdlib_master(\\.uninstantiated)*\\.(.*)") + regex.find(original)?.groupValues?.get(2)?.let { extension -> "stdlib-${properties["dependencies.compose.wasm"]}.$extension" } ?: original From 52e4b0a0d27010cbce44dbc43612a9348f492ff2 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Fri, 7 Mar 2025 15:26:05 +0100 Subject: [PATCH 31/31] Use compiler output instead of binaryen because it may be incorrect --- cache-maker/build.gradle.kts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cache-maker/build.gradle.kts b/cache-maker/build.gradle.kts index c6a078de..950b1c4d 100644 --- a/cache-maker/build.gradle.kts +++ b/cache-maker/build.gradle.kts @@ -4,6 +4,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.targets.js.binaryen.BinaryenExec import org.jetbrains.kotlin.gradle.targets.js.binaryen.BinaryenRootEnvSpec import org.jetbrains.kotlin.gradle.targets.js.ir.JsIrBinary +import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrLink import org.jetbrains.kotlin.gradle.targets.js.ir.WasmBinary plugins { @@ -40,11 +41,11 @@ kotlin { } } -val compileProductionExecutableKotlinWasmJsOptimize: TaskProvider by tasks.existing(BinaryenExec::class) { +val compileProductionExecutableKotlinWasmJs: TaskProvider by tasks.existing(KotlinJsIrLink::class) { } -val composeWasmStdlib: Provider = compileProductionExecutableKotlinWasmJsOptimize - .flatMap { it.outputDirectory.locationOnly } +val composeWasmStdlib: Provider = compileProductionExecutableKotlinWasmJs + .flatMap { it.destinationDirectory.locationOnly } val composeWasmStdlibFile: Provider = composeWasmStdlib .map { it.file("stdlib_master.wasm") } @@ -73,7 +74,7 @@ kotlinComposeWasmStdlibFile.outgoing.variants.create("stdlib") { } artifact(composeWasmStdlib) { - builtBy(compileProductionExecutableKotlinWasmJsOptimize) + builtBy(compileProductionExecutableKotlinWasmJs) } } @@ -86,7 +87,7 @@ kotlinComposeWasmStdlibFile.outgoing.variants.create("wasm-file") { } artifact(composeWasmStdlibFile) { - builtBy(compileProductionExecutableKotlinWasmJsOptimize) + builtBy(compileProductionExecutableKotlinWasmJs) } }