Glueball is a Kotlin Multiplatform library for virtualising Kotlin code via WebAssembly.
It allows you to run the same Kotlin function either natively or virtually (via a WebAssembly VM), with a unified interface. This enables:
- In process app updates — Fix bugs instantly by downloading updated WASM binaries, bypassing app store review cycles or asking users to restart your app
- Sandboxed execution — Run untrusted or user-provided code safely within a VM
- A/B testing — Test different implementations without bloating your app with variants
- Annotate functions in
commonMainwith@Glueball - The KSP processor generates:
- A service interface with your annotated functions
- A Native implementation that calls Kotlin directly
- A Virtual implementation that runs via Chasm (a Kotlin WebAssembly VM)
- The Gradle plugin compiles your code to an optimised WASM binary
See the example project for a complete working demonstration, including an Android app.
plugins {
kotlin("multiplatform") version "2.1.0"
id("io.github.charlietap.glueball") version "0.1.1"
}
kotlin {
jvm() // At least one non-WASM target required
wasmWasi {
nodejs()
}
}
glueball {
packageName.set("com.example.generated")
interfaceName.set("FibonacciService")
}// src/commonMain/kotlin/com/example/Math.kt
package com.example
import io.github.charlietap.glueball.annotation.Glueball
@Glueball
fun fibonacci(n: Int): Int {
if (n <= 1) return n
var a = 0
var b = 1
var i = 1
while (i < n) {
val next = a + b
a = b
b = next
i++
}
return b
}The plugin generates an interface and two implementations:
import com.example.generated.FibonacciService
import com.example.generated.NativeFibonacciService
import com.example.generated.VirtualFibonacciService
// runs natively
val native: FibonacciService = NativeFibonacciService()
native.fibonacci(10)
// runs via a WebAssembly Virtual Machine
val wasmBytes: ByteArray = loadWasmBinary()
val virtual: FibonacciService = VirtualFibonacciService(wasmBytes)
virtual.fibonacci(10)For testing, enable automatic WASM binary embedding:
glueball {
packageName.set("com.example.generated")
interfaceName.set("FibonacciService")
generateTestBinary.set(true) // Embeds WASM as ByteArray in commonTest
}This generates FibonacciServiceTestBinary.BYTES for use in tests:
val service = VirtualFibonacciService(FibonacciServiceTestBinary.BYTES)| Property | Description | Default |
|---|---|---|
packageName |
Package for generated code | Required |
interfaceName |
Name of the generated service interface | Required |
generateTestBinary |
Embed WASM binary in test sources | true |
binaryOutputDirectory |
Output directory for compiled WASM | build/glueball-binary |
- Primitive types only: Parameters and return types must be
Boolean,Int,Long,Float, orDouble. Complex types (strings, objects, arrays) are not yet supported. - Top-level functions only: The
@Glueballannotation only works on top-level functions, not class methods. - wasmWasi target required: Your project must declare the
wasmWasitarget alongside at least one native target (JVM, iOS, etc.). - No suspend functions: Coroutines and suspend functions are not supported.
- Single module: All
@Glueballfunctions must be in the same module; cross-module virtualisation is not supported.
This project is dual-licensed under both the MIT and Apache 2.0 licenses.