Is anyone else having issues with `compileProducti...
# compose-web
m
Is anyone else having issues with
compileProductionExecutableKotlinWebOptimize
taking a really long time? (about 15 mins on my end)
r
It's nothing unusual
m
Is there a way to disable it while working on development builds?
My build.gradle.kts for reference:
Copy code
import externals.DownloadZipTask
import org.jetbrains.kotlin.gradle.dsl.JsSourceMapEmbedMode
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrLink
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile

plugins {
    kotlin("multiplatform")
    kotlin("plugin.serialization")
    kotlin("plugin.compose")
    id("org.jetbrains.compose")
}

repositories {
    mavenLocal()
}

val sharedConfiguration: Configuration by configurations.creating {
    isCanBeConsumed = true
    isCanBeResolved = false
}

kotlin {
    wasmJs("web") {
        browser {
            commonWebpackConfig {
                sourceMaps = !project.production
                outputFileName = "index.js"
                devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply {
                    static = (static ?: mutableListOf()).apply {
                        // Serve sources to debug inside browser
                        add(project.rootDir.path)
                        add(project.projectDir.path)
                    }
                }
            }
        }
        binaries.executable()
    }

    sourceSets {
        val commonMain by getting {
            kotlin.srcDir(layout.buildDirectory.dir("generated/graphql/commonMain/kotlin"))

            dependencies {
                implementation(project(":site-common"))

                implementation(compose.ui)
                implementation(compose.foundation)
                implementation(compose.material3)
                implementation(compose.runtime)
                implementation(compose.runtimeSaveable)
                implementation(compose.animation)
                implementation(compose.animationGraphics)
                implementation(compose.components.resources)

                implementation("io.ktor:ktor-client-core:${Versions.ktor}")
                implementation("io.ktor:ktor-client-content-negotiation:${Versions.ktor}")
                implementation("io.ktor:ktor-client-websockets:${Versions.ktor}")

                implementation("org.jetbrains.kotlinx:kotlinx-datetime:${Versions.datetime}")
            }
        }

        val webMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-js:${Versions.ktor}")
            }
        }
    }
}

tasks {
    val createGraphQLBindings by registering(graphql.GenerateGraphQLTask::class) {
        schemaFallback = projectDir.resolve("src/webMain/graphql/schema.graphqls")
        outputDir = layout.buildDirectory.dir("generated/graphql/commonMain/kotlin")
        packageName = "com.martmists.template.frontend.graphql"
    }

    val downloadJetbrainsMonoFont by registering(DownloadZipTask::class) {
        outputDirectory = layout.buildDirectory.dir("downloaded/JetbrainsMono")
        url = "<https://github.com/JetBrains/JetBrainsMono/releases/download/v2.304/JetBrainsMono-2.304.zip>"
    }
    val downloadInterFont by registering(DownloadZipTask::class) {
        outputDirectory = layout.buildDirectory.dir("downloaded/Inter")
        url = "<https://github.com/rsms/inter/releases/download/v4.1/Inter-4.1.zip>"
    }
    val downloadLucideIcons by registering(DownloadZipTask::class) {
        outputDirectory = layout.buildDirectory.dir("downloaded/Lucide")
        url = "<https://github.com/lucide-icons/lucide/releases/download/0.461.0/lucide-icons-0.461.0.zip>"
    }

    val copyFonts by registering(Copy::class) {
        from(downloadJetbrainsMonoFont, downloadInterFont)
        into(layout.buildDirectory.dir("downloaded/allResources/font"))
        eachFile {
            path = path.split("/").last()
        }
        include("**/ttf/*.ttf")
    }

    val copyIcons by registering(Copy::class) {
        from(downloadLucideIcons)
        into(layout.buildDirectory.dir("downloaded/allResources/drawable"))
        eachFile {
            path = path.split("/").last()
        }
        include("**/*.svg")
    }

    // Required by gradle to add the tasks as dependencies
    val copyNonXmlValueResourcesForCommonMain by getting {
        dependsOn(copyFonts, copyIcons)
    }

    // Run these tasks on IDEA import
    rootProject.tasks.named("prepareKotlinBuildScriptModel") {
        dependsOn(
            createGraphQLBindings,
            copyFonts,
            copyIcons,
        )
    }

    withType<AbstractKotlinCompile<*>> {
        dependsOn(createGraphQLBindings)
        compilerOptions.optIn.add("kotlin.uuid.ExperimentalUuidApi")
    }

    // Not sure which I need to use for WASM
    withType<Kotlin2JsCompile> {
        compilerOptions {
            sourceMapEmbedSources = JsSourceMapEmbedMode.SOURCE_MAP_SOURCE_CONTENT_INLINING
        }
    }

    withType<KotlinJsIrLink> {
        compilerOptions {
            sourceMapEmbedSources = JsSourceMapEmbedMode.SOURCE_MAP_SOURCE_CONTENT_INLINING
        }
    }

    // For some reason gradle forces me to add these two
    named("webBrowserDevelopmentWebpack") {
        dependsOn("webProductionExecutableCompileSync")
    }

    named("webBrowserProductionWebpack") {
        dependsOn("webDevelopmentExecutableCompileSync")
    }
}

artifacts {
    add(sharedConfiguration.name, tasks.named("copyFonts"))
    add(sharedConfiguration.name, tasks.named("copyIcons"))
    // if production, use webBrowserDistribution
    // if development, use webBrowserDevelopmentExecutableDistribution
    add(sharedConfiguration.name, tasks.named("webBrowser${if (project.production) "" else "DevelopmentExecutable"}Distribution"))
}

compose {
    resources {
        customDirectory(
            "commonMain",
            layout.buildDirectory.dir("downloaded/allResources")
        )
    }
}
r
I'm using something like this:
Copy code
afterEvaluate {
    tasks.withType<BinaryenExec> {
        binaryenArgs = mutableListOf(
            "--enable-nontrapping-float-to-int",
            "--enable-gc",
            "--enable-reference-types",
            "--enable-exception-handling",
            "--enable-bulk-memory",
            "--inline-functions-with-loops",
            "--traps-never-happen",
            "--fast-math",
            "--closed-world",
            "-O0",
        )
    }
}
It configures binaryen to do nothing