Skip to content

sureshg/kotlin-mpp-playground

Repository files navigation

Kotlin Multiplatform Playground!

GitHub Workflow Status OpenJDK Version Kotlin release Ktor Compose Multiplatform Kobweb Style guide

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.

Install OpenJDK EA Build

# Mac OS
$ curl -s "https://get.sdkman.io" | bash
$ sdk i java 23.ea-open
$ sdk u java 23.ea-open

Build & Run

$ ./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:web:kobwebStart -t
$ ./gradlew :compose:web: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

Deployed App and Docs

Resources

Module Dependency Graph

Module Dependency

%%{
  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:web["web"]
    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:web --> :shared
    : --> :backend
    : --> :benchmark
    : --> :compose
    : --> :meta
    : --> :shared
    : --> :web
    : --> :backend:data
    : --> :backend:jvm
    : --> :backend:native
    : --> :backend:profiling
    : --> :backend:security
    : --> :compose:desktop
    : --> :compose:web
    : --> :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