Files
Bitsy 82ffd7cf4d feat: migrate to Compose Multiplatform 1.12.0 + SDL3 3.4.16
Upstream baseline
- Pin both vendored refs to the STABLE v1.12.0 tag (core + umbrella); the
  native and JVM-parity legs are back in lockstep, no dev-build skew.
- Catalog: compose 1.12.0, composeRuntime 1.12.0. material3 stays
  1.12.0-alpha03 - that IS the version CMP 1.12.0 ships (its own train).
- Re-synced 1560 vendored files; drift + vendor-clean both clean.
- Retire the SelectionLayout.kt manual vendor: upstream fixed the same
  out-of-bounds at the source (lastSlot = currentSlot, not currentSlot + 1),
  so the fork's index clamps are redundant. Back to verbatim vendoring.
- Re-stamp 10 manual vendors to @ v1.12.0 (upstream unchanged base..pin).
- Regenerate the klib API dumps. These had already drifted on main (the last
  dump predates the scrollbar / IME changes), so the diff covers that too.

SDL3 3.4.16, skiko fork 0.150.1-mingw.2
- Rebuild the static libSDL3.a from release-3.4.16.
- CMP 1.12.0 uses skiko 0.150.1, unchanged, so the fork's Skia base still
  matches; bump to the -mingw.2 build and centralise it as `skikoMingw` in
  the version catalog instead of three hardcoded copies.
- Resolve the fork from the PUBLIC maven.bitsycore.com/releases instead of
  the credentialed GitHub Packages repo: building the Windows target no
  longer needs a GitHub token.

Gradle module paths mirror the directory
- Drop every projectDir redirect: :ui -> :compose:ui:ui,
  :animation-core -> :compose:animation:animation-core, and so on.
- INVARIANT (documented in settings.gradle.kts + CLAUDE.md): the leaf
  directory IS the published artifactId. KMP derives a target publication's
  coordinate as <project.name>-<target>, and a target disabled on the
  building host (all Apple targets on Windows) has no publication object to
  retarget - while the root kotlinMultiplatform metadata, which the WINDOWS
  publish job owns, still emits an available-at for it. A mismatched leaf
  silently ships a root module pointing at a nonexistent <leaf>-macosarm64.
  So compose/desktop/native/window and components/resources/library are
  renamed to their artifactIds. Published coordinates are unchanged.

Manual-vendor audit
- New scripts/compose-fork/audit-exclusions.py: classifies every `!` manifest
  exclusion as manual vendor (VENDOR-BASE, drift-tracked), reimplementation
  (VENDOR-REIMPL, deliberately not tracked), or orphan, and fails on any
  unclassified one.
- 14 project reimplementations were invisible to the drift checker by
  accident; mark them VENDOR-REIMPL. None needed reconciling (all verified
  <= 0.53 similarity to their upstream counterparts, none changed upstream
  between the old pin and v1.12.0).

Fix the JVM apidemo build
- Declare components-resources on jvmMain (decodeToImageBitmap /
  decodeToSvgPainter) and add the two missing cross-package imports. The JVM
  parity target had never compiled.

Verified on Windows: both native executables link and render, apidemo JVM
builds and launches, apiCheck green, common metadata compiles (the Windows
publish gate), publishToMavenLocal emits the same coordinates as before.
2026-09-12 00:03:13 +02:00

149 lines
5.9 KiB
Kotlin

