This repo shows a Gradle multi-project build structure that uses the Kotlin Multiplatform to build a JVM, JS, Desktop and Compose Web (wasm) applications.
# Mac OS
$ curl -s "https://get.sdkman.io" | bash
$ sdk i java 23.ea-open
$ sdk u java 23.ea-open
$ ./gradlew buildAndPublish
Run Modules
# Kotlin JVM
$ ./gradlew :shared:run
$ ./gradlew :backend:jvm:run
$ docker run \
-it \
--rm \
--pull always \
--workdir /app \
--publish 8080:8080 \
--publish 8081:8081 \
--name kotlin-mpp-playground \
--mount type=bind,source=$(pwd),destination=/app,readonly \
openjdk:23-slim /bin/bash -c "printenv && nohup jwebserver -b 0.0.0.0 -p 8081 -d / & backend/jvm/build/libs/jvm-app"
$ ./gradlew :backend:jvm:jibDockerBuild
$ docker run -it --rm --name jvm-app -p 8080:8080 -p 9898:9898 sureshg/jvm
$ docker stats
# With OpenTelemetry
$ brew tap CtrlSpice/homebrew-otel-desktop-viewer
$ brew install otel-desktop-viewer
$ otel-desktop-viewer
$ docker run -it --rm \
--name jvm \
-p 8080:8080 \
-p 9898:9898 \
-e OTEL_JAVAAGENT_ENABLED=true \
-e OTEL_TRACES_EXPORTER="otlp" \
-e OTEL_EXPORTER_OTLP_PROTOCOL="grpc" \
-e OTEL_EXPORTER_OTLP_ENDPOINT="http://host.docker.internal:4317" \
sureshg/jvm:latest
# Run container tests
$ ./gradlew :backend:jvm:test -PktorTest
$ ./gradlew :backend:jvm:jvmRun -DmainClass=dev.suresh.lang.SysCallKt --quiet
# Run with AppCDS
$ java -Xlog:class+load:file=/tmp/cds.log:uptime,level,tags,pid \
-XX:+AutoCreateSharedArchive \
-XX:SharedArchiveFile=/tmp/app.jsa \
-jar backend/jvm/build/libs/jvm-app.jar
# cds-log-parser.jar --logFile=/tmp/cds.log
# Kotlin JS
$ ./gradlew :web:js:jsBrowserProductionRun -t
$ ./gradlew kotlinUpgradePackageLock
# Kotlin Native
# -------------
$ ./gradlew :backend:native:build
# Arch specific binaries
$ ./gradlew :backend:native:macosArm64Binaries
$ ./gradlew :backend:native:macosX64Binaries
$ ./gradlew :backend:native:macOsUniversalBinary
# Native container image
$ ./gradlew :backend:native:jibDockerBuild
$ docker run -it --rm --name native-app sureshg/native
# Test linux binary on ARM64 MacOS
$ ./gradlew :backend:native:linuxArm64Binaries
$ docker run \
-it \
--rm \
--publish 8080:80 \
--mount type=bind,source=$(pwd),destination=/app,readonly \
debian:stable-slim
# /app/backend/native/build/bin/linuxArm64/releaseExecutable/native.kexe
# libtree -v /app/backend/native/build/bin/linuxArm64/releaseExecutable/native.kexe
# Build native binaries on container
$ docker run \
--platform=linux/amd64 \
-it \
--rm \
--pull always \
--workdir /app \
--name kotlin-native-build \
--mount type=bind,source=$(pwd),destination=/app \
--mount type=bind,source=${HOME}/.gradle,destination=/root/.gradle \
openjdk:23-slim /bin/bash
# apt update && apt install libtree tree
# ./gradlew --no-daemon :backend:native:build
# backend/native/build/bin/linuxX64/releaseExecutable/native.kexe
# Kobweb
# ------
$ kobweb run -p compose/web
$ ./gradlew :compose:html:kobwebStart -t
$ ./gradlew :compose:html:kobwebStop
# Compose Desktop
$ ./gradlew :compose:desktop:runDistributable
$ ./gradlew :compose:desktop:packageDistributionForCurrentOS
$ ./gradlew :compose:desktop:suggestModules
# Publishing
$ ./gradlew publishAllPublicationsToLocalRepository
# Benchmark
$ ./gradlew :benchmark:benchmark
# KMP hierarchy, Dependencies
$ ./gradlew :shared:printHierarchy
$ ./gradlew :backend:jvm:listResolvedArtifacts
$ ./gradlew createModuleGraph
$ ./gradlew generateChangelog
# Clean
$ ./gradlew cleanAll
# Gradle Daemon Toolchain
$ ./gradlew updateDaemonJvm
# Gradle Best Practices
$ ./gradlew -p gradle/build-logic :bestPracticesBaseline
$ ./gradlew checkBuildLogicBestPractices
$ ./gradlew dependencies
# GitHub Actions lint
$ actionlint
- π Kotlin Multiplatform Package Search
- π¨ Kotlin Multiplatform Wizard
- π Jetbrains Compose Rules
Module Dependency Graph
%%{
init: {
'theme': 'neutral'
}
}%%
graph LR
subgraph :backend
:backend:native["native"]
:backend:data["data"]
:backend:profiling["profiling"]
:backend:jvm["jvm"]
:backend:security["security"]
end
subgraph :compose
:compose:desktop["desktop"]
:compose:html["html"]
end
subgraph :dep-mgmt
:dep-mgmt:bom["bom"]
:dep-mgmt:catalog["catalog"]
end
subgraph :meta
:meta:compiler["compiler"]
:meta:ksp["ksp"]
end
subgraph :meta:compiler
:meta:compiler:plugin["plugin"]
end
subgraph :meta:ksp
:meta:ksp:processor["processor"]
end
subgraph :web
:web:js["js"]
:web:wasm["wasm"]
end
:web:js --> :shared
:benchmark --> :shared
:backend:native --> :shared
:web:wasm --> :shared
:compose:desktop --> :shared
:meta:compiler:plugin --> :shared
:meta:ksp:processor --> :shared
:backend:data --> :shared
:backend:profiling --> :shared
:compose:html --> :shared
: --> :backend
: --> :benchmark
: --> :compose
: --> :meta
: --> :shared
: --> :web
: --> :backend:data
: --> :backend:jvm
: --> :backend:native
: --> :backend:profiling
: --> :backend:security
: --> :compose:desktop
: --> :compose:html
: --> :meta:compiler
: --> :meta:ksp
: --> :web:js
: --> :web:wasm
: --> :meta:compiler:plugin
: --> :meta:ksp:processor
: --> :dep-mgmt:bom
: --> :dep-mgmt:catalog
:backend:jvm --> :shared
:backend:jvm --> :backend:data
:backend:jvm --> :backend:profiling
:backend:jvm --> :web:js
:backend:jvm --> :web:wasm
:backend:security --> :shared