From bf7040a119c77b7a5128e5ed40d0b749eb098e77 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Tue, 19 Feb 2019 14:23:00 +0300 Subject: [PATCH] Support experimental targets. (#2681) --- README.md | 2 ++ RELEASE_NOTES.md | 21 +++++++++----- backend.native/build.gradle | 3 +- build.gradle | 9 +++++- konan/konan.properties | 27 +++++++++++++++-- runtime/build.gradle | 2 -- .../kotlin/konan/target/Distribution.kt | 3 ++ .../kotlin/konan/target/KonanTarget.kt | 29 +++++++++++++++---- .../jetbrains/kotlin/konan/target/Linker.kt | 5 +++- .../jetbrains/kotlin/konan/target/Platform.kt | 3 +- .../kotlin/gradle/plugin/konan/KonanPlugin.kt | 6 +++- 11 files changed, 87 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 5cefeddb4b0..130351c619e 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ Then, build the compiler and libraries: ./gradlew bundle +To build with experimental targets support compile with `-Porg.jetbrains.kotlin.native.experimentalTargets`. + The build can take about an hour on a Macbook Pro. To run a shorter build with only the host compiler and libraries, run: diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 9794903236c..7fa3209ee41 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -23,18 +23,23 @@ the following platforms: * Mac OS X 10.11 and later (x86-64), host and target (`-target macos_x64`, default on macOS hosts) * Ubuntu Linux x86-64 (14.04, 16.04 and later), other Linux flavours may work as well, host and target - (`-target linux_x64`, default on Linux hosts, hosted on Linux, Windows and macOS) + (`-target linux_x64`, default on Linux hosts, hosted on Linux, Windows and macOS). * Microsoft Windows x86-64 (tested on Windows 7 and Windows 10), host and target (`-target mingw_x64`, - default on Windows hosts) - * Microsoft Windows x86-32 cross-compiled target (`-target mingw_x86`), hosted on Windows + default on Windows hosts). Experimental support is available on Linux and macOS hosts (requires Wine). + * Microsoft Windows x86-32 cross-compiled target (`-target mingw_x86`), hosted on Windows. + Experimental support is available on Linux and macOS hosts (requires Wine). * Apple iOS (armv7 and arm64 devices, x86 simulator), cross-compiled target - (`-target ios_arm32|ios_arm64|ios_x64`), hosted on macOS + (`-target ios_arm32|ios_arm64|ios_x64`), hosted on macOS. * Linux arm32 hardfp, Raspberry Pi, cross-compiled target (`-target raspberrypi`), hosted on Linux, Windows and macOS - * Linux MIPS big endian, cross-compiled target (`-target mips`), hosted on Linux - * Linux MIPS little endian, cross-compiled target (`-target mipsel`), hosted on Linux + * Linux MIPS big endian, cross-compiled target (`-target mips`), hosted on Linux. + * Linux MIPS little endian, cross-compiled target (`-target mipsel`), hosted on Linux. * Android arm32 and arm64 (`-target android_arm32|android_arm64`) target, hosted on Linux, macOS and Windows - (only `android_arm32` at the moment) - * WebAssembly (`-target wasm32`) target, hosted on Linux, Windows or macOS + (only `android_arm32` at the moment). + * WebAssembly (`-target wasm32`) target, hosted on Linux, Windows or macOS. + * Experimental support for Zephyr RTOS (`-target zephyr_stm32f4_disco`) is available on macOS, Linux + and Windows hosts. + + To enable experimental targets Kotlin/Native must be recompiled with `org.jetbrains.kotlin.native.experimentalTargets` Gradle property set. Adding support for other target platforms shouldn't be too hard, if LLVM support is available. diff --git a/backend.native/build.gradle b/backend.native/build.gradle index 10f278b3174..7d3277adeaa 100644 --- a/backend.native/build.gradle +++ b/backend.native/build.gradle @@ -211,7 +211,7 @@ task teamcityPublishStdLibSources { targetList.each { target -> def konanJvmArgs = [*HostManager.regularJvmArgs, - "-Dkonan.home=${rootProject.projectDir}", + "-Dkonan.home=${rootProject.projectDir}/dist", "-Djava.library.path=${project.buildDir}/nativelibs/$hostName", ] @@ -242,6 +242,7 @@ targetList.each { target -> dependsOn 'unzipStdlibSources' dependsOn ":runtime:${target}Runtime" + dependsOn ":distCompiler" } task("${target}Start", type: JavaExec) { diff --git a/build.gradle b/build.gradle index 15aa4fdda69..e84122915e1 100644 --- a/build.gradle +++ b/build.gradle @@ -41,7 +41,9 @@ convention.plugins.platformInfo = new PlatformInfo() ext { distDir = file('dist') dependenciesDir = DependencyProcessor.defaultDependenciesRoot - platformManager = new PlatformManager(DistributionKt.buildDistribution(projectDir.absolutePath)) + experimentalEnabled = project.hasProperty("org.jetbrains.kotlin.native.experimentalTargets") + platformManager = new PlatformManager(DistributionKt.buildDistribution(projectDir.absolutePath), + ext.experimentalEnabled) kotlinCommonStdlibModule="org.jetbrains.kotlin:kotlin-stdlib-common:${kotlinVersion}:sources" kotlinCompilerModule="org.jetbrains.kotlin:kotlin-compiler:${kotlinVersion}" @@ -296,6 +298,11 @@ task distCompiler(type: Copy) { from(project.file('konan')) { into('konan') } + if (experimentalEnabled) { + file('konan/experimentalTargetsEnabled').text = "" + } else { + delete('konan/experimentalTargetsEnabled') + } } task listDist(type: Exec) { diff --git a/konan/konan.properties b/konan/konan.properties index cce8c1ccd86..842618a8d20 100644 --- a/konan/konan.properties +++ b/konan/konan.properties @@ -338,6 +338,20 @@ llvmHome.mingw_x64 = msys2-mingw-w64-x86_64-gcc-7.3.0-clang-llvm-lld-6.0.1 targetToolchain.mingw_x64 = msys2-mingw-w64-x86_64-gcc-7.3.0-clang-llvm-lld-6.0.1 libffiDir.mingw_x64 = libffi-3.2.1-mingw-w64-x86-64 +targetToolchain.linux_x64-mingw_x64 = msys2-mingw-w64-x86_64-gcc-7.3.0-clang-llvm-lld-6.0.1 +targetToolchain.macos_x64-mingw_x64 = msys2-mingw-w64-x86_64-gcc-7.3.0-clang-llvm-lld-6.0.1 +dependencies.mingw_x64 = \ + msys2-mingw-w64-x86_64-gcc-7.3.0-clang-llvm-lld-6.0.1 \ + libffi-3.2.1-mingw-w64-x86-64 +dependencies.linux_x64-mingw_x64 = \ + msys2-mingw-w64-x86_64-gcc-7.3.0-clang-llvm-lld-6.0.1 \ + clang-llvm-6.0.1-linux-x86-64 \ + libffi-3.2.1-2-linux-x86-64 +dependencies.macos_x64-mingw_x64 = \ + msys2-mingw-w64-x86_64-gcc-7.3.0-clang-llvm-lld-6.0.1 \ + clang-llvm-6.0.1-darwin-macos \ + libffi-3.2.1-3-darwin-macos + quadruple.mingw_x64 = x86_64-w64-mingw32 targetSysRoot.mingw_x64 = msys2-mingw-w64-x86_64-gcc-7.3.0-clang-llvm-lld-6.0.1 # For using with Universal Windows Platform (UWP) we need to use this slower option. @@ -354,9 +368,6 @@ linkerKonanFlags.mingw_x64 =-static-libgcc -static-libstdc++ \ -Wl,--defsym,__cxa_demangle=Konan_cxa_demangle linkerOptimizationFlags.mingw_x64 = -Wl,--gc-sections entrySelector.mingw_x64 = -Wl,--defsym,main=Konan_main -dependencies.mingw_x64 = \ - msys2-mingw-w64-x86_64-gcc-7.3.0-clang-llvm-lld-6.0.1 \ - libffi-3.2.1-mingw-w64-x86-64 # Windows i686, based on mingw-w64. targetToolchain.mingw_x64-mingw_x86 = msys2-mingw-w64-i686-gcc-7.4.0-clang-llvm-6.0.1 @@ -364,6 +375,16 @@ dependencies.mingw_x64-mingw_x86 = \ msys2-mingw-w64-i686-gcc-7.4.0-clang-llvm-6.0.1 \ msys2-mingw-w64-x86_64-gcc-7.3.0-clang-llvm-lld-6.0.1 \ libffi-3.2.1-mingw-w64-x86-64 +targetToolchain.linux_x64-mingw_x86 = msys2-mingw-w64-i686-gcc-7.4.0-clang-llvm-6.0.1 +targetToolchain.macos_x64-mingw_x86 = msys2-mingw-w64-i686-gcc-7.4.0-clang-llvm-6.0.1 +dependencies.linux_x64-mingw_x86 = \ + msys2-mingw-w64-i686-gcc-7.4.0-clang-llvm-6.0.1 \ + clang-llvm-6.0.1-linux-x86-64 \ + libffi-3.2.1-2-linux-x86-64 +dependencies.macos_x64-mingw_x86 = \ + msys2-mingw-w64-i686-gcc-7.4.0-clang-llvm-6.0.1 \ + clang-llvm-6.0.1-darwin-macos \ + libffi-3.2.1-3-darwin-macos quadruple.mingw_x86 = i686-w64-mingw32 targetSysRoot.mingw_x86 = msys2-mingw-w64-i686-gcc-7.4.0-clang-llvm-6.0.1 diff --git a/runtime/build.gradle b/runtime/build.gradle index b852a961f75..5f5b02d2810 100644 --- a/runtime/build.gradle +++ b/runtime/build.gradle @@ -20,8 +20,6 @@ targetList.each { targetName -> dependsOn "${targetName}Debug" dependsOn "${targetName}Release" target targetName - if (!isWindows()) - compilerArgs '-fPIC' includeRuntime(delegate) linkerArgs project.file("../common/build/$targetName/hash.bc").path } diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Distribution.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Distribution.kt index ac6ab7a651b..8e1653bb7c2 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Distribution.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Distribution.kt @@ -39,6 +39,9 @@ class Distribution( val konanHome = findKonanHome() val konanSubdir = "$konanHome/konan" val mainPropertyFileName = "$konanSubdir/konan.properties" + val experimentalEnabled by lazy { + File("$konanSubdir/experimentalTargetsEnabled").exists + } private fun propertyFilesFromConfigDir(configDir: String, genericName: String): List { val directory = File(configDir, "platforms/$genericName") diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt index 07b84c86d67..5702511bad1 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt @@ -127,7 +127,7 @@ private class TargetManagerImpl(val userRequest: String?, val hostManager: HostM override val targetSuffix get() = target.name } -open class HostManager(protected val distribution: Distribution = Distribution()) { +open class HostManager(protected val distribution: Distribution = Distribution(), experimental: Boolean = false) { fun targetManager(userRequest: String? = null): TargetManager = TargetManagerImpl(userRequest, this) @@ -142,6 +142,8 @@ open class HostManager(protected val distribution: Distribution = Distribution() private val zephyrSubtargets = distribution.availableSubTarget("zephyr").map { ZEPHYR(it) } + private val experimentalEnabled = experimental || distribution.experimentalEnabled + private val configurableSubtargets = zephyrSubtargets val targetValues: List by lazy { @@ -171,7 +173,7 @@ open class HostManager(protected val distribution: Distribution = Distribution() return target } - val enabled: List by lazy { + val enabledRegular: List by lazy { when (host) { KonanTarget.LINUX_X64 -> listOf( KonanTarget.LINUX_X64, @@ -181,7 +183,7 @@ open class HostManager(protected val distribution: Distribution = Distribution() KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64, KonanTarget.WASM32 - ) + zephyrSubtargets + ) KonanTarget.MINGW_X64 -> listOf( KonanTarget.MINGW_X64, KonanTarget.MINGW_X86, @@ -191,7 +193,7 @@ open class HostManager(protected val distribution: Distribution = Distribution() // TODO: toolchain to be fixed for that to work. // KonanTarget.ANDROID_ARM64, KonanTarget.WASM32 - ) + zephyrSubtargets + ) KonanTarget.MACOS_X64 -> listOf( KonanTarget.MACOS_X64, KonanTarget.IOS_ARM32, @@ -202,12 +204,29 @@ open class HostManager(protected val distribution: Distribution = Distribution() KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64, KonanTarget.WASM32 - ) + zephyrSubtargets + ) else -> throw TargetSupportException("Unknown host platform: $host") } } + val enabledExperimental: List by lazy { + when (host) { + KonanTarget.LINUX_X64 -> listOf( + KonanTarget.MINGW_X86, KonanTarget.MINGW_X64 + ) + zephyrSubtargets + KonanTarget.MACOS_X64 -> listOf( + KonanTarget.MINGW_X86, KonanTarget.MINGW_X64 + ) + zephyrSubtargets + KonanTarget.MINGW_X64 -> listOf( + ) + zephyrSubtargets + else -> throw TargetSupportException("Unknown host platform: $host") + } + } + + val enabled : List + get() = if (experimentalEnabled) enabledRegular + enabledExperimental else enabledRegular + fun isEnabled(target: KonanTarget) = enabled.contains(target) companion object { diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Linker.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Linker.kt index 743712cae3b..7c13c65852d 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Linker.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Linker.kt @@ -303,7 +303,10 @@ open class MingwLinker(targetProperties: MingwConfigurables) return staticGnuArCommands(ar, executable, objectFiles, libraries) val dynamic = kind == LinkerOutputKind.DYNAMIC_LIBRARY - return listOf(Command(linker).apply { + return return listOf(when { + HostManager.hostIsMingw -> Command(linker) + else -> Command("wine64", "$linker.exe") + }.apply { +listOf("-o", executable) +objectFiles if (optimize) +linkerOptimizationFlags diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Platform.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Platform.kt index fe6bb48c20d..0ba5a07e0dd 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Platform.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Platform.kt @@ -29,7 +29,8 @@ class Platform(val configurables: Configurables) } } -class PlatformManager(distribution: Distribution = Distribution()) : HostManager(distribution) { +class PlatformManager(distribution: Distribution = Distribution(), experimental: Boolean = false) : + HostManager(distribution, experimental) { private val loaders = enabled.map { it to loadConfigurables(it, distribution.properties, DependencyProcessor.defaultDependenciesRoot.absolutePath) diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanPlugin.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanPlugin.kt index 5c55d544fc2..8bf99adc538 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanPlugin.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/konan/KonanPlugin.kt @@ -38,6 +38,7 @@ import org.jetbrains.kotlin.konan.KonanVersion import org.jetbrains.kotlin.konan.parseKonanVersion import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.buildDistribution import org.jetbrains.kotlin.konan.target.customerDistribution import org.jetbrains.kotlin.konan.util.DependencyProcessor import java.io.File @@ -114,7 +115,10 @@ internal val Project.konanArtifactsContainer: KonanArtifactContainer // stage (e.g. by getting it from maven as a plugin dependency) and bring back the PlatformManager here. internal val Project.hostManager: HostManager get() = findProperty("hostManager") as HostManager? ?: - HostManager(customerDistribution(konanHome)) + if (hasProperty("org.jetbrains.kotlin.native.experimentalTargets")) + HostManager(buildDistribution(rootProject.rootDir.absolutePath), true) + else + HostManager(customerDistribution(konanHome)) internal val Project.konanTargets: List get() = hostManager.toKonanTargets(konanExtension.targets)