From dc4dc220f7b297096ec582762c770a47c59aadd1 Mon Sep 17 00:00:00 2001 From: Kenny Cason Date: Thu, 12 Mar 2026 17:26:33 -0700 Subject: [PATCH 1/9] windows build attempt 1 --- .github/workflows/build.yml | 74 ++++++++++++++++++++++ buildSrc/src/main/kotlin/PlatformConfig.kt | 22 ++++++- buildSrc/src/main/kotlin/SdlDylibCopier.kt | 31 +++++---- 3 files changed, 114 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 93a70bb..7eed288 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -221,3 +221,77 @@ jobs: SDL_VIDEODRIVER: dummy SDL_AUDIODRIVER: dummy LD_LIBRARY_PATH: /usr/local/lib + + build-windows: + runs-on: windows-latest + timeout-minutes: 45 + + defaults: + run: + shell: msys2 {0} + + steps: + - name: Set up MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + update: false + install: >- + mingw-w64-x86_64-SDL3 + mingw-w64-x86_64-SDL3_image + mingw-w64-x86_64-SDL3_ttf + mingw-w64-x86_64-SDL3_mixer + mingw-w64-x86_64-SDL3_net + mingw-w64-x86_64-chipmunk + + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Verify SDL3 libraries + run: | + echo "=== MSYS2 mingw64 SDL3 libs ===" + ls /mingw64/bin/SDL3*.dll /mingw64/bin/libSDL3*.dll 2>/dev/null || true + ls /mingw64/lib/libSDL3* 2>/dev/null || true + echo "=== Include dirs ===" + ls /mingw64/include/SDL3/ | head -5 + + - name: Gradle cache + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle.kts', 'gradle/libs.versions.toml') }} + restore-keys: gradle-${{ runner.os }}- + + - name: Build all modules + env: + MSYS2_ROOT: D:/a/_temp/msys64 + run: | + ./gradlew clean build -x allTests -x nativeTest -x jvmTest -x jsTest + + - name: Compile and run kengine tests + env: + MSYS2_ROOT: D:/a/_temp/msys64 + SDL_VIDEODRIVER: dummy + SDL_AUDIODRIVER: dummy + run: | + ./gradlew :kengine:linkDebugTestNative || true + if [ -f ./kengine/build/bin/native/debugTest/test.kexe ]; then + # Copy DLLs next to the test binary + cp /mingw64/bin/SDL3.dll ./kengine/build/bin/native/debugTest/ 2>/dev/null || true + cp /mingw64/bin/SDL3_image.dll ./kengine/build/bin/native/debugTest/ 2>/dev/null || true + cp /mingw64/bin/SDL3_ttf.dll ./kengine/build/bin/native/debugTest/ 2>/dev/null || true + cp /mingw64/bin/SDL3_mixer.dll ./kengine/build/bin/native/debugTest/ 2>/dev/null || true + cp /mingw64/bin/SDL3_net.dll ./kengine/build/bin/native/debugTest/ 2>/dev/null || true + ./kengine/build/bin/native/debugTest/test.kexe \ + "--ktest_filter=*-*IT.*:*TiledMapLoaderTest.*" + fi diff --git a/buildSrc/src/main/kotlin/PlatformConfig.kt b/buildSrc/src/main/kotlin/PlatformConfig.kt index 0eeb526..4728d3a 100644 --- a/buildSrc/src/main/kotlin/PlatformConfig.kt +++ b/buildSrc/src/main/kotlin/PlatformConfig.kt @@ -2,16 +2,23 @@ object PlatformConfig { val hostOs: String = System.getProperty("os.name") val isMacOS: Boolean = hostOs == "Mac OS X" val isLinux: Boolean = hostOs == "Linux" + val isWindows: Boolean = hostOs.startsWith("Windows") + + // MSYS2 mingw64 root — standard location on GitHub Actions and local installs + private val msys2Root: String = System.getenv("MSYS2_ROOT") ?: "C:/msys64" + private val mingw64: String = "$msys2Root/mingw64" val includePaths: List = when { isMacOS -> listOf("/opt/homebrew/include", "/usr/local/include") isLinux -> listOf("/usr/local/include", "/usr/include", "/usr/include/x86_64-linux-gnu") + isWindows -> listOf("$mingw64/include") else -> listOf("/usr/local/include") } val libPaths: List = when { isMacOS -> listOf("/opt/homebrew/lib", "/usr/local/lib") isLinux -> listOf("/usr/local/lib", "/usr/lib/x86_64-linux-gnu", "/usr/lib") + isWindows -> listOf("$mingw64/lib") else -> listOf("/usr/local/lib") } @@ -50,8 +57,19 @@ object PlatformConfig { "-lpthread", "-ldl", "-lm" ) else emptyList() + val windowsSystemLibs: List + get() = if (isWindows) listOf( + "-lmingw32", "-lole32", "-loleaut32", "-limm32", + "-lwinmm", "-lgdi32", "-lsetupapi", "-lversion" + ) else emptyList() + fun sharedLibLinkerOpts(vararg libs: String): List = - libPathOpts + libs.map { "-l$it" } + macFrameworks + linuxSystemLibs + rpathOpts + libPathOpts + libs.map { "-l$it" } + + macFrameworks + linuxSystemLibs + windowsSystemLibs + rpathOpts - val sharedLibExt: String = if (isMacOS) "dylib" else "so" + val sharedLibExt: String = when { + isMacOS -> "dylib" + isWindows -> "dll" + else -> "so" + } } diff --git a/buildSrc/src/main/kotlin/SdlDylibCopier.kt b/buildSrc/src/main/kotlin/SdlDylibCopier.kt index 9be8ae1..e1a4206 100644 --- a/buildSrc/src/main/kotlin/SdlDylibCopier.kt +++ b/buildSrc/src/main/kotlin/SdlDylibCopier.kt @@ -8,22 +8,25 @@ class SdlDylibCopier(private val project: Project) { private val isMacOS = PlatformConfig.isMacOS private val isLinux = PlatformConfig.isLinux + private val isWindows = PlatformConfig.isWindows + + private val msys2Root: String = System.getenv("MSYS2_ROOT") ?: "C:/msys64" private val searchPaths: List = when { isMacOS -> listOf("/opt/homebrew/lib", "/usr/local/lib") isLinux -> listOf("/usr/local/lib", "/usr/lib/x86_64-linux-gnu", "/usr/lib") + isWindows -> listOf("$msys2Root/mingw64/bin", "$msys2Root/mingw64/lib") else -> listOf("/usr/local/lib") } /** * Resolve a shared library by base name (e.g. "SDL3"), searching platform-specific locations. - * On macOS looks for .dylib, on Linux looks for .so. */ private fun resolveLib(baseName: String): String { - val candidates = if (isMacOS) { - listOf("lib${baseName}.0.dylib", "lib${baseName}.dylib") - } else { - listOf("lib${baseName}.so.0", "lib${baseName}.so") + val candidates = when { + isMacOS -> listOf("lib${baseName}.0.dylib", "lib${baseName}.dylib") + isWindows -> listOf("${baseName}.dll", "lib${baseName}.dll") + else -> listOf("lib${baseName}.so.0", "lib${baseName}.so") } for (candidate in candidates) { for (searchPath in searchPaths) { @@ -33,10 +36,13 @@ class SdlDylibCopier(private val project: Project) { } } } + val installHint = when { + isMacOS -> "Install via Homebrew (brew install sdl3) or build from source (bash sdl3/build_sdl.sh)." + isWindows -> "Install via MSYS2 (pacman -S mingw-w64-x86_64-SDL3) or build from source." + else -> "Build from source (bash sdl3/build_sdl.sh) or install via your package manager." + } throw IllegalStateException( - "Could not find lib$baseName in any of: ${searchPaths.joinToString()}. " + - if (isMacOS) "Install via Homebrew (brew install sdl3) or build from source (bash sdl3/build_sdl.sh)." - else "Build from source (bash sdl3/build_sdl.sh) or install via your package manager." + "Could not find $baseName in any of: ${searchPaths.joinToString()}. $installHint" ) } @@ -64,7 +70,7 @@ class SdlDylibCopier(private val project: Project) { libTargetDirs: List ) { libsToCopy.forEach { libPath -> - val libName = libPath.substringAfterLast("/") + val libName = libPath.substringAfterLast("/").substringAfterLast("\\") libTargetDirs.forEach { toDir -> val targetDir = toDir.substringAfter("${project.buildDir}/bin/native/") @@ -87,7 +93,9 @@ class SdlDylibCopier(private val project: Project) { } } - fileMode = 0b111101101 // rwxr-xr-x (755) + if (!isWindows) { + fileMode = 0b111101101 // rwxr-xr-x (755) + } } } else { println("Task $taskName already exists. Skipping registration.") @@ -98,7 +106,7 @@ class SdlDylibCopier(private val project: Project) { project.tasks.named("nativeTest") { dependsOn( libsToCopy.flatMap { libPath -> - val libName = libPath.substringAfterLast("/") + val libName = libPath.substringAfterLast("/").substringAfterLast("\\") libTargetDirs.map { toDir -> val targetDir = toDir.substringAfter("${project.buildDir}/bin/native/") generateTaskName(project, libName, targetDir) @@ -116,6 +124,7 @@ class SdlDylibCopier(private val project: Project) { .removeSuffix(".dylib") .removeSuffix(".so.0") .removeSuffix(".so") + .removeSuffix(".dll") .capitalize() return if (targetDir.contains("debugTest")) "copy${moduleName}${prefix}ToDebugTestFrameworks" From 878417997403ee697dc3d7fc2c6666b18e6fdfb0 Mon Sep 17 00:00:00 2001 From: Kenny Cason Date: Thu, 12 Mar 2026 17:56:50 -0700 Subject: [PATCH 2/9] windows build attempt 2 --- .github/workflows/build.yml | 42 +++++++++++--- sdl3/build_sdl.sh | 111 +++++++++++++++++++++++++----------- 2 files changed, 112 insertions(+), 41 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7eed288..45594b2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -224,7 +224,7 @@ jobs: build-windows: runs-on: windows-latest - timeout-minutes: 45 + timeout-minutes: 60 defaults: run: @@ -237,12 +237,17 @@ jobs: msystem: MINGW64 update: false install: >- - mingw-w64-x86_64-SDL3 - mingw-w64-x86_64-SDL3_image - mingw-w64-x86_64-SDL3_ttf - mingw-w64-x86_64-SDL3_mixer - mingw-w64-x86_64-SDL3_net + mingw-w64-x86_64-cmake + mingw-w64-x86_64-gcc + mingw-w64-x86_64-pkg-config + mingw-w64-x86_64-freetype + mingw-w64-x86_64-harfbuzz + mingw-w64-x86_64-libjpeg-turbo + mingw-w64-x86_64-libpng + mingw-w64-x86_64-libwebp + mingw-w64-x86_64-libtiff mingw-w64-x86_64-chipmunk + make - name: Checkout uses: actions/checkout@v4 @@ -255,13 +260,33 @@ jobs: java-version: '17' distribution: 'temurin' + - name: Cache SDL3 source builds + uses: actions/cache@v4 + id: sdl-source-cache + with: + path: | + D:\a\_temp\msys64\mingw64\lib\libSDL3* + D:\a\_temp\msys64\mingw64\bin\SDL3* + D:\a\_temp\msys64\mingw64\bin\libSDL3* + D:\a\_temp\msys64\mingw64\include\SDL3 + D:\a\_temp\msys64\mingw64\include\SDL3_image + D:\a\_temp\msys64\mingw64\include\SDL3_ttf + D:\a\_temp\msys64\mingw64\include\SDL3_mixer + D:\a\_temp\msys64\mingw64\include\SDL3_net + key: sdl3-source-${{ runner.os }}-${{ hashFiles('.gitmodules', 'sdl3/build_sdl.sh') }} + + - name: Build all SDL3 libs from source + if: steps.sdl-source-cache.outputs.cache-hit != 'true' + run: bash sdl3/build_sdl.sh + - name: Verify SDL3 libraries run: | - echo "=== MSYS2 mingw64 SDL3 libs ===" + echo "=== SDL3 DLLs ===" ls /mingw64/bin/SDL3*.dll /mingw64/bin/libSDL3*.dll 2>/dev/null || true + echo "=== SDL3 import libs ===" ls /mingw64/lib/libSDL3* 2>/dev/null || true echo "=== Include dirs ===" - ls /mingw64/include/SDL3/ | head -5 + ls /mingw64/include/SDL3/ 2>/dev/null | head -5 - name: Gradle cache uses: actions/cache@v4 @@ -288,6 +313,7 @@ jobs: if [ -f ./kengine/build/bin/native/debugTest/test.kexe ]; then # Copy DLLs next to the test binary cp /mingw64/bin/SDL3.dll ./kengine/build/bin/native/debugTest/ 2>/dev/null || true + cp /mingw64/bin/libSDL3.dll ./kengine/build/bin/native/debugTest/ 2>/dev/null || true cp /mingw64/bin/SDL3_image.dll ./kengine/build/bin/native/debugTest/ 2>/dev/null || true cp /mingw64/bin/SDL3_ttf.dll ./kengine/build/bin/native/debugTest/ 2>/dev/null || true cp /mingw64/bin/SDL3_mixer.dll ./kengine/build/bin/native/debugTest/ 2>/dev/null || true diff --git a/sdl3/build_sdl.sh b/sdl3/build_sdl.sh index 498596e..08bcf39 100755 --- a/sdl3/build_sdl.sh +++ b/sdl3/build_sdl.sh @@ -11,24 +11,44 @@ # libwayland-dev libxkbcommon-dev libasound2-dev libpulse-dev libpipewire-0.3-dev \ # libfreetype-dev libharfbuzz-dev libjpeg-dev libpng-dev libwebp-dev # +# Windows/MSYS2: builds ALL SDL3 libs from source. +# Prerequisites: MSYS2 MINGW64 environment +# pacman -S mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc make +# set -e SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" OS="$(uname -s)" -if [ "$OS" = "Darwin" ]; then - BREW_PREFIX="$(brew --prefix 2>/dev/null || echo /opt/homebrew)" - SDL3_INCLUDE="${BREW_PREFIX}/include" - SDL3_LIB="${BREW_PREFIX}/lib/libSDL3.dylib" - NCPU="$(sysctl -n hw.ncpu)" -elif [ "$OS" = "Linux" ]; then - SDL3_INCLUDE="/usr/local/include" - SDL3_LIB="/usr/local/lib/libSDL3.so" - NCPU="$(nproc)" -else - echo "Unsupported OS: $OS" - exit 1 -fi +# Detect platform +case "$OS" in + Darwin) + BREW_PREFIX="$(brew --prefix 2>/dev/null || echo /opt/homebrew)" + SDL3_INCLUDE="${BREW_PREFIX}/include" + SDL3_LIB="${BREW_PREFIX}/lib/libSDL3.dylib" + NCPU="$(sysctl -n hw.ncpu)" + INSTALL_PREFIX="/usr/local" + USE_SUDO="sudo" + ;; + Linux) + SDL3_INCLUDE="/usr/local/include" + SDL3_LIB="/usr/local/lib/libSDL3.so" + NCPU="$(nproc)" + INSTALL_PREFIX="/usr/local" + USE_SUDO="sudo" + ;; + MINGW*|MSYS*) + SDL3_INCLUDE="/mingw64/include" + SDL3_LIB="/mingw64/lib/libSDL3.dll.a" + NCPU="$(nproc)" + INSTALL_PREFIX="/mingw64" + USE_SUDO="" + ;; + *) + echo "Unsupported OS: $OS" + exit 1 + ;; +esac build_cmake_project() { local name="$1" @@ -41,27 +61,49 @@ build_cmake_project() { rm -rf build mkdir build cd build - cmake .. \ + + cmake_gen="" + case "$OS" in + MINGW*|MSYS*) + cmake_gen="-G \"MinGW Makefiles\"" + ;; + esac + + eval cmake .. \ -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=/usr/local \ + -DCMAKE_INSTALL_PREFIX="$INSTALL_PREFIX" \ + $cmake_gen \ $extra_cmake_args - make -j"$NCPU" - sudo make install - echo "$name installed to /usr/local" + + case "$OS" in + MINGW*|MSYS*) + mingw32-make -j"$NCPU" + mingw32-make install + ;; + *) + make -j"$NCPU" + $USE_SUDO make install + ;; + esac + + echo "$name installed to $INSTALL_PREFIX" } -# On Linux, build SDL3 core + all satellite libs from source -if [ "$OS" = "Linux" ]; then - build_cmake_project "SDL3" "SDL" "" +# On Linux and Windows, build SDL3 core + all satellite libs from source +case "$OS" in + Linux|MINGW*|MSYS*) + build_cmake_project "SDL3" "SDL" "" - # Refresh linker cache so subsequent builds find libSDL3 - sudo ldconfig + if [ "$OS" = "Linux" ]; then + sudo ldconfig + fi - build_cmake_project "SDL3_image" "SDL_image" "" - build_cmake_project "SDL3_ttf" "SDL_ttf" "" -fi + build_cmake_project "SDL3_image" "SDL_image" "" + build_cmake_project "SDL3_ttf" "SDL_ttf" "" + ;; +esac -# Both platforms: build mixer and net from source +# All platforms: build mixer and net from source SDL3_CMAKE_ARGS="" if [ "$OS" = "Darwin" ]; then SDL3_CMAKE_ARGS="-DSDL3_INCLUDE_DIR=${SDL3_INCLUDE}/SDL3 -DSDL3_LIBRARY=${SDL3_LIB}" @@ -76,9 +118,12 @@ fi echo "" echo "=== Done ===" -if [ "$OS" = "Darwin" ]; then - echo "Brew-managed: SDL3, SDL3_image, SDL3_ttf (update with: brew upgrade sdl3 sdl3_image sdl3_ttf)" - echo "Source-built: SDL3_mixer, SDL3_net (installed to /usr/local/lib)" -else - echo "All SDL3 libs built from source and installed to /usr/local/lib" -fi +case "$OS" in + Darwin) + echo "Brew-managed: SDL3, SDL3_image, SDL3_ttf (update with: brew upgrade sdl3 sdl3_image sdl3_ttf)" + echo "Source-built: SDL3_mixer, SDL3_net (installed to /usr/local/lib)" + ;; + *) + echo "All SDL3 libs built from source and installed to $INSTALL_PREFIX" + ;; +esac From c59991e0186fab7fd686203126d1ec692af806e6 Mon Sep 17 00:00:00 2001 From: Kenny Cason Date: Thu, 12 Mar 2026 18:20:03 -0700 Subject: [PATCH 3/9] windows build attempt 3 --- .github/workflows/build.yml | 2 +- sdl3/build_sdl.sh | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 45594b2..073c0d9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -247,7 +247,7 @@ jobs: mingw-w64-x86_64-libwebp mingw-w64-x86_64-libtiff mingw-w64-x86_64-chipmunk - make + mingw-w64-x86_64-make - name: Checkout uses: actions/checkout@v4 diff --git a/sdl3/build_sdl.sh b/sdl3/build_sdl.sh index 08bcf39..e4137a9 100755 --- a/sdl3/build_sdl.sh +++ b/sdl3/build_sdl.sh @@ -62,19 +62,23 @@ build_cmake_project() { mkdir build cd build - cmake_gen="" case "$OS" in MINGW*|MSYS*) - cmake_gen="-G \"MinGW Makefiles\"" + cmake .. \ + -G "MinGW Makefiles" \ + -DCMAKE_MAKE_PROGRAM=mingw32-make \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="$INSTALL_PREFIX" \ + $extra_cmake_args + ;; + *) + cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="$INSTALL_PREFIX" \ + $extra_cmake_args ;; esac - eval cmake .. \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX="$INSTALL_PREFIX" \ - $cmake_gen \ - $extra_cmake_args - case "$OS" in MINGW*|MSYS*) mingw32-make -j"$NCPU" From 16731da317ba3dc2e28e5c5e0d815bbb75d6cf89 Mon Sep 17 00:00:00 2001 From: Kenny Cason Date: Thu, 12 Mar 2026 18:48:16 -0700 Subject: [PATCH 4/9] windows build attempt 4 --- kengine/src/nativeMain/kotlin/com/kengine/file/File.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kengine/src/nativeMain/kotlin/com/kengine/file/File.kt b/kengine/src/nativeMain/kotlin/com/kengine/file/File.kt index 22f329c..5347c5f 100644 --- a/kengine/src/nativeMain/kotlin/com/kengine/file/File.kt +++ b/kengine/src/nativeMain/kotlin/com/kengine/file/File.kt @@ -1,5 +1,6 @@ package com.kengine.file +import kotlinx.cinterop.convert import kotlinx.cinterop.refTo import kotlinx.cinterop.toKString import platform.posix.F_OK @@ -9,7 +10,7 @@ import platform.posix.getcwd object File { fun pwd(): String { val buffer = ByteArray(1024) - return getcwd(buffer.refTo(0), buffer.size.toULong())?.toKString() ?: "Unknown" + return getcwd(buffer.refTo(0), buffer.size.convert())?.toKString() ?: "Unknown" } fun isExist(path: String): Boolean { return access(path, F_OK) == 0 // F_OK checks existence only From 37a06cb30e588a107a205773b6d06158bf0500d6 Mon Sep 17 00:00:00 2001 From: Kenny Cason Date: Thu, 12 Mar 2026 19:46:29 -0700 Subject: [PATCH 5/9] windows build attempt 5 --- kengine/build.gradle.kts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kengine/build.gradle.kts b/kengine/build.gradle.kts index e651e56..ce43792 100644 --- a/kengine/build.gradle.kts +++ b/kengine/build.gradle.kts @@ -36,8 +36,10 @@ kotlin { nativeTarget.apply { binaries { staticLib() - sharedLib { - baseName = "kengine" + if (!PlatformConfig.isWindows) { + sharedLib { + baseName = "kengine" + } } all { linkerOpts(PlatformConfig.sharedLibLinkerOpts("SDL3", "SDL3_image", "SDL3_ttf")) From c6b85f427f16fa5f0c1ae90590a89d247aba8b51 Mon Sep 17 00:00:00 2001 From: Kenny Cason Date: Thu, 12 Mar 2026 21:20:46 -0700 Subject: [PATCH 6/9] windows build attempt 6: fix Konan sysroot patch path Use cygpath + USERPROFILE instead of $HOME to find .konan dir, since MSYS2 $HOME resolves to /home/user not C:\Users\user. Added verbose output for debugging. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/build.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 073c0d9..94f106c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -297,6 +297,31 @@ jobs: key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle.kts', 'gradle/libs.versions.toml') }} restore-keys: gradle-${{ runner.os }}- + - name: Patch Konan MinGW sysroot + run: | + # Kotlin/Native bundles an outdated MinGW sysroot whose CRT objects + # reference symbols missing from its bundled libs. Copy the system + # MSYS2 CRT libs over so the linker can resolve them. + # NOTE: $HOME in MSYS2 != Windows home; use USERPROFILE for .konan path + WIN_HOME="$(cygpath "$USERPROFILE")" + KONAN_MINGW="$WIN_HOME/.konan/dependencies/msys2-mingw-w64-x86_64-2/x86_64-w64-mingw32/lib" + if [ ! -d "$KONAN_MINGW" ]; then + echo "Konan sysroot not found, triggering download..." + ./gradlew :kengine:cinteropSdl3Native || true + fi + echo "KONAN_MINGW=$KONAN_MINGW" + ls "$KONAN_MINGW"/*.o 2>/dev/null | head -5 + if [ -d "$KONAN_MINGW" ]; then + echo "Patching Konan sysroot at $KONAN_MINGW" + cp -v /mingw64/x86_64-w64-mingw32/lib/libmingwex.a "$KONAN_MINGW/" + cp -v /mingw64/x86_64-w64-mingw32/lib/libmingw32.a "$KONAN_MINGW/" + echo "Done" + else + echo "ERROR: Konan MinGW sysroot not found at $KONAN_MINGW" + echo "Checking alternative locations..." + find "$WIN_HOME/.konan" -name "crt2.o" 2>/dev/null || echo "No crt2.o found" + fi + - name: Build all modules env: MSYS2_ROOT: D:/a/_temp/msys64 From 18c6115f7e5793acb43e36576a596072ab0e8daa Mon Sep 17 00:00:00 2001 From: Kenny Cason Date: Fri, 13 Mar 2026 02:35:05 -0700 Subject: [PATCH 7/9] windows build attempt 7: add MSYS2_ROOT to patch step The cinterop task needs MSYS2_ROOT to find SDL3 libs, otherwise it defaults to C:/msys64 instead of D:/a/_temp/msys64. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 94f106c..5ab5316 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -298,6 +298,8 @@ jobs: restore-keys: gradle-${{ runner.os }}- - name: Patch Konan MinGW sysroot + env: + MSYS2_ROOT: D:/a/_temp/msys64 run: | # Kotlin/Native bundles an outdated MinGW sysroot whose CRT objects # reference symbols missing from its bundled libs. Copy the system From 8ab5e376dc172caee948376d1043ffbb5997a977 Mon Sep 17 00:00:00 2001 From: Kenny Cason Date: Fri, 13 Mar 2026 03:05:21 -0700 Subject: [PATCH 8/9] windows build attempt 8: find CRT libs dynamically Use find instead of hardcoded path for libmingwex.a/libmingw32.a since MSYS2 MINGW64 may place them in different locations. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/build.yml | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5ab5316..80b3ad4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -315,12 +315,24 @@ jobs: ls "$KONAN_MINGW"/*.o 2>/dev/null | head -5 if [ -d "$KONAN_MINGW" ]; then echo "Patching Konan sysroot at $KONAN_MINGW" - cp -v /mingw64/x86_64-w64-mingw32/lib/libmingwex.a "$KONAN_MINGW/" - cp -v /mingw64/x86_64-w64-mingw32/lib/libmingw32.a "$KONAN_MINGW/" - echo "Done" + # Find libmingwex.a in the system MSYS2 installation + MINGWEX=$(find /mingw64 -name "libmingwex.a" 2>/dev/null | head -1) + MINGW32=$(find /mingw64 -name "libmingw32.a" 2>/dev/null | head -1) + echo "Found libmingwex.a at: $MINGWEX" + echo "Found libmingw32.a at: $MINGW32" + if [ -n "$MINGWEX" ] && [ -n "$MINGW32" ]; then + cp -v "$MINGWEX" "$KONAN_MINGW/" + cp -v "$MINGW32" "$KONAN_MINGW/" + echo "Patch applied successfully" + else + echo "ERROR: Could not find CRT libs in system MSYS2" + echo "Contents of /mingw64/lib/libmingw*:" + ls -la /mingw64/lib/libmingw* 2>/dev/null || echo " (none)" + echo "Searching all of /mingw64:" + find /mingw64 -name "libmingw*" 2>/dev/null || echo " (none found)" + fi else echo "ERROR: Konan MinGW sysroot not found at $KONAN_MINGW" - echo "Checking alternative locations..." find "$WIN_HOME/.konan" -name "crt2.o" 2>/dev/null || echo "No crt2.o found" fi From c769ccf45bd4cdd590aeb97a437782eb1bb32d71 Mon Sep 17 00:00:00 2001 From: Kenny Cason Date: Sat, 14 Mar 2026 07:07:26 -0700 Subject: [PATCH 9/9] windows build attempt 9: replace entire Konan sysroot lib Copying individual CRT files causes version mismatches (system libmingwex.a depends on system libmsvcrt.a). Instead, overlay all .a and .o files from system MSYS2 /mingw64/lib/ into the Konan sysroot so all CRT components are consistent. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/build.yml | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 80b3ad4..4c165da 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -314,23 +314,19 @@ jobs: echo "KONAN_MINGW=$KONAN_MINGW" ls "$KONAN_MINGW"/*.o 2>/dev/null | head -5 if [ -d "$KONAN_MINGW" ]; then - echo "Patching Konan sysroot at $KONAN_MINGW" - # Find libmingwex.a in the system MSYS2 installation - MINGWEX=$(find /mingw64 -name "libmingwex.a" 2>/dev/null | head -1) - MINGW32=$(find /mingw64 -name "libmingw32.a" 2>/dev/null | head -1) - echo "Found libmingwex.a at: $MINGWEX" - echo "Found libmingw32.a at: $MINGW32" - if [ -n "$MINGWEX" ] && [ -n "$MINGW32" ]; then - cp -v "$MINGWEX" "$KONAN_MINGW/" - cp -v "$MINGW32" "$KONAN_MINGW/" - echo "Patch applied successfully" - else - echo "ERROR: Could not find CRT libs in system MSYS2" - echo "Contents of /mingw64/lib/libmingw*:" - ls -la /mingw64/lib/libmingw* 2>/dev/null || echo " (none)" - echo "Searching all of /mingw64:" - find /mingw64 -name "libmingw*" 2>/dev/null || echo " (none found)" - fi + echo "Replacing Konan sysroot lib with system MSYS2 CRT" + # The bundled sysroot is too old — its crt2.o references symbols + # that don't exist in its bundled libs. Copying individual files + # causes version mismatches, so replace the entire lib directory. + SYS_LIB="/mingw64/lib" + echo "System lib at: $SYS_LIB ($(ls "$SYS_LIB"/*.a 2>/dev/null | wc -l) .a files)" + echo "Konan lib at: $KONAN_MINGW ($(ls "$KONAN_MINGW"/*.a 2>/dev/null | wc -l) .a files)" + # Back up the original, then overlay system libs + cp -r "$KONAN_MINGW" "${KONAN_MINGW}.bak" + cp -f "$SYS_LIB"/*.a "$KONAN_MINGW/" 2>/dev/null || true + cp -f "$SYS_LIB"/*.o "$KONAN_MINGW/" 2>/dev/null || true + echo "After patch: $(ls "$KONAN_MINGW"/*.a 2>/dev/null | wc -l) .a files" + echo "Patch applied successfully" else echo "ERROR: Konan MinGW sysroot not found at $KONAN_MINGW" find "$WIN_HOME/.konan" -name "crt2.o" 2>/dev/null || echo "No crt2.o found"