Files
mhoennig ba0a1cf419
werkator build succeeded after 02:49
form example
2026-09-16 12:08:41 +02:00

93 lines
4.7 KiB
Kotlin

plugins { kotlin("multiplatform") }
fun pkgConfig(vararg flags: String): List<String> {
val result = providers.exec {
commandLine(listOf("pkg-config") + flags + listOf("gtk+-3.0", "webkit2gtk-4.1"))
isIgnoreExitValue = true
}
if (result.result.get().exitValue != 0) throw GradleException(
"Linux desktop dependencies are missing. On Ubuntu/Debian run: " +
"sudo apt install build-essential pkg-config libgtk-3-dev libwebkit2gtk-4.1-dev\n" +
result.standardError.asText.get()
)
return result.standardOutput.asText.get().trim().split(Regex("\\s+")).filter { it.isNotEmpty() }
}
val nativeDir = layout.projectDirectory.dir("src/native")
val objectFile = layout.buildDirectory.file("native/keluna.o")
val compileHost by tasks.registering(Exec::class) {
inputs.dir(nativeDir)
outputs.file(objectFile)
doFirst {
objectFile.get().asFile.parentFile.mkdirs()
commandLine(listOf("cc", "-Wall", "-Wextra", "-Werror", "-c", "-fPIC",
nativeDir.file("keluna.c").asFile.absolutePath, "-o", objectFile.get().asFile.absolutePath) + pkgConfig("--cflags"))
}
}
val generated = layout.buildDirectory.dir("generated/keluna")
val web = rootProject.layout.projectDirectory.dir("keluna-web-runtime")
val shared = rootProject.layout.projectDirectory.dir("examples/shared")
val snakeCss = rootProject.layout.projectDirectory.file("examples/snake/src/commonMain/kotlin/dev/keluna/snake/Snake.css")
val workshopCss = rootProject.layout.projectDirectory.file("examples/workshop/src/commonMain/kotlin/dev/keluna/workshop/WorkshopForm.css")
val embedWebResources by tasks.registering {
inputs.dir(web); inputs.dir(shared); inputs.file(snakeCss); inputs.file(workshopCss)
outputs.dir(generated)
doLast {
// Encode UTF-8 bytes as integer literals, avoiding Kotlin and HTML interpolation.
val css = listOf(web.file("defaults.css"), shared.file("theme.css"), shared.file("Counter.css"))
.joinToString("\n") { it.asFile.readText() }
val values = mapOf(
"browserRuntime" to web.file("runtime.js").asFile.readText(), "styles" to css,
"snakeStyles" to (web.file("defaults.css").asFile.readText() + "\n" + snakeCss.asFile.readText()),
"workshopStyles" to (web.file("defaults.css").asFile.readText() + "\n" + workshopCss.asFile.readText())
)
val source = "package dev.keluna.example\n" + values.entries.joinToString("\n") { (name, value) ->
"val $name: String = byteArrayOf(${value.toByteArray(Charsets.UTF_8).joinToString(",")}).decodeToString()"
}
generated.get().file("WebResources.kt").asFile.apply { parentFile.mkdirs(); writeText(source) }
}
}
kotlin {
linuxX64 {
compilations.getByName("main") {
cinterops.create("keluna") {
definitionFile.set(nativeDir.file("keluna.def"))
includeDirs(nativeDir)
}
compileTaskProvider.configure { dependsOn(embedWebResources) }
}
binaries {
executable { entryPoint = "dev.keluna.example.main" }
executable("snake") {
entryPoint = "dev.keluna.snake.main"
baseName = "snake"
}
executable("workshop") {
entryPoint = "dev.keluna.workshop.main"
baseName = "workshop"
}
withType<org.jetbrains.kotlin.gradle.plugin.mpp.Executable> {
linkTaskProvider.configure { dependsOn(compileHost) }
linkerOpts(objectFile.get().asFile.absolutePath)
// Host WebKitGTK/GTK can require newer glibc symbols than the
// Kotlin/Native sysroot provides. Resolve shared-library imports
// against the host runtime; executable/object symbols remain checked.
linkerOpts("--allow-shlib-undefined")
// Kotlin/Native invokes ld directly, rather than the compiler driver.
// Retain host library paths that pkg-config normally omits.
linkerOpts(pkgConfig("--keep-system-libs", "--libs").flatMap { flag ->
when {
flag == "-pthread" -> listOf("-lpthread")
flag.startsWith("-Wl,") -> flag.removePrefix("-Wl,").split(',')
else -> listOf(flag)
}
})
}
}
}
sourceSets.commonMain {
kotlin.srcDir("../examples/shared")
kotlin.srcDir(generated)
dependencies { implementation(project(":keluna-ui")); implementation(project(":keluna-runtime")); implementation(project(":examples:snake")); implementation(project(":examples:workshop")) }
}
}