import com.bitsycore.compose.sdl.build.registerComposeFontBundling
plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.kotlin.plugin.compose)
alias(libs.plugins.compose.multiplatform)
alias(libs.plugins.kotlin.plugin.serialization)
id("com.bitsycore.compose-desktop-native.bridge")
}
val isHostMingwCompatible = rootProject.extra["vHostSupportsMingw"] as Boolean
// ==================
// MARK: Targets
// ==================
kotlin {
jvm()
buildList {
add(linuxArm64())
add(linuxX64())
add(macosArm64())
if (isHostMingwCompatible) add(mingwX64())
}.forEach {
it.binaries {
executable {
when {
target.name == "mingwX64" -> linkerOpts(
// crypt32: client-cert (mTLS) import into the Windows cert store.
"-lcrypt32",
"-Wl,--gc-sections", "-Wl,-s",
// GUI subsystem (no console window), keeping the C `main` entry.
"-Wl,--subsystem,windows", "-Wl,-e,mainCRTStartup",
)
target.name.startsWith("linux") -> linkerOpts(
"-L/usr/lib/x86_64-linux-gnu", "-L/usr/lib/aarch64-linux-gnu",
"-lfontconfig", "-lGL", "-lX11",
)
}
}
}
}
applyDefaultHierarchyTemplate()
sourceSets {
commonMain {
dependencies {
val vComposeJvmVersion = libs.versions.compose.get()
val vComposeM3JvmVersion = libs.versions.composeMaterial3.get()
// Official Maven coords for everything the shared UI touches; native
// configurations substitute them for the port modules automatically
// (root bridge in-repo, the bridge plugin for consumers).
implementation("org.jetbrains.compose.runtime:runtime:${libs.versions.composeRuntime.get()}")
implementation("org.jetbrains.compose.ui:ui:$vComposeJvmVersion")
implementation("org.jetbrains.compose.ui:ui-graphics:$vComposeJvmVersion")
implementation("org.jetbrains.compose.ui:ui-text:$vComposeJvmVersion")
implementation("org.jetbrains.compose.ui:ui-unit:$vComposeJvmVersion")
implementation("org.jetbrains.compose.ui:ui-geometry:$vComposeJvmVersion")
implementation("org.jetbrains.compose.ui:ui-util:$vComposeJvmVersion")
implementation("org.jetbrains.compose.foundation:foundation:$vComposeJvmVersion")
implementation("org.jetbrains.compose.foundation:foundation-layout:$vComposeJvmVersion")
implementation("org.jetbrains.compose.animation:animation:$vComposeJvmVersion")
implementation("org.jetbrains.compose.animation:animation-core:$vComposeJvmVersion")
implementation("org.jetbrains.compose.material3:material3:$vComposeM3JvmVersion")
// Common Material Symbols Utility
implementation(project(":utils:material-symbols"))
implementation(libs.ktor.client.core)
implementation(libs.ktor.client.content.negotiation)
implementation(libs.ktor.serialization.kotlinx.json)
implementation(libs.kotlinx.serialization.json)
implementation(libs.okio)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.datetime)
}
}
nativeMain {
dependencies {
implementation(project(":compose:desktop:native:desktop-native-window"))
implementation(libs.ktor.client.curl)
}
}
jvmMain {
dependencies {
implementation(compose.desktop.currentOs)
// decodeToImageBitmap / decodeToSvgPainter (window icon + in-memory
// image viewer). JVM-only: the native side goes through the port's
// own EncodedImageDecoder seam, so this stays out of commonMain.
implementation("org.jetbrains.compose.components:components-resources:${libs.versions.compose.get()}")
implementation(libs.ktor.client.cio)
implementation(libs.kotlinx.coroutines.swing)
}
}
}
compilerOptions {
freeCompilerArgs.add("-Xexpect-actual-classes")
freeCompilerArgs.add("-opt-in=kotlinx.cinterop.ExperimentalForeignApi")
}
}
compose.desktop {
application {
mainClass = "apidemo.MainJvmKt"
}
}
compose.desktop.native {
entryPoint = "apidemo.main"
icon {
light.from(
layout.projectDirectory.file("icons/voltic-icon-32.png"),
layout.projectDirectory.file("icons/voltic-icon-128.png"),
)
dark.from(
layout.projectDirectory.file("icons/voltic-icon-dark-32.png"),
layout.projectDirectory.file("icons/voltic-icon-dark-128.png"),
)
exeIcon.from(
listOf(16, 32, 48, 64, 128, 256).map {
layout.projectDirectory.file("icons/voltic-icon-$it.png")
}
)
embedWindowsIcon = providers.gradleProperty("embedWindowsIcon").map { it.toBoolean() }
}
}
// ==================
// MARK: Fonts (shared pipeline - buildSrc ComposeFontBundling.kt)
// ==================
registerComposeFontBundling {
bundleNotoSans = true
// The mono body font is loaded through the app's own seam (Fonts.kt), not via
// FontFamily.Monospace call sites - auto-detection can't see it, bundle explicitly.
bundleNotoSansMono = true
bundleMaterialSymbols = true
enableIconSubsetting = true
}
// Parity-window icon (cosmetic : the harness compares the canvas, not chrome).
tasks.named<ProcessResources>("jvmProcessResources") {
from(layout.projectDirectory.file("icons/voltic-icon-256.png")) { into("icon") }
}