From d4b47ac709e375d9b39888eb93f71c3def7451d0 Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Fri, 19 Jan 2018 17:11:48 +0300 Subject: [PATCH] Splitted KonanProperties into Configurables hierarchy. Untangled Platfrom classes from the LinkStage and Distribution. Simplified clang management a little. --- Interop/Indexer/build.gradle | 4 +- Interop/Runtime/build.gradle | 2 +- .../native/interop/gen/jvm/ToolConfig.kt | 27 +- .../kotlin/backend/konan/CAdapterCompile.kt | 2 +- .../kotlin/backend/konan/Distribution.kt | 32 +- .../kotlin/backend/konan/KonanConfig.kt | 18 +- .../kotlin/backend/konan/LinkStage.kt | 319 +----------------- .../konan/library/SearchPathResolver.kt | 11 +- .../backend/konan/objcexport/ObjCExport.kt | 4 +- backend.native/konan.properties | 3 + build.gradle | 8 +- .../org/jetbrains/kotlin/ExecClang.groovy | 4 +- .../kotlin/NativeInteropPlugin.groovy | 2 +- dependencies/build.gradle | 10 +- .../org/jetbrains/kotlin/cli/klib/main.kt | 6 +- .../kotlin/konan/file}/NativeFileType.kt | 3 +- .../kotlin/konan/target/ClangArgs.kt | 105 +++--- .../kotlin/konan/target/ClangManager.kt | 74 ---- .../kotlin/konan/target/Configurables.kt | 80 +++++ .../kotlin/konan/target/ConfigurablesImpl.kt | 54 +++ .../kotlin/konan/target/KonanProperties.kt | 83 ++--- .../jetbrains/kotlin/konan/target/Linker.kt | 303 +++++++++++++++++ .../jetbrains/kotlin/konan/target/Platform.kt | 41 +++ .../kotlin/konan/util/DependencyProcessor.kt | 14 +- .../kotlin/cli/utilities/InteropCompiler.kt | 2 +- 25 files changed, 653 insertions(+), 558 deletions(-) rename {backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan => shared/src/main/kotlin/org/jetbrains/kotlin/konan/file}/NativeFileType.kt (94%) delete mode 100644 shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangManager.kt create mode 100644 shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Configurables.kt create mode 100644 shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ConfigurablesImpl.kt create mode 100644 shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Linker.kt create mode 100644 shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Platform.kt diff --git a/Interop/Indexer/build.gradle b/Interop/Indexer/build.gradle index 1416541cc5b..08101c6b097 100644 --- a/Interop/Indexer/build.gradle +++ b/Interop/Indexer/build.gradle @@ -72,7 +72,7 @@ model { } binaries.all { - cCompiler.args hostCompilerArgsForJni + cCompiler.args hostPlatform.clang.hostCompilerArgsForJni cCompiler.args.addAll(cflags) } @@ -157,4 +157,4 @@ task updatePrebuilt { into 'prebuilt/nativeInteropStubs/c' } } -} \ No newline at end of file +} diff --git a/Interop/Runtime/build.gradle b/Interop/Runtime/build.gradle index f0dd23a9bb7..d52aadd09e6 100644 --- a/Interop/Runtime/build.gradle +++ b/Interop/Runtime/build.gradle @@ -33,7 +33,7 @@ model { def hostLibffiDir = rootProject.ext.get("${host}LibffiDir") - cCompiler.args hostCompilerArgsForJni + cCompiler.args hostPlatform.clang.hostCompilerArgsForJni cCompiler.args "-I$hostLibffiDir/include" linker.args "$hostLibffiDir/lib/libffi.a" diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/ToolConfig.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/ToolConfig.kt index 126217e0ee3..3b83ad9dd16 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/ToolConfig.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/ToolConfig.kt @@ -16,10 +16,13 @@ package org.jetbrains.kotlin.native.interop.tool -import org.jetbrains.kotlin.konan.file.* -import org.jetbrains.kotlin.konan.properties.* -import org.jetbrains.kotlin.konan.target.* -import org.jetbrains.kotlin.konan.util.* +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.properties.loadProperties +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.PlatformManager +import org.jetbrains.kotlin.konan.target.TargetManager +import org.jetbrains.kotlin.konan.util.DependencyProcessor +import org.jetbrains.kotlin.konan.util.visibleName class ToolConfig(userProvidedTargetName: String?, userProvidedKonanProperties: String?, runnerProvidedKonanHome: String) { @@ -33,23 +36,21 @@ class ToolConfig(userProvidedTargetName: String?, userProvidedKonanProperties: S private val dependencies = DependencyProcessor.defaultDependenciesRoot - private val targetProperties = KonanProperties(target, properties, dependencies.path) + private val platform = PlatformManager(properties, dependencies.path).platform(target) val substitutions = mapOf ( "target" to target.detailedName, "arch" to target.architecture.visibleName) - fun downloadDependencies() = targetProperties.downloadDependencies() + fun downloadDependencies() = platform.downloadDependencies() - val llvmHome = targetProperties.absoluteLlvmHome + val defaultCompilerOpts = + platform.clang.targetLibclangArgs.toList() - val sysRoot get() = targetProperties.absoluteTargetSysRoot + val llvmHome = platform.absoluteLlvmHome + val sysRoot = platform.absoluteTargetSysRoot - val defaultCompilerOpts = ClangManager(properties, dependencies.path) - .targetLibclangArgs(targetProperties.target).toList() - - - val libclang = when (host) { + val libclang = when (host) { KonanTarget.MINGW -> "$llvmHome/bin/libclang.dll" else -> "$llvmHome/lib/${System.mapLibraryName("clang")}" } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterCompile.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterCompile.kt index bcc0059243d..ad67e0706fd 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterCompile.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterCompile.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.konan.exec.* import org.jetbrains.kotlin.konan.target.* import org.jetbrains.kotlin.konan.file.* -fun produceCAdapterBitcode(clang: TargetClang, cppFileName: String, bitcodeFileName: String) { +fun produceCAdapterBitcode(clang: ClangArgs, cppFileName: String, bitcodeFileName: String) { val clangCommand = clang.clangCXX("-std=c++11", cppFileName, "-emit-llvm", "-c", "-o", bitcodeFileName) Command(clangCommand).execute() } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Distribution.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Distribution.kt index 6d37d4351fa..f2c99fa11d2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Distribution.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Distribution.kt @@ -16,21 +16,15 @@ package org.jetbrains.kotlin.backend.konan -import org.jetbrains.kotlin.konan.target.* import org.jetbrains.kotlin.konan.file.* import org.jetbrains.kotlin.konan.properties.* +import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.konan.util.visibleName import org.jetbrains.kotlin.konan.util.DependencyProcessor -class Distribution(val targetManager: TargetManager, - val propertyFileOverride: String? = null, - val runtimeFileOverride: String? = null) { - - val target = targetManager.target - val targetName = targetManager.targetName - val host = TargetManager.host - val hostSuffix = TargetManager.hostSuffix - val hostTargetSuffix = targetManager.hostTargetSuffix - val targetSuffix = targetManager.targetSuffix +class Distribution(val target: KonanTarget, + propertyFileOverride: String? = null, + runtimeFileOverride: String? = null) { val localKonanDir = "${File.userHome}/.konan" @@ -46,22 +40,10 @@ class Distribution(val targetManager: TargetManager, val klib = "$konanHome/klib" val stdlib = "$klib/common/stdlib" + + val targetName = target.visibleName val defaultNatives = "$konanHome/konan/targets/${targetName}/native" val runtime = runtimeFileOverride ?: "$stdlib/targets/${targetName}/native/runtime.bc" val dependenciesDir = DependencyProcessor.defaultDependenciesRoot.absolutePath - - val targetProperties = KonanProperties(target, properties, dependenciesDir) - - val llvmHome = targetProperties.absoluteLlvmHome - val llvmBin = "$llvmHome/bin" - val llvmLib = "$llvmHome/lib" - val llvmLto = "$llvmBin/llvm-lto" - - private val libLTODir = when (TargetManager.host) { - KonanTarget.MACBOOK, KonanTarget.LINUX -> llvmLib - KonanTarget.MINGW -> llvmBin - else -> error("Don't know libLTO location for this platform.") - } - val libLTO = "$libLTODir/${System.mapLibraryName("LTO")}" } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt index 4ee11c5f412..f35257a729f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt @@ -52,19 +52,17 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration val indirectBranchesAreAllowed = target != KonanTarget.WASM32 - private fun Distribution.prepareDependencies(checkDependencies: Boolean) { - if (checkDependencies) { - targetProperties.downloadDependencies() + internal val distribution = Distribution(target, + configuration.get(KonanConfigKeys.PROPERTY_FILE), + configuration.get(KonanConfigKeys.RUNTIME_FILE)) + + internal val platform = PlatformManager(distribution.properties, distribution.dependenciesDir).platform(target).apply { + if (configuration.getBoolean(KonanConfigKeys.CHECK_DEPENDENCIES)) { + downloadDependencies() } } - internal val distribution = Distribution(targetManager, - configuration.get(KonanConfigKeys.PROPERTY_FILE), - configuration.get(KonanConfigKeys.RUNTIME_FILE)).apply { - prepareDependencies(configuration.getBoolean(KonanConfigKeys.CHECK_DEPENDENCIES)) - } - - internal val clang = TargetClang(distribution.properties, distribution.dependenciesDir, target) + internal val clang = platform.clang internal val produce get() = configuration.get(KonanConfigKeys.PRODUCE)!! private val prefix = produce.prefix(target) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt index c932059b8a0..6277b3bb179 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/LinkStage.kt @@ -16,310 +16,21 @@ package org.jetbrains.kotlin.backend.konan -import java.lang.ProcessBuilder -import java.lang.ProcessBuilder.Redirect import org.jetbrains.kotlin.konan.KonanExternalToolFailure import org.jetbrains.kotlin.konan.exec.Command import org.jetbrains.kotlin.konan.file.* -import org.jetbrains.kotlin.konan.properties.* import org.jetbrains.kotlin.konan.target.* typealias BitcodeFile = String typealias ObjectFile = String typealias ExecutableFile = String -// Use "clang -v -save-temps" to write linkCommand() method -// for another implementation of this class. -internal abstract class PlatformFlags(val properties: KonanProperties) { - val llvmLtoNooptFlags = properties.llvmLtoNooptFlags - val llvmLtoOptFlags = properties.llvmLtoOptFlags - val llvmLtoFlags = properties.llvmLtoFlags - val llvmLtoDynamicFlags = properties.llvmLtoDynamicFlags - val entrySelector = properties.entrySelector - val linkerOptimizationFlags = properties.linkerOptimizationFlags - val linkerKonanFlags = properties.linkerKonanFlags - val linkerNoDebugFlags = properties.linkerNoDebugFlags - val linkerDynamicFlags = properties.linkerDynamicFlags - val llvmDebugOptFlags = properties.llvmDebugOptFlags - val s2wasmFlags = properties.s2wasmFlags - val targetToolchain = properties.absoluteTargetToolchain - val targetSysRoot = properties.absoluteTargetSysRoot - - val targetLibffi = properties.libffiDir ?.let { listOf("${properties.absoluteLibffiDir}/lib/libffi.a") } ?: emptyList() - - open val useCompilerDriverAsLinker: Boolean get() = false // TODO: refactor. - - abstract fun linkCommand(objectFiles: List, - executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command - - open fun linkCommandSuffix(): List = emptyList() - - protected fun propertyTargetString(name: String) - = properties.targetString(name)!! - protected fun propertyTargetList(name: String) - = properties.targetList(name) - - abstract fun filterStaticLibraries(binaries: List): List - - open fun linkStaticLibraries(binaries: List): List { - val libraries = filterStaticLibraries(binaries) - // Let's just pass them as absolute paths - return libraries - } - -} - -internal open class AndroidPlatform(distribution: Distribution) - : PlatformFlags(distribution.targetProperties) { - - private val prefix = "$targetToolchain/bin/" - private val clang = "$prefix/clang" - - override val useCompilerDriverAsLinker: Boolean get() = true - - override fun filterStaticLibraries(binaries: List) - = binaries.filter { it.isUnixStaticLib } - - override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command { - // liblog.so must be linked in, as we use its functionality in runtime. - return Command(clang).apply { - + "-o" - + executable - + "-fPIC" - + "-shared" - + "-llog" - + objectFiles - if (optimize) + linkerOptimizationFlags - if (!debug) + linkerNoDebugFlags - if (dynamic) + linkerDynamicFlags - + linkerKonanFlags - } - } -} - -internal open class MacOSBasedPlatform(distribution: Distribution) - : PlatformFlags(distribution.targetProperties) { - - private val linker = "$targetToolchain/usr/bin/ld" - internal val dsymutil = "${distribution.llvmBin}/llvm-dsymutil" - internal val libLTO = distribution.libLTO - - open val osVersionMin by lazy { - listOf( - propertyTargetString("osVersionMinFlagLd"), - properties.osVersionMin!! + ".0") - } - - override fun filterStaticLibraries(binaries: List) - = binaries.filter { it.isUnixStaticLib } - - override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command { - return object : Command(linker) {} .apply { - + "-demangle" - + listOf("-object_path_lto", "temporary.o", "-lto_library", libLTO) - + listOf("-dynamic", "-arch", propertyTargetString("arch")) - + osVersionMin - + listOf("-syslibroot", targetSysRoot, "-o", executable) - + objectFiles - if (optimize) + linkerOptimizationFlags - if (!debug) + linkerNoDebugFlags - if (dynamic) + linkerDynamicFlags - + linkerKonanFlags - + "-lSystem" - } - } - - fun dsymUtilCommand(executable: ExecutableFile, outputDsymBundle: String) = - object : Command(dsymutilCommand(executable, outputDsymBundle)) { - override fun runProcess(): Int = - executeCommandWithFilter(command) - } - - // TODO: consider introducing a better filtering directly in Command. - private fun executeCommandWithFilter(command: List): Int { - val builder = ProcessBuilder(command) - - // Inherit main process output streams. - val isDsymUtil = (command[0] == dsymutil) - - builder.redirectOutput(Redirect.INHERIT) - builder.redirectInput(Redirect.INHERIT) - if (!isDsymUtil) - builder.redirectError(Redirect.INHERIT) - - val process = builder.start() - if (isDsymUtil) { - /** - * llvm-lto has option -alias that lets tool to know which symbol we use instead of _main, - * llvm-dsym doesn't have such a option, so we ignore annoying warning manually. - */ - val errorStream = process.errorStream - val outputStream = bufferedReader(errorStream) - while (true) { - val line = outputStream.readLine() ?: break - if (!line.contains("warning: could not find object file symbol for symbol _main")) - System.err.println(line) - } - outputStream.close() - } - val exitCode = process.waitFor() - return exitCode - } - - open fun dsymutilCommand(executable: ExecutableFile, outputDsymBundle: String): List = - listOf(dsymutil, executable, "-o", outputDsymBundle) - - open fun dsymutilDryRunVerboseCommand(executable: ExecutableFile): List = - listOf(dsymutil, "-dump-debug-map" ,executable) -} - -internal open class LinuxBasedPlatform(val distribution: Distribution) - : PlatformFlags(distribution.targetProperties) { - - private val llvmLib = distribution.llvmLib - private val libGcc = "$targetSysRoot/${propertyTargetString("libGcc")}" - private val linker = "$targetToolchain/bin/ld.gold" - private val pluginOptimizationFlags = propertyTargetList("pluginOptimizationFlags") - private val specificLibs - = propertyTargetList("abiSpecificLibraries").map { "-L${targetSysRoot}/$it" } - - override fun filterStaticLibraries(binaries: List) - = binaries.filter { it.isUnixStaticLib } - - override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command { - val isMips = (distribution.target == KonanTarget.LINUX_MIPS32 || - distribution.target == KonanTarget.LINUX_MIPSEL32) - // TODO: Can we extract more to the konan.properties? - return Command(linker).apply { - + "--sysroot=${targetSysRoot}" - + "-export-dynamic" - + "-z" - + "relro" - + "--build-id" - + "--eh-frame-hdr" - // + "-m" - // + "elf_x86_64", - + "-dynamic-linker" - + propertyTargetString("dynamicLinker") - + "-o" - + executable - if (!dynamic) + "$targetSysRoot/usr/lib64/crt1.o" - + "$targetSysRoot/usr/lib64/crti.o" - if (dynamic) - + "$libGcc/crtbeginS.o" - else - + "$libGcc/crtbegin.o" - + "-L$llvmLib" - + "-L$libGcc" - if (!isMips) + "--hash-style=gnu" // MIPS doesn't support hash-style=gnu - + specificLibs - + listOf("-L$targetSysRoot/../lib", "-L$targetSysRoot/lib", "-L$targetSysRoot/usr/lib") - if (optimize) { - + "-plugin" - +"$llvmLib/LLVMgold.so" - + pluginOptimizationFlags - } - if (optimize) + linkerOptimizationFlags - if (!debug) + linkerNoDebugFlags - if (dynamic) + linkerDynamicFlags - + objectFiles - + linkerKonanFlags - + listOf("-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed", - "-lc", "-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed") - if (dynamic) - + "$libGcc/crtendS.o" - else - + "$libGcc/crtend.o" - + "$targetSysRoot/usr/lib64/crtn.o" - } - } -} - -internal open class MingwPlatform(distribution: Distribution) - : PlatformFlags(distribution.targetProperties) { - - private val linker = "$targetToolchain/bin/clang++" - - override val useCompilerDriverAsLinker: Boolean get() = true - - override fun filterStaticLibraries(binaries: List) - = binaries.filter { it.isWindowsStaticLib || it.isUnixStaticLib } - - override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command { - return Command(linker).apply { - + listOf("-o", executable) - + objectFiles - if (optimize) + linkerOptimizationFlags - if (!debug) + linkerNoDebugFlags - if (dynamic) + linkerDynamicFlags - } - } - - override fun linkCommandSuffix() = linkerKonanFlags -} - -internal open class WasmPlatform(distribution: Distribution) - : PlatformFlags(distribution.targetProperties) { - - private val clang = "clang" - - override val useCompilerDriverAsLinker: Boolean get() = false - - override fun filterStaticLibraries(binaries: List) - = binaries.filter{it.isJavaScript} - - override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command { - return object: Command("") { - override fun execute() { - val src = File(objectFiles.single()) - val dst = File(executable) - src.recursiveCopyTo(dst) - javaScriptLink(args, executable) - } - - private fun javaScriptLink(jsFiles: List, executable: String): String { - val linkedJavaScript = File("$executable.js") - - val linkerHeader = "var konan = { libraries: [] };\n" - val linkerFooter = """|if (isBrowser()) { - | konan.moduleEntry([]); - |} else { - | konan.moduleEntry(arguments); - |}""".trimMargin() - - linkedJavaScript.writeBytes(linkerHeader.toByteArray()); - - jsFiles.forEach { - linkedJavaScript.appendBytes(File(it).readBytes()) - } - - linkedJavaScript.appendBytes(linkerFooter.toByteArray()); - return linkedJavaScript.name - } - } - } -} - internal class LinkStage(val context: Context) { - val config = context.config.configuration - val target = context.config.targetManager.target - - private val distribution = context.config.distribution - - private val platform = when (target) { - KonanTarget.LINUX, KonanTarget.RASPBERRYPI, - KonanTarget.LINUX_MIPS32, KonanTarget.LINUX_MIPSEL32 -> - LinuxBasedPlatform(distribution) - KonanTarget.MACBOOK, KonanTarget.IPHONE, KonanTarget.IPHONE_SIM -> - MacOSBasedPlatform(distribution) - KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64 -> - AndroidPlatform(distribution) - KonanTarget.MINGW -> - MingwPlatform(distribution) - KonanTarget.WASM32 -> - WasmPlatform(distribution) - } + private val config = context.config.configuration + private val target = context.config.targetManager.target + private val platform = context.config.platform + private val linker = platform.linker private val optimize = config.get(KonanConfigKeys.OPTIMIZATION) ?: false private val debug = config.get(KonanConfigKeys.DEBUG) ?: false @@ -341,7 +52,7 @@ internal class LinkStage(val context: Context) { private fun llvmLto(files: List): ObjectFile { val combined = temporary("combined", ".o") - val tool = distribution.llvmLto + val tool = "${platform.absoluteLlvmHome}/bin/llvm-lto" val command = mutableListOf(tool, "-o", combined) command.addNonEmpty(platform.llvmLtoFlags) when { @@ -363,12 +74,12 @@ internal class LinkStage(val context: Context) { } private fun targetTool(tool: String, vararg arg: String) { - val absoluteToolName = "${platform.targetToolchain}/bin/$tool" + val absoluteToolName = "${platform.absoluteTargetToolchain}/bin/$tool" runTool(absoluteToolName, *arg) } private fun hostLlvmTool(tool: String, args: List) { - val absoluteToolName = "${distribution.llvmBin}/$tool" + val absoluteToolName = "${platform.absoluteLlvmHome}/bin/$tool" val command = listOf(absoluteToolName) + args runTool(command) } @@ -380,7 +91,7 @@ internal class LinkStage(val context: Context) { val combinedS = temporary("combined", ".s") targetTool("llc", combinedBc, "-o", combinedS) - val s2wasmFlags = platform.s2wasmFlags.toTypedArray() + val s2wasmFlags = (platform.configurables as WasmConfigurables).s2wasmFlags.toTypedArray() val combinedWast = temporary( "combined", ".wast") targetTool("s2wasm", combinedS, "-o", combinedWast, *s2wasmFlags) @@ -392,7 +103,7 @@ internal class LinkStage(val context: Context) { } private fun asLinkerArgs(args: List): List { - if (platform.useCompilerDriverAsLinker) { + if (linker.useCompilerDriverAsLinker) { return args } @@ -440,21 +151,21 @@ internal class LinkStage(val context: Context) { } try { - platform.linkCommand(objectFiles, executable, optimize, debug, dynamic).apply { - + platform.targetLibffi + linker.linkCommand(objectFiles, executable, optimize, debug, dynamic).apply { + + linker.targetLibffi + asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) + entryPointSelector + frameworkLinkerArgs - + platform.linkCommandSuffix() - + platform.linkStaticLibraries(includedBinaries) + + linker.linkCommandSuffix() + + linker.linkStaticLibraries(includedBinaries) + libraryProvidedLinkerFlags logger = context::log }.execute() - if (debug && platform is MacOSBasedPlatform) { + if (debug && linker is MacOSBasedLinker) { val outputDsymBundle = context.config.outputFile + ".dSYM" // `outputFile` is either binary or bundle. - platform.dsymUtilCommand(executable, outputDsymBundle) + linker.dsymUtilCommand(executable, outputDsymBundle) .logWith(context::log) .execute() } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/SearchPathResolver.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/SearchPathResolver.kt index 233ec42bbdf..cac6b684b4c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/SearchPathResolver.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/SearchPathResolver.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.backend.konan.util.suffixIfNot import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.target.TargetManager +import org.jetbrains.kotlin.konan.util.visibleName interface SearchPathResolver { val searchRoots: List @@ -30,13 +31,13 @@ interface SearchPathResolver { fun defaultLinks(nostdlib: Boolean, noDefaultLibs: Boolean): List } -fun defaultResolver(repositories: List, targetManager: TargetManager): SearchPathResolver = - defaultResolver(repositories, Distribution(targetManager)) +fun defaultResolver(repositories: List, target: KonanTarget): SearchPathResolver = + defaultResolver(repositories, Distribution(target)) fun defaultResolver(repositories: List, distribution: Distribution): SearchPathResolver = KonanLibrarySearchPathResolver( repositories, - distribution.targetManager, + distribution.target, distribution.klib, distribution.localKonanDir ) @@ -133,7 +134,7 @@ fun SearchPathResolver.resolveLibrariesRecursive(libraryNames: List, class KonanLibrarySearchPathResolver( repositories: List, - val targetManager: TargetManager?, + val target: KonanTarget?, val distributionKlib: String?, val localKonanDir: String?, val skipCurrentDir: Boolean = false @@ -146,7 +147,7 @@ class KonanLibrarySearchPathResolver( get() = distributionKlib?.File()?.child("common") val distPlatformHead: File? - get() = targetManager?.let { distributionKlib?.File()?.child("platform")?.child(targetManager.targetName) } + get() = target?.let { distributionKlib?.File()?.child("platform")?.child(target.visibleName) } val currentDirHead: File? get() = if (!skipCurrentDir) File.userDir else null diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt index 7040bbd924f..3fb891906ba 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExport.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.AppleConfigurables import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.isSubpackageOf @@ -102,7 +103,8 @@ internal class ObjCExport(val context: Context) { KonanTarget.MACBOOK -> "MacOSX" else -> error(target) } - val minimumOsVersion = context.config.distribution.targetProperties.osVersionMin!! + val properties = context.config.platform.configurables as AppleConfigurables + val minimumOsVersion = properties.osVersionMin!! val contents = StringBuilder() contents.append(""" diff --git a/backend.native/konan.properties b/backend.native/konan.properties index f2adc8047a5..f52c495fd00 100644 --- a/backend.native/konan.properties +++ b/backend.native/konan.properties @@ -193,9 +193,11 @@ targetToolchain.linux-linux_mips32 = target-gcc-toolchain-2-linux-mips/x86_64-un dependencies.linux-linux_mips32 = \ clang-llvm-5.0.0-linux-x86-64 \ target-gcc-toolchain-2-linux-mips \ + target-gcc-toolchain-3-linux-x86-64 \ target-sysroot-2-mips \ libffi-3.2.1-2-linux-x86-64 \ libffi-3.2.1-2-linux-mips + quadruple.linux_mips32 = mips-unknown-linux-gnu entrySelector.linux_mips32 = --defsym main=Konan_main linkerOptimizationFlags.linux_mips32 = --gc-sections @@ -220,6 +222,7 @@ targetToolchain.linux-linux_mipsel32 = target-gcc-toolchain-2-linux-mips/x86_64- dependencies.linux-linux_mipsel32 = \ clang-llvm-5.0.0-linux-x86-64 \ target-gcc-toolchain-2-linux-mips \ + target-gcc-toolchain-3-linux-x86-64 \ target-sysroot-2-mipsel \ libffi-3.2.1-2-linux-x86-64 \ libffi-3.2.1-2-linux-mipsel diff --git a/build.gradle b/build.gradle index a798a900435..a60513d3e77 100644 --- a/build.gradle +++ b/build.gradle @@ -39,7 +39,7 @@ ext { distDir = file('dist') dependenciesDir = DependencyProcessor.defaultDependenciesRoot - clangManager = new ClangManager(konanProperties, dependenciesDir.absolutePath) + platformManager = new PlatformManager(konanProperties, dependenciesDir.absolutePath) kotlinCompilerModule="org.jetbrains.kotlin:kotlin-compiler:${kotlinCompilerVersion}" kotlinStdLibModule="org.jetbrains.kotlin:kotlin-stdlib:${kotlinStdLibVersion}" kotlinReflectModule="org.jetbrains.kotlin:kotlin-reflect:${kotlinReflectVersion}" @@ -71,7 +71,7 @@ void setupHostAndTarget() { void setupClang(Project project) { - project.convention.plugins.clangManager = project.rootProject.ext.clangManager + project.convention.plugins.platformManager = project.rootProject.ext.platformManager project.convention.plugins.execClang = new org.jetbrains.kotlin.ExecClang(project) project.plugins.withType(NativeComponentPlugin) { @@ -98,13 +98,13 @@ void setupClang(Project project) { toolChains { clang(Clang) { - hostClang.hostClangPath.each { + hostPlatform.clang.clangPaths.each { path it } eachPlatform { // TODO: will not work when cross-compiling [cCompiler, cppCompiler, linker].each { - it.withArguments { it.addAll(project.hostClangArgs) } + it.withArguments { it.addAll(project.hostPlatform.clang.clangArgs) } } } diff --git a/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/ExecClang.groovy b/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/ExecClang.groovy index b528677d40c..19ed6e047c8 100644 --- a/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/ExecClang.groovy +++ b/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/ExecClang.groovy @@ -33,7 +33,7 @@ class ExecClang { } private List konanArgs(KonanTarget target) { - return project.rootProject.targetClangArgsForKonanSources(target) + return project.rootProject.platform(target).clang.clangArgsForKonanSources } private List konanArgs(String target) { @@ -95,7 +95,7 @@ class ExecClang { throw new GradleException("unsupported clang executable: $executable") } - environment["PATH"] = project.files(project.hostClang.hostClangPath).asPath + + environment["PATH"] = project.files(project.hostPlatform.clang.clangPaths).asPath + File.pathSeparator + environment["PATH"] args defaultArgs } diff --git a/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy b/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy index fdcc04d58f2..a17dd8f191f 100644 --- a/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy +++ b/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy @@ -238,7 +238,7 @@ class NamedNativeInteropConfig implements Named { } // TODO: the interop plugin should probably be reworked to execute clang from build scripts directly - environment['PATH'] = project.files(project.hostClang.hostClangPath).asPath + + environment['PATH'] = project.files(project.hostPlatform.clang.clangPaths).asPath + File.pathSeparator + environment['PATH'] args compilerOpts.collectMany { ['-copt', it] } diff --git a/dependencies/build.gradle b/dependencies/build.gradle index 4b177f6e26b..a1c57f9b0f9 100644 --- a/dependencies/build.gradle +++ b/dependencies/build.gradle @@ -23,7 +23,7 @@ import org.jetbrains.kotlin.konan.target.* import org.jetbrains.kotlin.konan.util.DependencyProcessor import static org.jetbrains.kotlin.konan.target.KonanTarget.* import static org.jetbrains.kotlin.konan.util.VisibleNamedKt.* -import org.jetbrains.kotlin.konan.properties.KonanProperties +import org.jetbrains.kotlin.konan.properties.KonanPropertiesLoader import org.jetbrains.kotlin.konan.properties.* buildscript { @@ -210,14 +210,14 @@ class HelperNativeDep extends TgzNativeDep { enum DependencyKind { LLVM( "llvm", { it.llvmHome }, { "llvmDir" } ), - GCC_TOOLCHAIN( "gccToolchain", { it.gccToolchain }, { "gccToolchainDir" }), + GCC_TOOLCHAIN( "gccToolchain", { (it instanceof LinuxBasedConfigurables) ? it.gccToolchain : null }, { "gccToolchainDir" }), SYSROOT( "sysroot", { it.targetSysRoot } ), LIBFFI( "libffi", { it.libffiDir } ), TARGET_TOOLCHAIN("targetToolchain", { it.targetToolchain } ) DependencyKind(String name, - @ClosureParams(value = FromString.class, options = "KonanProperties") Closure dirGetter, + @ClosureParams(value = FromString.class, options = "KonanPropertiesLoader") Closure dirGetter, @ClosureParams(value = FromString.class, options = "KonanTarget") Closure propertyNameGetter = {target -> "${getVisibleName(target)}${name.capitalize()}Dir"}) { this.name = name @@ -229,7 +229,7 @@ enum DependencyKind { private Closure dirGetter // KonanProperties -> String private Closure propertyNameGetter // KonanTarget -> String - String getDirectory(KonanProperties properties) { + String getDirectory(KonanPropertiesLoader properties) { return dirGetter(properties) } @@ -241,7 +241,7 @@ enum DependencyKind { } TargetManager.enabled.each { target -> - def konanProperties = new KonanProperties(target, + def konanProperties = new KonanPropertiesLoader(target, rootProject.ext.konanProperties, rootProject.ext.dependenciesDir.canonicalPath ) diff --git a/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt b/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt index 626e18ee67b..4f5ccd8c6d7 100644 --- a/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt +++ b/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt @@ -135,7 +135,7 @@ val currentAbiVersion = 1 fun libraryInRepo(repository: File, name: String): File { val resolver = KonanLibrarySearchPathResolver( repositories = listOf(repository.absolutePath), - targetManager = null, + target = null, distributionKlib = null, localKonanDir = null, skipCurrentDir = true @@ -146,7 +146,7 @@ fun libraryInRepo(repository: File, name: String): File { fun libraryInCurrentDir(name: String): File { val resolver = KonanLibrarySearchPathResolver( repositories = emptyList(), - targetManager = null, + target = null, distributionKlib = null, localKonanDir = null ) @@ -156,7 +156,7 @@ fun libraryInCurrentDir(name: String): File { fun libraryInRepoOrCurrentDir(repository: File, name: String): File { val resolver = KonanLibrarySearchPathResolver( repositories = listOf(repository.absolutePath), - targetManager = null, + target = null, distributionKlib = null, localKonanDir = null ) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeFileType.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/NativeFileType.kt similarity index 94% rename from backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeFileType.kt rename to shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/NativeFileType.kt index 4629be89cdd..b6965fa8fbf 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/NativeFileType.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/file/NativeFileType.kt @@ -14,8 +14,7 @@ * limitations under the License. */ -package org.jetbrains.kotlin.backend.konan - +package org.jetbrains.kotlin.konan.file val String.isJavaScript get() = this.endsWith(".js") diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangArgs.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangArgs.kt index f9be86a5217..a83c6485a9e 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangArgs.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangArgs.kt @@ -16,70 +16,70 @@ package org.jetbrains.kotlin.konan.target -import org.jetbrains.kotlin.konan.properties.KonanProperties import org.jetbrains.kotlin.konan.file.File -class ClangTargetArgs(val target: KonanTarget, konanProperties: KonanProperties) { +class ClangArgs(private val configurables: Configurables) : Configurables by configurables { - val sysRoot = konanProperties.absoluteTargetSysRoot - val targetArg = konanProperties.targetArg + val targetArg = if (configurables is NonAppleConfigurables) + configurables.targetArg + else null val specificClangArgs: List get() { val result = when (target) { KonanTarget.LINUX -> - listOf("--sysroot=$sysRoot") + listOf("--sysroot=$absoluteTargetSysRoot") KonanTarget.RASPBERRYPI -> listOf("-target", targetArg!!, "-mfpu=vfp", "-mfloat-abi=hard", - "--sysroot=$sysRoot", + "--sysroot=$absoluteTargetSysRoot", // TODO: those two are hacks. - "-I$sysRoot/usr/include/c++/4.8.3", - "-I$sysRoot/usr/include/c++/4.8.3/arm-linux-gnueabihf") + "-I$absoluteTargetSysRoot/usr/include/c++/4.8.3", + "-I$absoluteTargetSysRoot/usr/include/c++/4.8.3/arm-linux-gnueabihf") KonanTarget.LINUX_MIPS32 -> listOf("-target", targetArg!!, - "--sysroot=$sysRoot", - "-I$sysRoot/usr/include/c++/4.9.4", - "-I$sysRoot/usr/include/c++/4.9.4/mips-unknown-linux-gnu") + "--sysroot=$absoluteTargetSysRoot", + "-I$absoluteTargetSysRoot/usr/include/c++/4.9.4", + "-I$absoluteTargetSysRoot/usr/include/c++/4.9.4/mips-unknown-linux-gnu") KonanTarget.LINUX_MIPSEL32 -> listOf("-target", targetArg!!, - "--sysroot=$sysRoot", - "-I$sysRoot/usr/include/c++/4.9.4", - "-I$sysRoot/usr/include/c++/4.9.4/mipsel-unknown-linux-gnu") + "--sysroot=$absoluteTargetSysRoot", + "-I$absoluteTargetSysRoot/usr/include/c++/4.9.4", + "-I$absoluteTargetSysRoot/usr/include/c++/4.9.4/mipsel-unknown-linux-gnu") KonanTarget.MINGW -> - listOf("-target", targetArg!!, "--sysroot=$sysRoot", "-Xclang", "-flto-visibility-public-std") + listOf("-target", targetArg!!, "--sysroot=$absoluteTargetSysRoot", "-Xclang", "-flto-visibility-public-std") KonanTarget.MACBOOK -> - listOf("--sysroot=$sysRoot", "-mmacosx-version-min=10.11") + listOf("--sysroot=$absoluteTargetSysRoot", "-mmacosx-version-min=10.11") KonanTarget.IPHONE -> - listOf("-stdlib=libc++", "-arch", "arm64", "-isysroot", sysRoot, "-miphoneos-version-min=8.0.0") + listOf("-stdlib=libc++", "-arch", "arm64", "-isysroot", absoluteTargetSysRoot, "-miphoneos-version-min=8.0.0") KonanTarget.IPHONE_SIM -> - listOf("-stdlib=libc++", "-isysroot", sysRoot, "-miphoneos-version-min=8.0.0") + listOf("-stdlib=libc++", "-isysroot", absoluteTargetSysRoot, "-miphoneos-version-min=8.0.0") KonanTarget.ANDROID_ARM32 -> listOf("-target", targetArg!!, - "--sysroot=$sysRoot", + "--sysroot=$absoluteTargetSysRoot", // HACKS! - "-I$sysRoot/usr/include/c++/4.9.x", - "-I$sysRoot/usr/include/c++/4.9.x/arm-linux-androideabi") + "-I$absoluteTargetSysRoot/usr/include/c++/4.9.x", + "-I$absoluteTargetSysRoot/usr/include/c++/4.9.x/arm-linux-androideabi") KonanTarget.ANDROID_ARM64 -> listOf("-target", targetArg!!, - "--sysroot=$sysRoot", + "--sysroot=$absoluteTargetSysRoot", // HACKS! - "-I$sysRoot/usr/include/c++/4.9.x", - "-I$sysRoot/usr/include/c++/4.9.x/aarch64-linux-android") + "-I$absoluteTargetSysRoot/usr/include/c++/4.9.x", + "-I$absoluteTargetSysRoot/usr/include/c++/4.9.x/aarch64-linux-android") KonanTarget.WASM32 -> listOf("-target", targetArg!!, "-O1", "-fno-rtti", "-fno-exceptions", "-D_LIBCPP_ABI_VERSION=2", "-D_LIBCPP_NO_EXCEPTIONS=1", "-nostdinc", "-Xclang", "-nobuiltininc", "-Xclang", "-nostdsysteminc", - "-Xclang", "-isystem$sysRoot/include/libcxx", "-Xclang", "-isystem$sysRoot/lib/libcxxabi/include", - "-Xclang", "-isystem$sysRoot/include/compat", "-Xclang", "-isystem$sysRoot/include/libc") + "-Xclang", "-isystem$absoluteTargetSysRoot/include/libcxx", "-Xclang", "-isystem$absoluteTargetSysRoot/lib/libcxxabi/include", + "-Xclang", "-isystem$absoluteTargetSysRoot/include/compat", "-Xclang", "-isystem$absoluteTargetSysRoot/include/libc") } return result } @@ -119,35 +119,58 @@ class ClangTargetArgs(val target: KonanTarget, konanProperties: KonanProperties) listOf("-DKONAN_WASM=1", "-DKONAN_NO_FFI=1", "-DKONAN_NO_THREADS=1", "-DKONAN_NO_EXCEPTIONS=1", "-DKONAN_INTERNAL_DLMALLOC=1", "-DKONAN_INTERNAL_SNPRINTF=1", "-DKONAN_INTERNAL_NOW=1") } -} -class ClangHostArgs(val hostProperties: KonanProperties) { + private val host = TargetManager.host - val targetToolchain get() = hostProperties.absoluteTargetToolchain - val gccToolchain get() = hostProperties.absoluteGccToolchain - val sysRoot get() = hostProperties.absoluteTargetSysRoot - val llvmDir get() = hostProperties.absoluteLlvmHome - - val binDir = when(TargetManager.host) { - KonanTarget.LINUX -> "$targetToolchain/bin" - KonanTarget.MINGW -> "$sysRoot/bin" - KonanTarget.MACBOOK -> "$targetToolchain/usr/bin" + private val binDir = when(host) { + KonanTarget.LINUX -> "$absoluteTargetToolchain/bin" + KonanTarget.MINGW -> "$absoluteTargetToolchain/bin" + KonanTarget.MACBOOK -> "$absoluteTargetToolchain/usr/bin" else -> throw TargetSupportException("Unexpected host platform") } private val extraHostClangArgs = - if (TargetManager.host == KonanTarget.LINUX) { - listOf("--gcc-toolchain=$gccToolchain") + if (configurables is LinuxBasedConfigurables) { + listOf("--gcc-toolchain=${configurables.absoluteGccToolchain}") } else { emptyList() } val commonClangArgs = listOf("-B$binDir") + extraHostClangArgs - val hostClangPath = listOf("$llvmDir/bin", binDir) + val clangPaths = listOf("$absoluteLlvmHome/bin", binDir) private val jdkHome = File.jdkHome.absoluteFile.parent - val hostCompilerArgsForJni = listOf("", TargetManager.jniHostPlatformIncludeDir).map { "-I$jdkHome/include/$it" } + val hostCompilerArgsForJni = listOf("", TargetManager.jniHostPlatformIncludeDir).map { "-I$jdkHome/include/$it" }.toTypedArray() + + val clangArgs = + (commonClangArgs + specificClangArgs).toTypedArray() + + val clangArgsForKonanSources = + clangArgs + clangArgsSpecificForKonanSources + + val targetLibclangArgs: List get() { + // libclang works not exactly the same way as the clang binary and + // (in particular) uses different default header search path. + // See e.g. http://lists.llvm.org/pipermail/cfe-dev/2013-November/033680.html + // We workaround the problem with -isystem flag below. + val llvmVersion = llvmVersion + val llvmHome = absoluteLlvmHome + val isystemArgs = listOf("-isystem", "$llvmHome/lib/clang/$llvmVersion/include") + + return isystemArgs + clangArgs.toList() + } + + val targetClangCmd + = listOf("${absoluteLlvmHome}/bin/clang") + clangArgs + + val targetClangXXCmd + = listOf("${absoluteLlvmHome}/bin/clang++") + clangArgs + + fun clangC(vararg userArgs: String) = targetClangCmd + userArgs.asList() + + fun clangCXX(vararg userArgs: String) = targetClangXXCmd + userArgs.asList() + } diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangManager.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangManager.kt deleted file mode 100644 index 98e734f3943..00000000000 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ClangManager.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed -> in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.konan.target - -import org.jetbrains.kotlin.konan.properties.* - -class ClangManager(val properties: Properties, val baseDir: String) { - private val host = TargetManager.host - private val enabledTargets = TargetManager.enabled - private val konanProperties = enabledTargets.map { - it to KonanProperties(it, properties, baseDir) - }.toMap() - - private val targetClangArgs = enabledTargets.map { - it to ClangTargetArgs(it, konanProperties[it]!!) - }.toMap() - - private val hostClang = ClangHostArgs(konanProperties[host]!!) - - // These are converted to arrays to be convenient - // in groovy plugins. - val hostClangArgs = (hostClang.commonClangArgs + targetClangArgs[host]!!.specificClangArgs).toTypedArray() - - fun targetClangArgs(target: KonanTarget) - = (hostClang.commonClangArgs + targetClangArgs[target]!!.specificClangArgs).toTypedArray() - - fun targetClangArgsForKonanSources(target: KonanTarget) = - targetClangArgs(target) + targetClangArgs[target]!!.clangArgsSpecificForKonanSources - - val hostCompilerArgsForJni = hostClang.hostCompilerArgsForJni.toTypedArray() - - fun targetLibclangArgs(target: KonanTarget): List { - // libclang works not exactly the same way as the clang binary and - // (in particular) uses different default header search path. - // See e.g. http://lists.llvm.org/pipermail/cfe-dev/2013-November/033680.html - // We workaround the problem with -isystem flag below. - val llvmVersion = properties.hostString("llvmVersion")!! - val llvmHome = konanProperties[target]!!.absoluteLlvmHome - val isystemArgs = listOf("-isystem", "$llvmHome/lib/clang/$llvmVersion/include") - - return isystemArgs + targetClangArgs(target).toList() - } - - fun targetClangCmd(target: KonanTarget) - = listOf("${hostClang.llvmDir}/bin/clang") + targetClangArgs(target) - - fun targetClangXXCmd(target: KonanTarget) - = listOf("${hostClang.llvmDir}/bin/clang++") + targetClangArgs(target) -} - -class TargetClang(private val clangManager: ClangManager, private val target: KonanTarget) { - constructor (properties: Properties, baseDir: String, target: KonanTarget) - : this (ClangManager(properties, baseDir), target) - - fun clangC(vararg userArgs: String) = clangManager.targetClangCmd(target) + userArgs.asList() - - fun clangCXX(vararg userArgs: String) = clangManager.targetClangXXCmd(target) + userArgs.asList() -} - - diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Configurables.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Configurables.kt new file mode 100644 index 00000000000..95760855789 --- /dev/null +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Configurables.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed -> in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.konan.target + +import org.jetbrains.kotlin.konan.properties.* + +interface Configurables : TargetableExternalStorage { + + val target: KonanTarget + + val llvmHome get() = hostString("llvmHome") + val llvmVersion get() = hostString("llvmVersion") + + // TODO: Delegate to a map? + val llvmLtoNooptFlags get() = targetList("llvmLtoNooptFlags") + val llvmLtoOptFlags get() = targetList("llvmLtoOptFlags") + val llvmLtoFlags get() = targetList("llvmLtoFlags") + val llvmLtoDynamicFlags get() = targetList("llvmLtoDynamicFlags") + val entrySelector get() = targetList("entrySelector") + val linkerOptimizationFlags get() = targetList("linkerOptimizationFlags") + val linkerKonanFlags get() = targetList("linkerKonanFlags") + val linkerNoDebugFlags get() = targetList("linkerNoDebugFlags") + val linkerDynamicFlags get() = targetList("linkerDynamicFlags") + val llvmDebugOptFlags get() = targetList("llvmDebugOptFlags") + val targetSysRoot get() = targetString("targetSysRoot") + val libffiDir get() = targetString("libffiDir") + + // Notice: these ones are host-target. + val targetToolchain get() = hostTargetString("targetToolchain") + + val absoluteTargetSysRoot get() = absolute(targetSysRoot) + val absoluteTargetToolchain get() = absolute(targetToolchain) + val absoluteLlvmHome get() = absolute(llvmHome) + val absoluteLibffiDir get() = absolute(libffiDir) +} + +interface NonAppleConfigurables : Configurables { + val targetArg get() = targetString("quadruple") +} + +interface AppleConfigurables : Configurables { + val arch get() = targetString("arch")!! + val osVersionMin get() = targetString("osVersionMin")!! + val osVersionMinFlagLd get() = targetString("osVersionMinFlagLd")!! +} + +interface MingwConfigurables : NonAppleConfigurables + +interface LinuxBasedConfigurables : NonAppleConfigurables { + val gccToolchain get() = hostString("gccToolchain") + val absoluteGccToolchain get() = absolute(gccToolchain) + + val libGcc get() = targetString("libGcc")!! + val dynamicLinker get() = targetString("dynamicLinker")!! + val pluginOptimizationFlags get() = targetList("pluginOptimizationFlags") + val abiSpecificLibraries get() = targetList("abiSpecificLibraries") +} + +interface LinuxConfigurables : LinuxBasedConfigurables +interface LinuxMIPSConfigurables : LinuxBasedConfigurables +interface RaspberryPiConfigurables : LinuxBasedConfigurables +interface AndroidConfigurables : NonAppleConfigurables + +interface WasmConfigurables : NonAppleConfigurables { + val s2wasmFlags get() = targetList("s2wasmFlags") +} diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ConfigurablesImpl.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ConfigurablesImpl.kt new file mode 100644 index 00000000000..fc3d7e2cf5b --- /dev/null +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ConfigurablesImpl.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed -> in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.konan.target + +import org.jetbrains.kotlin.konan.properties.* + +class LinuxConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?) + : LinuxConfigurables, KonanPropertiesLoader(target, properties, baseDir) + +class LinuxMIPSConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?) + : LinuxMIPSConfigurables, KonanPropertiesLoader(target, properties, baseDir) + +class AndroidConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?) + : AndroidConfigurables, KonanPropertiesLoader(target, properties, baseDir) + +class AppleConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?) + : AppleConfigurables, 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) + + +fun loadConfigurables(target: KonanTarget, properties: Properties, baseDir: String?) = when (target) { + KonanTarget.LINUX, KonanTarget.RASPBERRYPI -> + LinuxConfigurablesImpl(target, properties, baseDir) + KonanTarget.LINUX_MIPS32, KonanTarget.LINUX_MIPSEL32 -> + LinuxMIPSConfigurablesImpl(target, properties, baseDir) + KonanTarget.MACBOOK, KonanTarget.IPHONE, KonanTarget.IPHONE_SIM -> + AppleConfigurablesImpl(target, properties, baseDir) + KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64 -> + AndroidConfigurablesImpl(target, properties, baseDir) + KonanTarget.MINGW -> + MingwConfigurablesImpl(target, properties, baseDir) + KonanTarget.WASM32 -> + WasmConfigurablesImpl(target, properties, baseDir) + } + diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanProperties.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanProperties.kt index 455722f5a73..bbdca9e3e9d 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanProperties.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanProperties.kt @@ -16,73 +16,44 @@ package org.jetbrains.kotlin.konan.properties -import org.jetbrains.kotlin.konan.file.* -import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.Configurables import org.jetbrains.kotlin.konan.util.DependencyProcessor -class KonanProperties(val target: KonanTarget, val properties: Properties, val baseDir: String? = null) { +interface TargetableExternalStorage { + fun targetString(key: String): String? + fun targetList(key: String): List + fun hostString(key: String): String? + fun hostList(key: String): List + fun hostTargetString(key: String): String? + fun hostTargetList(key: String): List + fun absolute(value: String?): String + fun downloadDependencies() +} - fun downloadDependencies() { +open class KonanPropertiesLoader(override val target: KonanTarget, val properties: Properties, val baseDir: String? = null) : Configurables { + val dependencies get() = hostTargetList("dependencies") + + override fun downloadDependencies() { dependencyProcessor!!.run() } - fun targetString(key: String): String? + override fun targetString(key: String): String? = properties.targetString(key, target) - fun targetList(key: String): List + override fun targetList(key: String): List = properties.targetList(key, target) - fun hostString(key: String): String? + override fun hostString(key: String): String? = properties.hostString(key) - fun hostList(key: String): List + override fun hostList(key: String): List = properties.hostList(key) - fun hostTargetString(key: String): String? + override fun hostTargetString(key: String): String? = properties.hostTargetString(key, target) - fun hostTargetList(key: String): List + override fun hostTargetList(key: String): List = properties.hostTargetList(key, target) - - val llvmHome get() = hostString("llvmHome") - - // TODO: Delegate to a map? - val llvmLtoNooptFlags get() = targetList("llvmLtoNooptFlags") - val llvmLtoOptFlags get() = targetList("llvmLtoOptFlags") - val llvmLtoFlags get() = targetList("llvmLtoFlags") - val llvmLtoDynamicFlags get() = targetList("llvmLtoDynamicFlags") - val entrySelector get() = targetList("entrySelector") - val linkerOptimizationFlags get() = targetList("linkerOptimizationFlags") - val linkerKonanFlags get() = targetList("linkerKonanFlags") - val linkerNoDebugFlags get() = targetList("linkerNoDebugFlags") - val linkerDynamicFlags get() = targetList("linkerDynamicFlags") - val llvmDebugOptFlags get() = targetList("llvmDebugOptFlags") - val s2wasmFlags get() = targetList("s2wasmFlags") - - val targetSysRoot get() = targetString("targetSysRoot") - val libffiDir get() = targetString("libffiDir") - val gccToolchain get() = targetString("gccToolchain") - val targetArg get() = targetString("quadruple") - // Notice: these ones are host-target. - val targetToolchain get() = hostTargetString("targetToolchain") - val dependencies get() = hostTargetList("dependencies") - - private fun absolute(value: String?): String = + override fun absolute(value: String?): String = dependencyProcessor!!.resolveRelative(value!!).absolutePath - - val absoluteTargetSysRoot get() = absolute(targetSysRoot) - val absoluteTargetToolchain get() = absolute(targetToolchain) - val absoluteGccToolchain get() = absolute(gccToolchain) - val absoluteLlvmHome get() = absolute(llvmHome) - val absoluteLibffiDir get() = absolute(libffiDir) - - val mingwWithLlvm: String? - get() { - if (target != KonanTarget.MINGW) { - error("Only mingw target can have '.mingwWithLlvm' property") - } - // TODO: make it a property in the konan.properties. - // Use (equal) llvmHome fow now. - return targetString("llvmHome") - } - - val osVersionMin: String? get() = targetString("osVersionMin") - - private val dependencyProcessor = baseDir?.let { DependencyProcessor(java.io.File(it), this) } - + private val dependencyProcessor by lazy { + baseDir?.let { DependencyProcessor(java.io.File(it), this) } + } } + 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 new file mode 100644 index 00000000000..b467dc9ce61 --- /dev/null +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Linker.kt @@ -0,0 +1,303 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.konan.target + +import java.lang.ProcessBuilder +import java.lang.ProcessBuilder.Redirect +import org.jetbrains.kotlin.konan.exec.Command +import org.jetbrains.kotlin.konan.file.* + +typealias BitcodeFile = String +typealias ObjectFile = String +typealias ExecutableFile = String + +// Use "clang -v -save-temps" to write linkCommand() method +// for another implementation of this class. +abstract class LinkerFlags(val configurables: Configurables) + /* : Configurables by configurables */{ + + protected val llvmBin = "${configurables.absoluteLlvmHome}/bin" + protected val llvmLib = "${configurables.absoluteLlvmHome}/lib" + + private val libLTODir = when (TargetManager.host) { + KonanTarget.MACBOOK, KonanTarget.LINUX -> llvmLib + KonanTarget.MINGW -> llvmBin + else -> error("Don't know libLTO location for this platform.") + } + + val libLTO = "$libLTODir/${System.mapLibraryName("LTO")}" + + val targetLibffi = configurables.libffiDir ?.let { listOf("${configurables.absoluteLibffiDir}/lib/libffi.a") } ?: emptyList() + + open val useCompilerDriverAsLinker: Boolean get() = false // TODO: refactor. + + abstract fun linkCommand(objectFiles: List, + executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command + + open fun linkCommandSuffix(): List = emptyList() + + abstract fun filterStaticLibraries(binaries: List): List + + open fun linkStaticLibraries(binaries: List): List { + val libraries = filterStaticLibraries(binaries) + // Let's just pass them as absolute paths + return libraries + } +} + +open class AndroidLinker(targetProperties: AndroidConfigurables) + : LinkerFlags(targetProperties), AndroidConfigurables by targetProperties { + + private val prefix = "$absoluteTargetToolchain/bin/" + private val clang = "$prefix/clang" + + override val useCompilerDriverAsLinker: Boolean get() = true + + override fun filterStaticLibraries(binaries: List) + = binaries.filter { it.isUnixStaticLib } + + override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command { + // liblog.so must be linked in, as we use its functionality in runtime. + return Command(clang).apply { + + "-o" + + executable + + "-fPIC" + + "-shared" + + "-llog" + + objectFiles + if (optimize) + linkerOptimizationFlags + if (!debug) + linkerNoDebugFlags + if (dynamic) + linkerDynamicFlags + + linkerKonanFlags + } + } +} + +open class MacOSBasedLinker(targetProperties: AppleConfigurables) + : LinkerFlags(targetProperties), AppleConfigurables by targetProperties { + + private val linker = "$absoluteTargetToolchain/usr/bin/ld" + internal val dsymutil = "$absoluteLlvmHome/bin/llvm-dsymutil" + + open val osVersionMinFlags: List by lazy { + listOf( + osVersionMinFlagLd, + osVersionMin + ".0") + } + + override fun filterStaticLibraries(binaries: List) + = binaries.filter { it.isUnixStaticLib } + + override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command { + return object : Command(linker) {} .apply { + + "-demangle" + + listOf("-object_path_lto", "temporary.o", "-lto_library", libLTO) + + listOf("-dynamic", "-arch", arch) + + osVersionMinFlags + + listOf("-syslibroot", absoluteTargetSysRoot, "-o", executable) + + objectFiles + if (optimize) + linkerOptimizationFlags + if (!debug) + linkerNoDebugFlags + if (dynamic) + linkerDynamicFlags + + linkerKonanFlags + + "-lSystem" + } + } + + fun dsymUtilCommand(executable: ExecutableFile, outputDsymBundle: String) = + object : Command(dsymutilCommand(executable, outputDsymBundle)) { + override fun runProcess(): Int = + executeCommandWithFilter(command) + } + + // TODO: consider introducing a better filtering directly in Command. + private fun executeCommandWithFilter(command: List): Int { + val builder = ProcessBuilder(command) + + // Inherit main process output streams. + val isDsymUtil = (command[0] == dsymutil) + + builder.redirectOutput(Redirect.INHERIT) + builder.redirectInput(Redirect.INHERIT) + if (!isDsymUtil) + builder.redirectError(Redirect.INHERIT) + + val process = builder.start() + if (isDsymUtil) { + /** + * llvm-lto has option -alias that lets tool to know which symbol we use instead of _main, + * llvm-dsym doesn't have such a option, so we ignore annoying warning manually. + */ + val errorStream = process.errorStream + val outputStream = bufferedReader(errorStream) + while (true) { + val line = outputStream.readLine() ?: break + if (!line.contains("warning: could not find object file symbol for symbol _main")) + System.err.println(line) + } + outputStream.close() + } + val exitCode = process.waitFor() + return exitCode + } + + open fun dsymutilCommand(executable: ExecutableFile, outputDsymBundle: String): List = + listOf(dsymutil, executable, "-o", outputDsymBundle) + + open fun dsymutilDryRunVerboseCommand(executable: ExecutableFile): List = + listOf(dsymutil, "-dump-debug-map" ,executable) +} + +open class LinuxBasedLinker(targetProperties: LinuxBasedConfigurables) + : LinkerFlags(targetProperties), LinuxBasedConfigurables by targetProperties { + + override val libGcc: String = "$absoluteTargetSysRoot/${super.libGcc}" + private val linker = "$absoluteTargetToolchain/bin/ld.gold" + private val specificLibs + = abiSpecificLibraries.map { "-L${absoluteTargetSysRoot}/$it" } + + override fun filterStaticLibraries(binaries: List) + = binaries.filter { it.isUnixStaticLib } + + override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command { + val isMips = (configurables is LinuxMIPSConfigurables) + + // TODO: Can we extract more to the konan.configurables? + return Command(linker).apply { + + "--sysroot=${absoluteTargetSysRoot}" + + "-export-dynamic" + + "-z" + + "relro" + + "--build-id" + + "--eh-frame-hdr" + + "-dynamic-linker" + + dynamicLinker + + "-o" + + executable + if (!dynamic) + "$absoluteTargetSysRoot/usr/lib64/crt1.o" + + "$absoluteTargetSysRoot/usr/lib64/crti.o" + if (dynamic) + + "$libGcc/crtbeginS.o" + else + + "$libGcc/crtbegin.o" + + "-L$llvmLib" + + "-L$libGcc" + if (!isMips) + "--hash-style=gnu" // MIPS doesn't support hash-style=gnu + + specificLibs + + listOf("-L$absoluteTargetSysRoot/../lib", "-L$absoluteTargetSysRoot/lib", "-L$absoluteTargetSysRoot/usr/lib") + if (optimize) { + + "-plugin" + +"$llvmLib/LLVMgold.so" + + pluginOptimizationFlags + } + if (optimize) + linkerOptimizationFlags + if (!debug) + linkerNoDebugFlags + if (dynamic) + linkerDynamicFlags + + objectFiles + + linkerKonanFlags + + listOf("-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed", + "-lc", "-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed") + if (dynamic) + + "$libGcc/crtendS.o" + else + + "$libGcc/crtend.o" + + "$absoluteTargetSysRoot/usr/lib64/crtn.o" + } + } +} + +open class MingwLinker(targetProperties: MingwConfigurables) + : LinkerFlags(targetProperties), MingwConfigurables by targetProperties { + + private val linker = "$absoluteTargetToolchain/bin/clang++" + + override val useCompilerDriverAsLinker: Boolean get() = true + + override fun filterStaticLibraries(binaries: List) + = binaries.filter { it.isWindowsStaticLib || it.isUnixStaticLib } + + override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command { + return Command(linker).apply { + + listOf("-o", executable) + + objectFiles + if (optimize) + linkerOptimizationFlags + if (!debug) + linkerNoDebugFlags + if (dynamic) + linkerDynamicFlags + } + } + + override fun linkCommandSuffix() = linkerKonanFlags +} + +open class WasmLinker(targetProperties: WasmConfigurables) + : LinkerFlags(targetProperties), WasmConfigurables by targetProperties { + + private val clang = "clang" + + override val useCompilerDriverAsLinker: Boolean get() = false + + override fun filterStaticLibraries(binaries: List) + = binaries.filter{it.isJavaScript} + + override fun linkCommand(objectFiles: List, executable: ExecutableFile, optimize: Boolean, debug: Boolean, dynamic: Boolean): Command { + return object: Command("") { + override fun execute() { + val src = File(objectFiles.single()) + val dst = File(executable) + src.recursiveCopyTo(dst) + javaScriptLink(args, executable) + } + + private fun javaScriptLink(jsFiles: List, executable: String): String { + val linkedJavaScript = File("$executable.js") + + val linkerHeader = "var konan = { libraries: [] };\n" + val linkerFooter = """|if (isBrowser()) { + | konan.moduleEntry([]); + |} else { + | konan.moduleEntry(arguments); + |}""".trimMargin() + + linkedJavaScript.writeBytes(linkerHeader.toByteArray()); + + jsFiles.forEach { + linkedJavaScript.appendBytes(File(it).readBytes()) + } + + linkedJavaScript.appendBytes(linkerFooter.toByteArray()); + return linkedJavaScript.name + } + } + } +} + +fun linker(configurables: Configurables): LinkerFlags = + when (configurables.target) { + KonanTarget.LINUX, KonanTarget.RASPBERRYPI -> + LinuxBasedLinker(configurables as LinuxConfigurables) + KonanTarget.LINUX_MIPS32, KonanTarget.LINUX_MIPSEL32 -> + LinuxBasedLinker(configurables as LinuxMIPSConfigurables) + KonanTarget.MACBOOK, KonanTarget.IPHONE, KonanTarget.IPHONE_SIM -> + MacOSBasedLinker(configurables as AppleConfigurables) + KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64 -> + AndroidLinker(configurables as AndroidConfigurables) + KonanTarget.MINGW -> + MingwLinker(configurables as MingwConfigurables) + KonanTarget.WASM32 -> + WasmLinker(configurables as WasmConfigurables) + } + 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 new file mode 100644 index 00000000000..3e31eb6325f --- /dev/null +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Platform.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.konan.target + +import org.jetbrains.kotlin.konan.properties.* + +class Platform(val configurables: Configurables) + : Configurables by configurables { + + val clang by lazy { + ClangArgs(configurables) + } + val linker by lazy { + linker(configurables) + } +} + +class PlatformManager(properties: Properties, baseDir: String) { + private val host = TargetManager.host + private val platforms = TargetManager.enabled.map { + it to Platform(loadConfigurables(it, properties, baseDir)) + }.toMap() + + fun platform(target: KonanTarget) = platforms[target]!! + val hostPlatform = platforms[host]!! +} + diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/util/DependencyProcessor.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/util/DependencyProcessor.kt index 3f429d49894..76efb5bc3b1 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/util/DependencyProcessor.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/util/DependencyProcessor.kt @@ -17,7 +17,7 @@ package org.jetbrains.kotlin.konan.util import org.jetbrains.kotlin.konan.file.use -import org.jetbrains.kotlin.konan.properties.KonanProperties +import org.jetbrains.kotlin.konan.properties.KonanPropertiesLoader import org.jetbrains.kotlin.konan.properties.Properties import org.jetbrains.kotlin.konan.properties.propertyList import java.io.File @@ -69,11 +69,11 @@ private fun Properties.findCandidates(dependencies: List): Map): Array { val manifest = File(buildDir, "manifest.properties") val targetManager = TargetManager(target) - val resolver = defaultResolver(repos, targetManager) + val resolver = defaultResolver(repos, targetManager.target) val allLibraries = resolver.resolveLibrariesRecursive( libraries, targetManager.target, noStdLib = true, noDefaultLibs = noDefaultLibs )