build: move Kotlin plugin build to Gradle
This commit is contained in:
parent
d378b7cd02
commit
268f2f15d9
54
Makefile
54
Makefile
@ -1,54 +0,0 @@
|
||||
BUILD_DEV_OUT_DIR=build/compileSync/wasmWasi/main/developmentExecutable/kotlin
|
||||
BUILD_PROD_OUT_DIR=build/compileSync/wasmWasi/main/productionExecutable/optimized
|
||||
BUILD_ROOT_DIR=build/
|
||||
BINDINGS_OUT_DIR=src/wasmWasiMain/kotlin/bindings/
|
||||
TOOLS_DIR=tools
|
||||
WIT_BINDGEN_BRANCH=kotlin
|
||||
WIT_BINDGEN_PATH=$(TOOLS_DIR)/bin/wit-bindgen
|
||||
WIT_PATH=wit/v0.1
|
||||
|
||||
# Make sure this matches the value in `settings.gradle.kts`
|
||||
PROJECT_NAME=pumpkin-plugin-template-kt
|
||||
|
||||
.PHONY: componentify componentify-dev componentify-prod compile compile-dev compile-prod setup setup-and-componentify clean install-wit-bindgen run-wit-bindgen
|
||||
|
||||
# default target for when you don't want to think about it
|
||||
setup-and-componentify: # no dependencies, as setup and run "look" independent to the Makefile, this guarantees the order:
|
||||
$(MAKE) setup
|
||||
$(MAKE) componentify
|
||||
|
||||
setup: install-wit-bindgen
|
||||
|
||||
compile: compile-prod
|
||||
|
||||
compile-dev: run-wit-bindgen
|
||||
./gradlew compileDevelopmentExecutableKotlinWasmWasi
|
||||
|
||||
compile-prod: run-wit-bindgen
|
||||
./gradlew compileProductionExecutableKotlinWasmWasiOptimize
|
||||
|
||||
componentify: componentify-prod
|
||||
|
||||
componentify-dev: compile-dev
|
||||
wasm-tools component embed $(WIT_PATH) $(BUILD_DEV_OUT_DIR)/$(PROJECT_NAME).wasm -o $(BUILD_DEV_OUT_DIR)/$(PROJECT_NAME)-embedded.wasm
|
||||
wasm-tools component new $(BUILD_DEV_OUT_DIR)/$(PROJECT_NAME)-embedded.wasm --adapt wasi_snapshot_preview1=wasi_snapshot_preview1.reactor.wasm -o $(BUILD_DEV_OUT_DIR)/$(PROJECT_NAME)-component.wasm
|
||||
cp $(BUILD_DEV_OUT_DIR)/$(PROJECT_NAME)-component.wasm $(BUILD_ROOT_DIR)/$(PROJECT_NAME).wasm
|
||||
|
||||
componentify-prod: compile-prod
|
||||
wasm-tools component embed $(WIT_PATH) $(BUILD_PROD_OUT_DIR)/$(PROJECT_NAME).wasm -o $(BUILD_PROD_OUT_DIR)/$(PROJECT_NAME)-embedded.wasm
|
||||
wasm-tools component new $(BUILD_PROD_OUT_DIR)/$(PROJECT_NAME)-embedded.wasm --adapt wasi_snapshot_preview1=wasi_snapshot_preview1.reactor.wasm -o $(BUILD_PROD_OUT_DIR)/$(PROJECT_NAME)-component.wasm
|
||||
cp $(BUILD_PROD_OUT_DIR)/$(PROJECT_NAME)-component.wasm $(BUILD_ROOT_DIR)/$(PROJECT_NAME).wasm
|
||||
|
||||
clean:
|
||||
./gradlew clean
|
||||
rm -rf build
|
||||
rm -rf $(TOOLS_DIR)
|
||||
rm -f $(BINDINGS_OUT_DIR)/*
|
||||
|
||||
# doesn't depend on install-wit-bindgen* so that we can run the target
|
||||
# multiple times with the same wit-bindgen installation
|
||||
run-wit-bindgen:
|
||||
$(WIT_BINDGEN_PATH) kotlin --kotlin-imports 'plugin.*' --kotlin-package-name pumpkin $(WIT_PATH) --out-dir=$(BINDINGS_OUT_DIR)
|
||||
|
||||
install-wit-bindgen:
|
||||
cargo install wit-bindgen-cli --git https://github.com/Kotlin/wit-bindgen --branch $(WIT_BINDGEN_BRANCH) --root $(TOOLS_DIR)
|
||||
20
README.md
20
README.md
@ -13,24 +13,24 @@ Kotlin/Wasm + components it's still in it's early stages, and not as straightfor
|
||||
- Rust
|
||||
- This is required as a key component (wit-bindgen) is written and Rust must be built from a particular Kotlin-enabled fork.
|
||||
- You only need a default Rust install for your host platform. NOT for any WebAssembly targets
|
||||
- Make
|
||||
- To run the convenience `Makefile`. You may opt to do without and perform the necessary steps manually.
|
||||
- `wasm-tools`
|
||||
- To bundle the Wasm Kotlin produces into a component.
|
||||
|
||||
## Initial setup
|
||||
|
||||
To being working on your project, you'll want to adjust the project name in `settings.gradle.kts` and in the Makefile. Whatever your name you'll project, is what the generated Wasm will be named.
|
||||
Initialize the WIT submodule after cloning:
|
||||
|
||||
After that, you'll want to run `make` for the first time. This will setup the toolchain, generate the `pumpkin` package bindings into `src/wasmWasiMain/kotlin/bindings`, and build your plugin, leaving it in `build/<project-name>.wasm`, ready to be installed into Pumpkin.
|
||||
```sh
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
Then you can tweaking the plugin src in `src/wasmWasiMain/kotlin/plugin/Plugin.kt`.
|
||||
Then adjust the project name in `settings.gradle.kts`. The generated component is named after that project.
|
||||
|
||||
Run `./gradlew build` to install the pinned build tools, generate the `pumpkin` package bindings, compile the Kotlin/Wasm module, and produce a validated component at `build/<project-name>.wasm`, ready to be installed into Pumpkin. Generated bindings live under `build/generated/`.
|
||||
|
||||
Then you can tweak the plugin source in `src/wasmWasiMain/kotlin/plugin/Plugin.kt`.
|
||||
|
||||
## Rebuilding
|
||||
|
||||
Rebuilding the plugin is as simple as running `make` again. You can also be more specific by running `make componentify` to avoid the overhead of checking the `wit-bindgen` installation and regenerating the bindings.
|
||||
|
||||
If you need a debug build instead of a release build, run `make componentify-dev` (`componentify` is an alias of `componentify-prod`). Note that this will make loading the plugin take SIGNFICANTLY longer (making optimized builds actually better for the development loop).
|
||||
Rebuild with `./gradlew build`. Gradle skips tool installation, binding generation, and component assembly when their declared inputs are unchanged. Use `./gradlew clean` to remove generated build output; it intentionally retains the installed tool cache under `tools/`.
|
||||
|
||||
## Updating the WIT
|
||||
|
||||
|
||||
186
build.gradle.kts
186
build.gradle.kts
@ -1,3 +1,8 @@
|
||||
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||
|
||||
import org.gradle.process.CommandLineArgumentProvider
|
||||
import org.jetbrains.kotlin.gradle.targets.wasm.binaryen.BinaryenExec
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
}
|
||||
@ -7,8 +12,189 @@ repositories {
|
||||
}
|
||||
|
||||
kotlin {
|
||||
@OptIn(ExperimentalWasmDsl::class)
|
||||
wasmWasi {
|
||||
nodejs()
|
||||
binaries.executable()
|
||||
}
|
||||
}
|
||||
|
||||
val cargoHome = providers.environmentVariable("CARGO_HOME")
|
||||
.orElse(providers.systemProperty("user.home").map { "$it/.cargo" })
|
||||
val executableSuffix = if (System.getProperty("os.name").startsWith("Windows", ignoreCase = true)) ".exe" else ""
|
||||
val cargoExecutable = cargoHome.map { "$it/bin/cargo$executableSuffix" }
|
||||
|
||||
val witDirectory = layout.projectDirectory.dir("wit/v0.1")
|
||||
val reactorAdapter = layout.projectDirectory.file("wasi_snapshot_preview1.reactor.wasm")
|
||||
|
||||
val witBindgenRevision = "700f2db5e1d01f7bee8d756750c6f631171f520e"
|
||||
val witBindgenDirectory = layout.projectDirectory.dir("tools/wit-bindgen/$witBindgenRevision")
|
||||
val witBindgen = witBindgenDirectory.file("bin/wit-bindgen")
|
||||
|
||||
val wasmToolsVersion = "1.258.0"
|
||||
val wasmToolsDirectory = layout.projectDirectory.dir("tools/wasm-tools/$wasmToolsVersion")
|
||||
val wasmTools = wasmToolsDirectory.file("bin/wasm-tools$executableSuffix")
|
||||
|
||||
val generatedBindings = layout.buildDirectory.dir("generated/wit/wasmWasiMain/kotlin")
|
||||
val projectWasmName = rootProject.name
|
||||
val embeddedReleaseComponent = layout.buildDirectory.file(
|
||||
"intermediates/pumpkin-components/release/$projectWasmName-embedded.wasm"
|
||||
)
|
||||
val releaseComponent = layout.buildDirectory.file("$projectWasmName.wasm")
|
||||
|
||||
val installWitBindgen by tasks.registering(Exec::class) {
|
||||
group = "build setup"
|
||||
description = "Installs Pumpkin's pinned Kotlin binding generator."
|
||||
|
||||
inputs.property("revision", witBindgenRevision)
|
||||
outputs.dir(witBindgenDirectory)
|
||||
|
||||
commandLine(
|
||||
cargoExecutable.get(),
|
||||
"install",
|
||||
"wit-bindgen-cli",
|
||||
"--git", "https://github.com/Kotlin/wit-bindgen",
|
||||
"--rev", witBindgenRevision,
|
||||
"--locked",
|
||||
"--root", witBindgenDirectory.asFile.absolutePath,
|
||||
)
|
||||
}
|
||||
|
||||
val installWasmTools by tasks.registering(Exec::class) {
|
||||
group = "build setup"
|
||||
description = "Installs the pinned wasm-tools executable."
|
||||
|
||||
inputs.property("version", wasmToolsVersion)
|
||||
outputs.dir(wasmToolsDirectory)
|
||||
|
||||
commandLine(
|
||||
cargoExecutable.get(),
|
||||
"install",
|
||||
"wasm-tools",
|
||||
"--version", wasmToolsVersion,
|
||||
"--locked",
|
||||
"--root", wasmToolsDirectory.asFile.absolutePath,
|
||||
)
|
||||
}
|
||||
|
||||
val generateWitBindings by tasks.registering(Exec::class) {
|
||||
group = "build"
|
||||
description = "Generates Kotlin bindings from Pumpkin's WIT definitions."
|
||||
|
||||
dependsOn(installWitBindgen)
|
||||
inputs.dir(witDirectory)
|
||||
inputs.file(witBindgen)
|
||||
inputs.property("kotlinPackage", "pumpkin")
|
||||
inputs.property("kotlinImports", "plugin.*")
|
||||
outputs.dir(generatedBindings)
|
||||
|
||||
doFirst {
|
||||
val outputDirectory = generatedBindings.get().asFile
|
||||
check(outputDirectory.deleteRecursively() || !outputDirectory.exists()) {
|
||||
"Could not remove stale bindings from $outputDirectory"
|
||||
}
|
||||
check(outputDirectory.mkdirs() || outputDirectory.isDirectory) {
|
||||
"Could not create bindings directory $outputDirectory"
|
||||
}
|
||||
}
|
||||
|
||||
commandLine(
|
||||
witBindgen.asFile.absolutePath,
|
||||
"kotlin",
|
||||
"--kotlin-imports", "plugin.*",
|
||||
"--kotlin-package-name", "pumpkin",
|
||||
witDirectory.asFile.absolutePath,
|
||||
"--out-dir", generatedBindings.get().asFile.absolutePath,
|
||||
)
|
||||
}
|
||||
|
||||
kotlin {
|
||||
sourceSets.named("wasmWasiMain") {
|
||||
kotlin.srcDir(generateWitBindings)
|
||||
}
|
||||
}
|
||||
|
||||
val compileReleaseWasm = tasks.named<BinaryenExec>("compileProductionExecutableKotlinWasmWasiOptimize")
|
||||
val releaseCoreWasm = compileReleaseWasm.flatMap {
|
||||
it.outputDirectory.file("$projectWasmName.wasm")
|
||||
}
|
||||
|
||||
val embedComponentWitRelease by tasks.registering(Exec::class) {
|
||||
group = "build"
|
||||
description = "Embeds Pumpkin's WIT into the release Kotlin/Wasm module."
|
||||
|
||||
dependsOn(compileReleaseWasm, installWasmTools)
|
||||
inputs.dir(witDirectory)
|
||||
inputs.file(releaseCoreWasm)
|
||||
inputs.file(wasmTools)
|
||||
outputs.file(embeddedReleaseComponent)
|
||||
|
||||
executable = wasmTools.asFile.absolutePath
|
||||
argumentProviders.add(
|
||||
object : CommandLineArgumentProvider {
|
||||
override fun asArguments() = listOf(
|
||||
"component",
|
||||
"embed",
|
||||
witDirectory.asFile.absolutePath,
|
||||
releaseCoreWasm.get().asFile.absolutePath,
|
||||
"-o", embeddedReleaseComponent.get().asFile.absolutePath,
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
doFirst {
|
||||
val outputDirectory = embeddedReleaseComponent.get().asFile.parentFile
|
||||
check(outputDirectory.mkdirs() || outputDirectory.isDirectory) {
|
||||
"Could not create component directory $outputDirectory"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val assemblePluginRelease by tasks.registering(Exec::class) {
|
||||
group = "build"
|
||||
description = "Creates the release WebAssembly component that Pumpkin can load."
|
||||
|
||||
dependsOn(embedComponentWitRelease)
|
||||
inputs.file(embeddedReleaseComponent)
|
||||
inputs.file(reactorAdapter)
|
||||
inputs.file(wasmTools)
|
||||
outputs.file(releaseComponent)
|
||||
|
||||
commandLine(
|
||||
wasmTools.asFile.absolutePath,
|
||||
"component",
|
||||
"new",
|
||||
embeddedReleaseComponent.get().asFile.absolutePath,
|
||||
"--adapt", "wasi_snapshot_preview1=${reactorAdapter.asFile.absolutePath}",
|
||||
"-o", releaseComponent.get().asFile.absolutePath,
|
||||
)
|
||||
}
|
||||
|
||||
val validatePluginRelease by tasks.registering(Exec::class) {
|
||||
group = "verification"
|
||||
description = "Validates the release WebAssembly component."
|
||||
|
||||
dependsOn(assemblePluginRelease)
|
||||
inputs.file(releaseComponent)
|
||||
inputs.file(wasmTools)
|
||||
|
||||
commandLine(
|
||||
wasmTools.asFile.absolutePath,
|
||||
"validate",
|
||||
releaseComponent.get().asFile.absolutePath,
|
||||
)
|
||||
}
|
||||
|
||||
tasks.named("assemble") {
|
||||
dependsOn(assemblePluginRelease)
|
||||
}
|
||||
|
||||
tasks.named("check") {
|
||||
dependsOn(validatePluginRelease)
|
||||
}
|
||||
|
||||
tasks.register("cleanProject") {
|
||||
group = "build"
|
||||
description = "Removes generated build output."
|
||||
dependsOn(tasks.named("clean"))
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// When changing this, make sure to modify the Makefile accordingly
|
||||
rootProject.name = "pumpkin-plugin-template-kt"
|
||||
|
||||
pluginManagement {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user