diff --git a/kotlin-native/Interop/Indexer/build.gradle.kts b/kotlin-native/Interop/Indexer/build.gradle.kts index a1c9e8d0ef4..8e4ad1f33a5 100644 --- a/kotlin-native/Interop/Indexer/build.gradle.kts +++ b/kotlin-native/Interop/Indexer/build.gradle.kts @@ -38,7 +38,7 @@ val llvmDir = project.findProperty("llvmDir") val libclang = if (HostManager.hostIsMingw) { - "bin/libclang.dll" + "lib/libclang.lib" } else { "lib/${System.mapLibraryName("clang")}" } diff --git a/kotlin-native/konan/konan.properties b/kotlin-native/konan/konan.properties index e24e322c3fc..fe7fb36b649 100644 --- a/kotlin-native/konan/konan.properties +++ b/kotlin-native/konan/konan.properties @@ -867,8 +867,16 @@ runtimeDefinitions.android_x64 = __ANDROID__ USE_GCC_UNWIND=1 USE_ELF_SYMBOLS=1 llvmHome.mingw_x64 = $llvm.mingw_x64.dev targetToolchain.mingw_x64 = msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1 libffiDir.mingw_x64 = libffi-3.2.1-mingw-w64-x86-64 +windowsKitParts.mingw_x64 = windows-kit-x64-v1-alpha2 +msvcParts.mingw_x64 = msvc-x64-v1-alpha2 lldLocation.mingw_x64 = lld-11.1.0-windows-x64/ld.lld.exe +windows-kit-x64-v1-alpha2.default = \ + remote:internal + +msvc-x64-v1-alpha2.default = \ + remote:internal + targetToolchain.linux_x64-mingw_x64 = msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1 targetToolchain.macos_x64-mingw_x64 = msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1 # for Windows we are currently using LLDB 9 diff --git a/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangArgs.kt b/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangArgs.kt index f52fa8662e2..8c716215a3f 100644 --- a/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangArgs.kt +++ b/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangArgs.kt @@ -42,6 +42,9 @@ sealed class ClangArgs( private val target = configurables.target private val targetTriple = configurables.targetTriple + // TODO: Should be dropped in favor of real MSVC target. + private val argsForWindowsJni = forJni && target == KonanTarget.MINGW_X64 + private val clangArgsSpecificForKonanSources get() = configurables.runtimeDefinitions.map { "-D$it" } @@ -54,34 +57,50 @@ sealed class ClangArgs( } // TODO: Use buildList private val commonClangArgs: List = mutableListOf>().apply { - add(listOf("-B$binDir", "-fno-stack-protector")) + // Currently, MinGW toolchain contains old LLVM 8, and -fuse-ld=lld picks linker from there. + // And, unfortunately, `-fuse-ld=` doesn't work correctly for MSVC toolchain. + // That's why we just don't add $absoluteTargetToolchain/bin to binary search path in case of JNI compilation. + // TODO: Can be removed after MinGW sysroot update. + if (!argsForWindowsJni) { + add(listOf("-B$binDir")) + } else { + require(configurables is MingwConfigurables) + add(configurables.msvc.compilerFlags()) + add(configurables.windowsKit.compilerFlags()) + // Do not depend on link.exe from Visual Studio. + add(listOf("-fuse-ld=lld")) + } + add(listOf("-fno-stack-protector")) if (configurables is GccConfigurables) { add(listOf("--gcc-toolchain=${configurables.absoluteGccToolchain}")) } - if (configurables is AppleConfigurables) { - val osVersionMin = when (target) { - // Here we workaround Clang 8 limitation: macOS major version should be 10. - // So we compile runtime with version 10.16 and then override version in BitcodeCompiler. - // TODO: Fix with LLVM Update. - KonanTarget.MACOS_ARM64 -> "10.16" - else -> configurables.osVersionMin + val targetString: String = when { + argsForWindowsJni -> "x86_64-pc-windows-msvc" + configurables is AppleConfigurables -> { + val osVersionMin = when (target) { + // Here we workaround Clang 8 limitation: macOS major version should be 10. + // So we compile runtime with version 10.16 and then override version in BitcodeCompiler. + // TODO: Fix with LLVM Update. + KonanTarget.MACOS_ARM64 -> "10.16" + else -> configurables.osVersionMin + } + targetTriple.copy( + architecture = when (targetTriple.architecture) { + // TODO: LLVM 8 doesn't support arm64_32. + // We can use armv7k because they are compatible at bitcode level. + "arm64_32" -> "armv7k" + else -> targetTriple.architecture + }, + os = "${targetTriple.os}$osVersionMin" + ).toString() } - val targetArg = targetTriple.copy( - architecture = when (targetTriple.architecture) { - // TODO: LLVM 8 doesn't support arm64_32. - // We can use armv7k because they are compatible at bitcode level. - "arm64_32" -> "armv7k" - else -> targetTriple.architecture - }, - os = "${targetTriple.os}$osVersionMin" - ) - add(listOf("-target", targetArg.toString())) - } else { - add(listOf("-target", configurables.targetTriple.toString())) + else -> configurables.targetTriple.toString() } + add(listOf("-target", targetString)) val hasCustomSysroot = configurables is ZephyrConfigurables || configurables is WasmConfigurables || configurables is AndroidConfigurables + || argsForWindowsJni if (!hasCustomSysroot) { when (configurables) { // isysroot and sysroot on darwin are _almost_ synonyms. @@ -89,7 +108,6 @@ sealed class ClangArgs( is AppleConfigurables -> add(listOf("-isysroot", absoluteTargetSysRoot)) else -> add(listOf("--sysroot=$absoluteTargetSysRoot")) } - } // PIC is not required on Windows (and Clang will fail with `error: unsupported option '-fPIC'`) if (configurables !is MingwConfigurables) { diff --git a/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Configurables.kt b/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Configurables.kt index 92e2a0b8c2b..f89ebbd4683 100644 --- a/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Configurables.kt +++ b/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Configurables.kt @@ -107,6 +107,12 @@ interface AppleConfigurables : Configurables, ClangFlags { interface MingwConfigurables : Configurables, ClangFlags { val lldLocation get() = targetString("lldLocation")!! val absoluteLldLocation get() = absolute(lldLocation) + + val windowsKit: WindowsKit + val msvc: Msvc + + val windowsKitParts get() = hostString("windowsKitParts")!! + val msvcParts get() = hostString("msvcParts")!! } interface GccConfigurables : Configurables, ClangFlags { diff --git a/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ConfigurablesImpl.kt b/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ConfigurablesImpl.kt index 1089c0087f9..d5af616a59b 100644 --- a/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ConfigurablesImpl.kt +++ b/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ConfigurablesImpl.kt @@ -27,9 +27,6 @@ class GccConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: class AndroidConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?) : AndroidConfigurables, KonanPropertiesLoader(target, properties, baseDir) -class MingwConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?) - : MingwConfigurables, KonanPropertiesLoader(target, properties, baseDir) - class WasmConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?) : WasmConfigurables, KonanPropertiesLoader(target, properties, baseDir) diff --git a/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Windows.kt b/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Windows.kt new file mode 100644 index 00000000000..86381d10ebc --- /dev/null +++ b/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Windows.kt @@ -0,0 +1,111 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.konan.target + +import org.jetbrains.kotlin.konan.util.InternalServer +import java.nio.file.Path +import org.jetbrains.kotlin.konan.properties.KonanPropertiesLoader +import org.jetbrains.kotlin.konan.properties.Properties +import java.nio.file.Paths + +class MingwConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?) + : MingwConfigurables, KonanPropertiesLoader(target, properties, baseDir) { + override val windowsKit: WindowsKit by lazy { + when (windowsSdkPartsProvider) { + WindowsSdkPartsProvider.InternalServer -> createCustomWindowsKitPath(Paths.get(absolute(windowsKitParts))) + WindowsSdkPartsProvider.Local -> WindowsKit.DefaultPath + } + } + override val msvc: Msvc by lazy { + when (windowsSdkPartsProvider) { + WindowsSdkPartsProvider.InternalServer -> createCustomMsvcPath(Paths.get(absolute(msvcParts))) + WindowsSdkPartsProvider.Local -> Msvc.DefaultPath + } + } + + private val windowsSdkPartsProvider by lazy { + if (InternalServer.isAvailable) { + WindowsSdkPartsProvider.InternalServer + } else { + WindowsSdkPartsProvider.Local + } + } + + override val dependencies + get() = super.dependencies + when (windowsSdkPartsProvider) { + WindowsSdkPartsProvider.InternalServer -> listOf(windowsKitParts, msvcParts) + WindowsSdkPartsProvider.Local -> emptyList() + } +} + +private fun createCustomWindowsKitPath(windowsKitParts: Path): WindowsKit.CustomPath { + return WindowsKit.CustomPath( + libraryDirectories = listOf( + windowsKitParts.resolve("Lib").resolve("ucrt").resolve("x64"), + windowsKitParts.resolve("Lib").resolve("um").resolve("x64") + ), + includeDirectories = listOf( + windowsKitParts.resolve("Include").resolve("ucrt") + ) + ) +} + +private fun createCustomMsvcPath(msvcParts: Path): Msvc.CustomPath { + return Msvc.CustomPath( + libraryDirectories = listOf( + msvcParts.resolve("lib").resolve("x64") + ), + includeDirectories = listOf( + msvcParts.resolve("include") + ) + ) +} + +sealed class Msvc { + + abstract fun compilerFlags(): List + + object DefaultPath : Msvc() { + override fun compilerFlags(): List = emptyList() + } + + class CustomPath( + private val includeDirectories: List, + private val libraryDirectories: List + ) : Msvc() { + // Note that this approach doesn't exclude default VS path. + // TODO: A better (but harder) way would be LIB environment variable. + override fun compilerFlags(): List = + includeDirectories.flatMap { listOf("-isystem", it.toAbsolutePath().toString()) } + + libraryDirectories.flatMap { listOf("-L", it.toAbsolutePath().toString()) } + + } +} + +sealed class WindowsKit { + abstract fun compilerFlags(): List + + object DefaultPath : WindowsKit() { + override fun compilerFlags(): List = emptyList() + } + + class CustomPath( + private val includeDirectories: List, + private val libraryDirectories: List + ) : WindowsKit() { + // Note that this approach doesn't exclude default Windows Kit path. + // TODO: A better (but harder) way would be LIB environment variable. + override fun compilerFlags(): List = + includeDirectories.flatMap { listOf("-isystem", it.toAbsolutePath().toString()) } + + libraryDirectories.flatMap { listOf("-L", it.toAbsolutePath().toString()) } + + } +} + +private sealed class WindowsSdkPartsProvider { + object Local : WindowsSdkPartsProvider() + object InternalServer : WindowsSdkPartsProvider() +} \ No newline at end of file