[K/N] Support compiler compilation in MSVC environment
The right way is to add something like KonanTarget.MSVC_X64, but doing so requires changes throughout whole compiler. It would be especially painful in HostManager, where we would need to deprecate KonanTarget.MINGW_X64 as host. Instead we "hack" ClangArgs to compile for x86_64-pc-windows-msvc instead of x86_64-pc-windows-gnu in JNI case. CI may contain custom MSVC and Windows Kit installation path, so we should support it. Things might break when machine has several MSVC installed (at custom and default path), but it sounds more like incorrect environment setup problem than ours.
This commit is contained in:
@@ -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")}"
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+39
-21
@@ -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<String> = mutableListOf<List<String>>().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=<absolute path>` 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) {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
-3
@@ -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)
|
||||
|
||||
|
||||
@@ -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<String>
|
||||
|
||||
object DefaultPath : Msvc() {
|
||||
override fun compilerFlags(): List<String> = emptyList()
|
||||
}
|
||||
|
||||
class CustomPath(
|
||||
private val includeDirectories: List<Path>,
|
||||
private val libraryDirectories: List<Path>
|
||||
) : 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<String> =
|
||||
includeDirectories.flatMap { listOf("-isystem", it.toAbsolutePath().toString()) } +
|
||||
libraryDirectories.flatMap { listOf("-L", it.toAbsolutePath().toString()) }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sealed class WindowsKit {
|
||||
abstract fun compilerFlags(): List<String>
|
||||
|
||||
object DefaultPath : WindowsKit() {
|
||||
override fun compilerFlags(): List<String> = emptyList()
|
||||
}
|
||||
|
||||
class CustomPath(
|
||||
private val includeDirectories: List<Path>,
|
||||
private val libraryDirectories: List<Path>
|
||||
) : 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<String> =
|
||||
includeDirectories.flatMap { listOf("-isystem", it.toAbsolutePath().toString()) } +
|
||||
libraryDirectories.flatMap { listOf("-L", it.toAbsolutePath().toString()) }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class WindowsSdkPartsProvider {
|
||||
object Local : WindowsSdkPartsProvider()
|
||||
object InternalServer : WindowsSdkPartsProvider()
|
||||
}
|
||||
Reference in New Issue
Block a user