From a9a85594104ad0265d119728e3191e79879d9359 Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov <41585329+ddolovov@users.noreply.github.com> Date: Thu, 18 Apr 2019 10:19:28 +0700 Subject: [PATCH] Support building tetris sample for MinGW32 (#2890) * Samples: Make API inside of MPPTools less verbose * Samples: Ability to build tetris for MinGW X86 * Samples: Instructions for installing SDL2 to MinGW32 * Fix location of MinGW32 * Simplify MinGW32 check --- samples/buildSrc/src/main/kotlin/Internals.kt | 19 ++++++----- samples/buildSrc/src/main/kotlin/MPPTools.kt | 24 ++++++++----- samples/tetris/README.md | 5 +-- samples/tetris/build.gradle | 34 +++++++++++++++---- samples/tetris/gradle.properties | 3 ++ 5 files changed, 60 insertions(+), 25 deletions(-) diff --git a/samples/buildSrc/src/main/kotlin/Internals.kt b/samples/buildSrc/src/main/kotlin/Internals.kt index 466f15e47f5..d3c994c708f 100644 --- a/samples/buildSrc/src/main/kotlin/Internals.kt +++ b/samples/buildSrc/src/main/kotlin/Internals.kt @@ -6,11 +6,11 @@ import org.gradle.api.NamedDomainObjectCollection import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project -import org.gradle.api.plugins.ExtraPropertiesExtension import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetPreset /* * This file includes internal short-cuts visible only inside of the 'buildSrc' module. @@ -19,20 +19,21 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation internal val hostOs by lazy { System.getProperty("os.name") } internal val userHome by lazy { System.getProperty("user.home") } -internal val Project.ext: ExtraPropertiesExtension - get() = extensions.getByName("ext") as ExtraPropertiesExtension +internal val mingwX64Path by lazy { System.getenv("MINGW64_DIR") ?: "c:/msys64/mingw64" } +internal val mingwX86Path by lazy { System.getenv("MINGW32_DIR") ?: "c:/msys32/mingw32" } + internal val Project.kotlin: KotlinMultiplatformExtension get() = extensions.getByName("kotlin") as KotlinMultiplatformExtension -internal val NamedDomainObjectCollection>.macosX64: KotlinTargetPreset<*> - get() = getByName(::macosX64.name) as KotlinTargetPreset<*> +internal val NamedDomainObjectCollection>.macosX64: KotlinNativeTargetPreset + get() = getByName(::macosX64.name) as KotlinNativeTargetPreset -internal val NamedDomainObjectCollection>.linuxX64: KotlinTargetPreset<*> - get() = getByName(::linuxX64.name) as KotlinTargetPreset<*> +internal val NamedDomainObjectCollection>.linuxX64: KotlinNativeTargetPreset + get() = getByName(::linuxX64.name) as KotlinNativeTargetPreset -internal val NamedDomainObjectCollection>.mingwX64: KotlinTargetPreset<*> - get() = getByName(::mingwX64.name) as KotlinTargetPreset<*> +internal val NamedDomainObjectCollection>.mingwX64: KotlinNativeTargetPreset + get() = getByName(::mingwX64.name) as KotlinNativeTargetPreset internal val NamedDomainObjectContainer>.main: KotlinNativeCompilation get() = getByName(::main.name) as KotlinNativeCompilation diff --git a/samples/buildSrc/src/main/kotlin/MPPTools.kt b/samples/buildSrc/src/main/kotlin/MPPTools.kt index 1f7ae4b6c26..7e7d37fa8bb 100644 --- a/samples/buildSrc/src/main/kotlin/MPPTools.kt +++ b/samples/buildSrc/src/main/kotlin/MPPTools.kt @@ -10,6 +10,8 @@ import org.gradle.api.Project import org.gradle.api.Task import org.jetbrains.kotlin.gradle.plugin.KotlinTarget import org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetPreset +import org.jetbrains.kotlin.konan.target.KonanTarget import java.nio.file.Paths /* @@ -27,8 +29,12 @@ val isWindows by lazy { hostOs.startsWith("Windows") } val isLinux by lazy { hostOs == "Linux" } // Short-cuts for mostly used paths. -@get:JvmName("mingwPath") -val mingwPath by lazy { System.getenv("MINGW64_DIR") ?: "c:/msys64/mingw64" } +@JvmOverloads +fun mingwPath(preset: KotlinNativeTargetPreset? = null) = when (preset?.konanTarget) { + null, is KonanTarget.MINGW_X64 -> mingwX64Path + is KonanTarget.MINGW_X86 -> mingwX86Path + else -> error("Not a MinGW preset: $preset") +} @get:JvmName("kotlinNativeDataPath") val kotlinNativeDataPath by lazy { @@ -39,17 +45,19 @@ val kotlinNativeDataPath by lazy { @JvmOverloads fun defaultHostPreset( subproject: Project, - whitelist: List> = listOf(subproject.kotlin.presets.macosX64, subproject.kotlin.presets.linuxX64, subproject.kotlin.presets.mingwX64) + whitelist: List> = with(subproject.kotlin.presets) { listOf(macosX64, linuxX64, mingwX64) } ): KotlinTargetPreset<*> { if (whitelist.isEmpty()) throw Exception("Preset whitelist must not be empty in Kotlin/Native ${subproject.displayName}.") - val presetCandidate = when { - isMacos -> subproject.kotlin.presets.macosX64 - isLinux -> subproject.kotlin.presets.linuxX64 - isWindows -> subproject.kotlin.presets.mingwX64 - else -> null + val presetCandidate = with(subproject.kotlin.presets) { + when { + isMacos -> macosX64 + isLinux -> linuxX64 + isWindows -> mingwX64 + else -> null + } } return if (presetCandidate != null && presetCandidate in whitelist) diff --git a/samples/tetris/README.md b/samples/tetris/README.md index fd843698ffb..708b49aacfd 100644 --- a/samples/tetris/README.md +++ b/samples/tetris/README.md @@ -7,8 +7,9 @@ of cross-platform game and multimedia applications. Install SDL2 development files (see https://www.libsdl.org/download-2.0.php). For Mac - copy `SDL2.framework` to `$HOME/Library/Frameworks`. For Debian-like Linux - use `apt-get install libsdl2-dev`. -For Windows - `pacman -S mingw-w64-x86_64-SDL2` in MinGW64 console, if you do -not have MSYS2-MinGW64 installed - install it first as described in http://www.msys2.org +For Windows - `pacman -S mingw-w64-x86_64-SDL2` in MinGW64 console +or `pacman -S mingw-w64-i686-SDL2` in MinGW32 console. If you do not have MSYS2-MinGW64 (MSYS2-MinGW32) +installed - install it first as described in http://www.msys2.org To build Tetris application for your host platform use `../gradlew assemble`. diff --git a/samples/tetris/build.gradle b/samples/tetris/build.gradle index a604c55ff7c..7bdb54b314b 100644 --- a/samples/tetris/build.gradle +++ b/samples/tetris/build.gradle @@ -18,9 +18,10 @@ kotlin { case presets.linuxX64: compilations.main.linkerOpts '-L/usr/lib64', '-L/usr/lib/x86_64-linux-gnu', '-lSDL2' break + case presets.mingwX86: case presets.mingwX64: compilations.main.linkerOpts winCompiledResourceFile.path, - "-L${MPPTools.mingwPath()}/lib", + "-L${MPPTools.mingwPath(hostPreset)}/lib", '-Wl,-Bstatic', '-lstdc++', '-static', @@ -47,8 +48,9 @@ kotlin { case presets.linuxX64: includeDirs '/usr/include/SDL2' break + case presets.mingwX86: case presets.mingwX64: - includeDirs "${MPPTools.mingwPath()}/include/SDL2" + includeDirs "${MPPTools.mingwPath(hostPreset)}/include/SDL2" break case presets.linuxArm32Hfp: includeDirs "${MPPTools.kotlinNativeDataPath()}/dependencies/target-sysroot-1-raspberrypi/usr/include/SDL2" @@ -60,10 +62,16 @@ kotlin { } } -if (hostPreset == kotlin.presets.mingwX64) { +if ((hostPreset == kotlin.presets.mingwX86) || (hostPreset == kotlin.presets.mingwX64)) { tasks.create('compileWindowsResources', Exec) { + def windresDir = null + if (hostPreset == kotlin.presets.mingwX86) + windresDir = "${MPPTools.kotlinNativeDataPath()}/dependencies/msys2-mingw-w64-i686-gcc-7.4.0-clang-llvm-6.0.1/bin" + else + windresDir = "${MPPTools.kotlinNativeDataPath()}/dependencies/msys2-mingw-w64-x86_64-gcc-7.3.0-clang-llvm-lld-6.0.1/bin" + assert windresDir != null + def winResourceFile = kotlin.sourceSets.tetrisMain.resources.files.find { it.name == 'Tetris.rc' } - def windresDir = "${MPPTools.kotlinNativeDataPath()}/dependencies/msys2-mingw-w64-x86_64-gcc-7.3.0-clang-llvm-lld-6.0.1/bin" def path = System.getenv('PATH') commandLine "$windresDir/windres", winResourceFile, '-O', 'coff', '-o', winCompiledResourceFile @@ -104,7 +112,16 @@ afterEvaluate { } private def determinePreset() { - def preset = isRaspberryPiBuild() ? kotlin.presets.linuxArm32Hfp /* aka RaspberryPi */ : MPPTools.defaultHostPreset(project) + def preset = null + if (isRaspberryPiBuild()) { + preset = kotlin.presets.linuxArm32Hfp // aka RaspberryPi + } else if (isMingwX86Build()) { + preset = kotlin.presets.mingwX86 + } else { + preset = MPPTools.defaultHostPreset(project) + } + assert preset != null + println("$project has been configured for ${preset.name} platform.") preset } @@ -112,4 +129,9 @@ private def determinePreset() { // If host platform is Linux and RaspberryPi target is activated. private boolean isRaspberryPiBuild() { MPPTools.isLinux() && Boolean.parseBoolean(project.findProperty('tetris.raspberrypi.build') as String) -} \ No newline at end of file +} + +// If host platform is Windows and x86 target is activated. +private boolean isMingwX86Build() { + MPPTools.isWindows() && Boolean.parseBoolean(project.findProperty('tetris.mingwX86.build') as String) +} diff --git a/samples/tetris/gradle.properties b/samples/tetris/gradle.properties index 0c7c2c2a6d4..6268795b943 100644 --- a/samples/tetris/gradle.properties +++ b/samples/tetris/gradle.properties @@ -3,3 +3,6 @@ kotlin.import.noCommonSourceSets=true # Uncomment if you would like to build for RaspberryPi: #tetris.raspberrypi.build=true + +# Uncomment if you would like to build for MingwX86: +#tetris.mingwX86.build=true