Skip to content

Add IC for Compose Wasm #809

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
737a012
Add IC for Compose Wasm
ilgonmic Oct 10, 2024
24276ed
No need docker in local case
ilgonmic Nov 5, 2024
774be3f
Remove image after cache build
ilgonmic Nov 5, 2024
450acc2
Use lazy argumentProviders instead of args
ilgonmic Nov 5, 2024
3f6474c
Readonly cache
ilgonmic Nov 18, 2024
3b6b687
Remove time measure
ilgonmic Nov 18, 2024
b501e3f
Fix variant-aware configurations for Gradle
ilgonmic Dec 4, 2024
44a201c
Fix sample to be compatible with example in playground
ilgonmic Dec 4, 2024
f8907a2
First version with typeinfo
ilgonmic Jan 21, 2025
192a43f
Add resources server
ilgonmic Jan 21, 2025
70f145f
Add test of resources server
ilgonmic Jan 21, 2025
1ad372a
Add test of resources server
ilgonmic Jan 21, 2025
e6666a5
Microfix
ilgonmic Jan 21, 2025
4d62cde
Microfix #2
ilgonmic Jan 21, 2025
e9e2027
Microfix #3
ilgonmic Jan 21, 2025
8a744cc
Microfix #4
ilgonmic Jan 21, 2025
f9c5322
Microfix #5
ilgonmic Jan 21, 2025
2a531d4
Microfix #6
ilgonmic Jan 21, 2025
6272ff0
Microfix #7
ilgonmic Jan 21, 2025
2ba3afb
Microfix #8
ilgonmic Jan 21, 2025
7c01e96
Microfix #9
ilgonmic Jan 21, 2025
278c883
Fix after version upgrade
ilgonmic Mar 6, 2025
f2eb7d4
Adopt #1
ilgonmic Mar 6, 2025
1cb1d90
Adopt #2
ilgonmic Mar 6, 2025
9bcdf1f
Adopt #3
ilgonmic Mar 7, 2025
a84cd62
Adopt #4
ilgonmic Mar 7, 2025
ca5c5a9
Adopt #5
ilgonmic Mar 7, 2025
d683836
One request for resources
ilgonmic Mar 7, 2025
b0eee73
Fix resource server
ilgonmic Mar 7, 2025
da96b9d
Fix stdlib.wasm file with hash
ilgonmic Mar 7, 2025
4b7aa4d
Use compiler output instead of binaryen because it may be incorrect
ilgonmic Mar 7, 2025
4e52b2e
Fixes after merge with current master
dkrasnoff Jul 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ build/
!**/src/main/**
!**/src/test/**
src/main/resources/application.properties
resource-server/src/main/resources/application.properties

# compile artifacts
.kotlin/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ develocity {
val overriddenName = buildScanUsername.orNull
server = "https://ge.jetbrains.com/"
buildScan {

termsOfUseUrl = "https://gradle.com/help/legal-terms-of-use"
termsOfUseAgree = "yes"

publishing.onlyIf { true }
capture {
fileFingerprints = true
Expand Down
139 changes: 95 additions & 44 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import org.gradle.kotlin.dsl.support.serviceOf
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin.Companion.kotlinNodeJsEnvSpec
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
Expand All @@ -20,10 +21,15 @@ plugins {

apply<NodeJsRootPlugin>()

allprojects {
afterEvaluate {
dependencies {
dependencies {
setOf(
rootProject,
project(":common"),
project(":executors"),
project(":indexation"),
).forEach { project ->
project.afterEvaluate {
project.dependencies {
project.dependencies {
implementation(libs.jackson.module.kotlin)
implementation(libs.kotlin.idea) {
isTransitive = false
Expand All @@ -33,9 +39,32 @@ allprojects {
}
}

val resourceDependency: Configuration by configurations.creating {
val kotlinComposeWasmStdlibFile: Configuration by configurations.creating {
isTransitive = false
isCanBeResolved = true
isCanBeConsumed = false
attributes {
attribute(
Category.CATEGORY_ATTRIBUTE,
objects.categoryComposeCache
)
attribute(
CacheAttribute.cacheAttribute,
CacheAttribute.WASM
)
}
}

val composeWasmStaticResources: Configuration by configurations.creating {
isTransitive = false
isCanBeResolved = true
isCanBeConsumed = false
attributes {
attribute(
Category.CATEGORY_ATTRIBUTE,
objects.categoryComposeWasmResources
)
}
}

dependencies {
Expand Down Expand Up @@ -64,44 +93,67 @@ dependencies {
}
testImplementation(libs.kotlinx.coroutines.test)

resourceDependency(libs.skiko.js.wasm.runtime)
kotlinComposeWasmStdlibFile(project(":cache-maker"))
composeWasmStaticResources(project(":resource-server"))
}

fun buildPropertyFile() {
rootDir.resolve("src/main/resources/${propertyFile}").apply {
println("Generate properties into $absolutePath")
parentFile.mkdirs()
writeText(generateProperties())
fun Project.generateProperties(
prefix: String = "",
): Map<String, String> = 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",
"spring.main.banner-mode" to "off",
"server.compression.enabled" to "true",
"server.compression.mime-types" to "application/json,text/javascript,application/wasm",
"springdoc.swagger-ui.path" to "/api-docs/swagger-ui.html",
"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.fileProvider(
provider {
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
springdoc.swagger-ui.path: /api-docs/swagger-ui.html
""".trimIndent()
val lambdaPropertiesGenerator by tasks.registering(PropertiesGenerator::class) {
dependsOn(kotlinComposeWasmStdlibFile)
propertiesFile.set(layout.buildDirectory.file("tmp/propertiesGenerator/${propertyFile}"))
hashableFile.fileProvider(
provider {
kotlinComposeWasmStdlibFile.singleFile
}
)

generateProperties(lambdaPrefix).forEach { (name, value) ->
propertiesMap.put(name, value)
}
}

tasks.withType<KotlinCompile> {
compilerOptions {
freeCompilerArgs.set(listOf("-Xjsr305=strict"))
}
dependsOn(":executors:jar")
dependsOn(":indexation:run")
buildPropertyFile()
dependsOn(propertiesGenerator)
}
println("Using Kotlin compiler ${libs.versions.kotlin.get()}")

Expand All @@ -110,18 +162,19 @@ tasks.withType<BootJar> {
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
val propertyFileContent = generateProperties("/var/task/")

from(tasks.compileKotlin)
from(tasks.processResources) {
eachFile {
if (name == propertyFile) {
file.writeText(propertyFileContent)
}
}
exclude(propertyFile)
}
from(lambdaPropertiesGenerator)
from(policy)
from(indexes)
from(indexesJs)
Expand All @@ -131,20 +184,18 @@ 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(kotlinComposeWasmStdlibFile)
into("lib") {
from(configurations.compileClasspath) { exclude("tomcat-embed-*") }
}

dependsOn(prepareComposeWasmResources)
}

tasks.named<Copy>("processResources") {
val archiveOperation = project.serviceOf<ArchiveOperations>()
from(resourceDependency.map {
archiveOperation.zipTree(it)
}) {
into("com/compiler/server")
}
dependsOn(propertiesGenerator)
}

tasks.withType<Test> {
Expand Down
10 changes: 10 additions & 0 deletions buildSrc/src/main/kotlin/CacheAttribute.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import org.gradle.api.attributes.Attribute

enum class CacheAttribute {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With @ilgonmic we've discussed left only FULL.
Thus, the whole attribute can be deleted.

FULL,
WASM;

companion object {
val cacheAttribute = Attribute.of("org.jetbrains.kotlin-compiler-server.cache", CacheAttribute::class.java)
}
}
8 changes: 8 additions & 0 deletions buildSrc/src/main/kotlin/CategoryAttribute.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import org.gradle.api.attributes.Category
import org.gradle.api.model.ObjectFactory

val ObjectFactory.categoryComposeCache
get() = named(Category::class.java, "compose-cache")

val ObjectFactory.categoryComposeWasmResources
get() = named(Category::class.java, "compose-wasm-resources")
57 changes: 57 additions & 0 deletions buildSrc/src/main/kotlin/PropertiesUpdater.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.MapProperty
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 PropertiesGenerator : DefaultTask() {

@get:InputFile
abstract val hashableFile: RegularFileProperty

@get:Input
abstract val propertiesMap: MapProperty<String, String>

@get:OutputFile
abstract val propertiesFile: RegularFileProperty

@TaskAction
fun updateProperties() {
val file = propertiesFile.get().asFile

propertiesMap.get().let {
if (it.isNotEmpty()) {
file.writeText("")
it.forEach { (key, value) ->
file.appendText("$key=$value\n")
}
}
}

file.appendText(
"\ndependencies.compose.wasm=${hashFileContent(hashableFile.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) }
}
46 changes: 46 additions & 0 deletions buildSrc/src/main/kotlin/base-kotlin-conventions.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension

extensions.configure<KotlinProjectExtension>("kotlin") {
logger.info("For the ${project.name} we used $kotlinVersion kotlin version in this build.")

sourceSets.configureEach {
languageSettings {
val kotlinLanguageVersion = project.providers.gradleProperty("kotlin_language_version")
if (kotlinLanguageVersion.isPresent) {
languageVersion = kotlinLanguageVersion.get()
logger.info("An overriding Kotlin language version of $languageVersion was found for project ${project.name}")
}
val kotlinApiVersion = project.providers.gradleProperty("kotlin_api_version")
if (kotlinApiVersion.isPresent) {
apiVersion = kotlinApiVersion.get()
logger.info("An overriding Kotlin api version of $apiVersion was found for project ${project.name}")
}
}
}

jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(17))
vendor.set(JvmVendorSpec.AMAZON)
}
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
compilerOptions {

freeCompilerArgs.addAll(
"-Xreport-all-warnings",
"-Xrender-internal-diagnostic-names",
"-Xuse-fir-experimental-checkers"
)

allWarningsAsErrors.set(false)
extraWarnings.set(true)

// Adding additional cli options for testing purpose
project.providers.gradleProperty("kotlin_additional_cli_options").orNull?.let { options ->
options.split(" ").filter { it.isNotBlank() }.forEach {
freeCompilerArgs.add(it)
}
}
}
}
Loading
Loading