From 9789420ed3cad7ce7b20fbff39c46d13b7b8836b Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Tue, 16 Jan 2018 17:43:55 +0300 Subject: [PATCH] A configurable zephyr board support. --- .../native/interop/gen/jvm/CommandLine.kt | 3 - .../native/interop/gen/jvm/ToolConfig.kt | 25 +-- .../kotlin/native/interop/gen/jvm/main.kt | 2 - backend.native/build.gradle | 7 +- .../org/jetbrains/kotlin/cli/bc/K2Native.kt | 1 - .../cli/bc/K2NativeCompilerArguments.kt | 9 +- .../kotlin/backend/konan/CAdapterGenerator.kt | 2 +- .../kotlin/backend/konan/CompilerOutput.kt | 2 +- .../kotlin/backend/konan/Distribution.kt | 49 ----- .../kotlin/backend/konan/KonanConfig.kt | 27 ++- .../backend/konan/KonanConfigurationKeys.kt | 2 - .../kotlin/backend/konan/LinkStage.kt | 34 +++- .../konan/library/SearchPathResolver.kt | 10 +- .../kotlin/backend/konan/llvm/ContextUtils.kt | 16 +- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 2 +- .../kotlin/backend/konan/llvm/LlvmUtils.kt | 6 +- .../kotlin/backend/konan/llvm/Runtime.kt | 5 - .../objcexport/ObjCExportCodeGenerator.kt | 2 +- .../backend/konan/objcexport/ObjCExport.kt | 2 +- .../kotlin/compiletest/DistProperties.kt | 4 +- build.gradle | 35 ++-- .../org/jetbrains/kotlin/ExecClang.groovy | 9 +- .../org/jetbrains/kotlin/KonanTest.groovy | 27 ++- .../kotlin/NativeInteropPlugin.groovy | 9 +- .../org/jetbrains/kotlin/KLibInstall.kt | 9 +- dependencies/build.gradle | 26 ++- .../org/jetbrains/kotlin/cli/klib/main.kt | 13 +- {backend.native => konan}/konan.properties | 15 +- konan/platforms/zephyr/stm32f4_disco | 36 ++++ platformLibs/build.gradle | 47 +++-- runtime/src/main/cpp/Math.cpp | 11 +- runtime/src/main/cpp/Porting.cpp | 90 +++++----- runtime/src/main/cpp/Porting.h | 2 +- runtime/src/main/cpp/Types.h | 4 +- runtime/src/main/cpp/dlmalloc/malloc.cpp | 2 +- samples/konan.sh | 5 +- samples/zephyr/CMakeLists.txt | 2 +- samples/zephyr/build.sh | 43 ++++- samples/zephyr/prj.conf | 3 +- samples/zephyr/src/blinky.c | 36 ++++ samples/zephyr/src/main.c | 18 ++ samples/zephyr/src/main.cpp | 13 -- samples/zephyr/src/main.kt | 23 ++- .../kotlin/konan/target/ClangArgs.kt | 32 ++-- .../kotlin/konan/target/Configurables.kt | 5 + .../kotlin/konan/target/ConfigurablesImpl.kt | 5 + .../kotlin/konan/target/Distribution.kt | 89 ++++++++++ .../kotlin/konan/target/KonanProperties.kt | 16 +- .../kotlin/konan/target/KonanTarget.kt | 168 ++++++++++-------- .../jetbrains/kotlin/konan/target/Linker.kt | 6 +- .../jetbrains/kotlin/konan/target/Platform.kt | 16 +- .../kotlin/konan/target/TargetProperties.kt | 8 +- .../gradle/plugin/KonanBuildingConfig.kt | 15 +- .../kotlin/gradle/plugin/KonanPlugin.kt | 16 +- .../gradle/plugin/tasks/KonanBaseTasks.kt | 13 +- .../plugin/tasks/KonanCompilerDownloadTask.kt | 2 +- .../plugin/tasks/KonanGenerateCMakeTask.kt | 12 +- .../gradle/plugin/tasks/KonanInteropTask.kt | 2 - .../plugin/test/CMakeSpecification.groovy | 6 +- .../gradle/plugin/test/KonanProject.groovy | 4 +- .../plugin/test/PathSpecification.groovy | 15 +- .../plugin/test/TaskSpecification.groovy | 6 +- .../kotlin/cli/utilities/InteropCompiler.kt | 14 +- 63 files changed, 665 insertions(+), 473 deletions(-) delete mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Distribution.kt rename {backend.native => konan}/konan.properties (96%) create mode 100644 konan/platforms/zephyr/stm32f4_disco create mode 100644 samples/zephyr/src/blinky.c create mode 100644 samples/zephyr/src/main.c delete mode 100644 samples/zephyr/src/main.cpp create mode 100644 shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Distribution.kt diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/CommandLine.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/CommandLine.kt index b9093702e88..faaea1e4d2b 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/CommandLine.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/CommandLine.kt @@ -51,9 +51,6 @@ class CInteropArguments : CommonInteropArguments() { @Argument(value = "-def", valueDescription = "", description = "the library definition file") var def: String? = null - @Argument(value = "-properties", valueDescription = "", description = "an alternative location of konan.properties file") - var properties: String? = null - // TODO: the short -h for -header conflicts with -h for -help. // The -header currently wins, but need to make it a little more sound. @Argument(value = "-header", shortName = "-h", valueDescription = "", description = "header file to produce kotlin bindings for") 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 39ceb4b0912..10940f2c45b 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,29 +16,20 @@ package org.jetbrains.kotlin.native.interop.tool -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.target.* import org.jetbrains.kotlin.konan.util.visibleName import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform -class ToolConfig(userProvidedTargetName: String?, userProvidedKonanProperties: String?, - runnerProvidedKonanHome: String, val flavor: KotlinPlatform) { +class ToolConfig(userProvidedTargetName: String?, flavor: KotlinPlatform) { - private val targetManager = TargetManager(userProvidedTargetName) - private val host = TargetManager.host + private val konanHome = System.getProperty("konan.home") + private val distribution = customerDistribution(konanHome) + private val platformManager = PlatformManager(distribution) + private val targetManager = platformManager.targetManager(userProvidedTargetName) + private val host = HostManager.host private val target = targetManager.target - private val konanHome = File(runnerProvidedKonanHome).absolutePath - private val konanPropertiesFile = userProvidedKonanProperties?.File() ?: File(konanHome, "konan/konan.properties") - private val properties = konanPropertiesFile.loadProperties() - - private val dependencies = DependencyProcessor.defaultDependenciesRoot - - private val platform = PlatformManager(properties, dependencies.path).platform(target) + private val platform = platformManager.platform(target) val substitutions = mapOf( "target" to target.detailedName, diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt index ccb915afd34..942eb72f6cf 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt @@ -249,8 +249,6 @@ private fun processCLib(args: Array): Array? { val tool = ToolConfig( arguments.target, - arguments.properties, - System.getProperty("konan.home"), flavor ) tool.downloadDependencies() diff --git a/backend.native/build.gradle b/backend.native/build.gradle index d24cdd01f3f..2b388e96625 100644 --- a/backend.native/build.gradle +++ b/backend.native/build.gradle @@ -168,11 +168,11 @@ task start(dependsOn: "${hostName}Start") // These files are built before the 'dist' is complete, // so we provide custom values for -// -runtime, -properties, -library and -Djava.library.path +// konan.home, --runtime, -Djava.library.path etc targetList.each { target -> def konanJvmArgs = ["-ea", - "-Dkonan.home=$distDir", + "-Dkonan.home=${rootProject.projectDir}", "-Djava.library.path=${project.buildDir}/nativelibs/$hostName", "-Dfile.encoding=UTF-8"] @@ -180,8 +180,7 @@ targetList.each { target -> if (target != "wasm32") defaultArgs += '-g' def konanArgs = [*defaultArgs, '-target', target, - '-runtime', project(':runtime').file("build/${target}/runtime.bc"), - '-properties', rootProject.konanPropertiesFile.canonicalPath, + '--runtime', project(':runtime').file("build/${target}/runtime.bc"), *project.globalBuildArgs] task("${target}Stdlib", type: JavaExec) { diff --git a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt index 4b33c7191eb..84ab3c72d73 100644 --- a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt +++ b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt @@ -124,7 +124,6 @@ class K2Native : CLICompiler() { arguments.mainPackage ?.let{ put(ENTRY, it) } arguments.manifestFile ?.let{ put(MANIFEST_FILE, it) } arguments.runtimeFile ?.let{ put(RUNTIME_FILE, it) } - arguments.propertyFile ?.let{ put(PROPERTY_FILE, it) } put(LIST_TARGETS, arguments.listTargets) put(OPTIMIZATION, arguments.optimization) diff --git a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt index acff284364f..734a90eea1a 100644 --- a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt +++ b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt @@ -78,15 +78,9 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { @Argument(value = "-produce", shortName = "-p", valueDescription = "{program|dynamic|framework|library|bitcode}", description = "Specify output file kind") var produce: String? = null - @Argument(value = "-properties", valueDescription = "", description = "Override standard 'konan.properties' location") - var propertyFile: String? = null - @Argument(value = "-repo", shortName = "-r", valueDescription = "", description = "Library search path") var repositories: Array? = null - @Argument(value = "-runtime", valueDescription = "", description = "Override standard 'runtime.bc' location") - var runtimeFile: String? = null - @Argument(value = "-target", valueDescription = "", description = "Set hardware target") var target: String? = null @@ -124,6 +118,9 @@ class K2NativeCompilerArguments : CommonCompilerArguments() { @Argument(value = "--purge_user_libs", description = "Don't link unused libraries even explicitly specified") var purgeUserLibs: Boolean = false + @Argument(value = "--runtime", valueDescription = "", description = "Override standard 'runtime.bc' location") + + var runtimeFile: String? = null @Argument(value = "--time", description = "Report execution time for compiler phases") var timePhases: Boolean = false diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt index d4283c8ef3f..25dcb454268 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt @@ -829,7 +829,7 @@ internal class CAdapterGenerator( output("RUNTIME_USED ${prefix}_ExportedSymbols* $exportedSymbol(void) { return &__konan_symbols;}") outputStreamWriter.close() - if (context.config.targetManager.target.family == Family.WINDOWS) { + if (context.config.target.family == Family.WINDOWS) { outputStreamWriter = context.config.tempFiles .cAdapterDef .printWriter() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt index 6d57d760386..12ea31b466d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CompilerOutput.kt @@ -73,7 +73,7 @@ internal fun produceOutput(context: Context) { val neededLibraries = context.llvm.librariesForLibraryManifest val abiVersion = context.config.currentAbiVersion - val target = context.config.targetManager.target + val target = context.config.target val nopack = config.getBoolean(KonanConfigKeys.NOPACK) val manifest = config.get(KonanConfigKeys.MANIFEST_FILE) 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 deleted file mode 100644 index f2c99fa11d2..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Distribution.kt +++ /dev/null @@ -1,49 +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 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.backend.konan - -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 target: KonanTarget, - propertyFileOverride: String? = null, - runtimeFileOverride: String? = null) { - - val localKonanDir = "${File.userHome}/.konan" - - private fun findKonanHome(): String { - val value = System.getProperty("konan.home", "dist") - val path = File(value).absolutePath - return path - } - - val konanHome = findKonanHome() - val propertyFileName = propertyFileOverride ?: "$konanHome/konan/konan.properties" - val properties = File(propertyFileName).loadProperties() - - 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 -} 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 f35257a729f..69ea5e3cad5 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 @@ -39,30 +39,29 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration val currentAbiVersion: Int = configuration.get(KonanConfigKeys.ABI_VERSION)!! - internal val targetManager = TargetManager( - configuration.get(KonanConfigKeys.TARGET)) + internal val distribution = Distribution( + false, + null, + configuration.get(KonanConfigKeys.RUNTIME_FILE)) - private val target = targetManager.target + internal val platformManager = PlatformManager(distribution) + internal val targetManager = platformManager.targetManager(configuration.get(KonanConfigKeys.TARGET)) + internal val target = targetManager.target init { - if (!target.enabled) { - error("Target $target is not available on the ${TargetManager.host} host") + if (!platformManager.isEnabled(target)) { + error("Target $target is not available on the ${HostManager.host} host") } } - val indirectBranchesAreAllowed = target != KonanTarget.WASM32 - - 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 { + val platform = platformManager.platform(target).apply { if (configuration.getBoolean(KonanConfigKeys.CHECK_DEPENDENCIES)) { downloadDependencies() } } internal val clang = platform.clang + val indirectBranchesAreAllowed = target != KonanTarget.WASM32 internal val produce get() = configuration.get(KonanConfigKeys.PRODUCE)!! private val prefix = produce.prefix(target) @@ -84,7 +83,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration get() = configuration.getList(KonanConfigKeys.LIBRARY_FILES) private val repositories = configuration.getList(KonanConfigKeys.REPOSITORIES) - private val resolver = defaultResolver(repositories, distribution) + private val resolver = defaultResolver(repositories, target, distribution) internal val immediateLibraries: List by lazy { val result = resolver.resolveImmediateLibraries( @@ -109,7 +108,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration internal val defaultNativeLibraries = if (produce == CompilerOutputKind.PROGRAM) - File(distribution.defaultNatives).listFiles.map { it.absolutePath } + File(distribution.defaultNatives(target)).listFiles.map { it.absolutePath } else emptyList() internal val nativeLibraries: List = diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt index 625b590523f..04378e2ae92 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt @@ -83,8 +83,6 @@ class KonanConfigKeys { = CompilerConfigurationKey.create("print locations") val PRODUCE: CompilerConfigurationKey = CompilerConfigurationKey.create("compiler output kind") - val PROPERTY_FILE: CompilerConfigurationKey - = CompilerConfigurationKey.create("override default property file path") val PURGE_USER_LIBS: CompilerConfigurationKey = CompilerConfigurationKey.create("purge user-specified libs too") val REPOSITORIES: CompilerConfigurationKey> 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 fbcbcfb1474..63649fbdf91 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 @@ -18,7 +18,8 @@ package org.jetbrains.kotlin.backend.konan import org.jetbrains.kotlin.konan.KonanExternalToolFailure import org.jetbrains.kotlin.konan.exec.Command -import org.jetbrains.kotlin.konan.file.* +import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.file.createTempFile import org.jetbrains.kotlin.konan.target.* typealias BitcodeFile = String @@ -28,7 +29,7 @@ typealias ExecutableFile = String internal class LinkStage(val context: Context) { private val config = context.config.configuration - private val target = context.config.targetManager.target + private val target = context.config.target private val platform = context.config.platform private val linker = platform.linker @@ -117,6 +118,19 @@ internal class LinkStage(val context: Context) { return combinedWasm } + private fun llvmLinkAndLlc(bitcodeFiles: List): String { + val combinedBc = temporary("combined", ".bc") + hostLlvmTool("llvm-link", "-o", combinedBc, *bitcodeFiles.toTypedArray()) + + val optimizedBc = temporary("optimized", ".bc") + hostLlvmTool("opt", combinedBc, "-o=$optimizedBc", "-O3") + + val combinedO = temporary("combined", ".o") + hostLlvmTool("llc", combinedBc, "-filetype=obj", "-o", combinedO, "-function-sections", "-data-sections") + + return combinedO + } + private fun asLinkerArgs(args: List): List { if (linker.useCompilerDriverAsLinker) { return args @@ -201,15 +215,19 @@ internal class LinkStage(val context: Context) { val libraryProvidedLinkerFlags = libraries.map{it -> it.linkerOpts}.flatten() - var objectFiles: List = listOf() + val objectFiles: MutableList = mutableListOf() val phaser = PhaseManager(context) phaser.phase(KonanPhase.OBJECT_FILES) { - objectFiles = listOf( - if (target == KonanTarget.WASM32) - bitcodeToWasm(bitcodeFiles) - else - llvmLto(bitcodeFiles) + objectFiles.add( + when (platform.configurables) { + is WasmConfigurables + -> bitcodeToWasm(bitcodeFiles) + is ZephyrConfigurables + -> llvmLinkAndLlc(bitcodeFiles) + else + -> llvmLto(bitcodeFiles) + } ) } phaser.phase(KonanPhase.LINKER) { 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 cac6b684b4c..a923ffc990c 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 @@ -16,14 +16,12 @@ package org.jetbrains.kotlin.backend.konan.library -import org.jetbrains.kotlin.backend.konan.Distribution import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl import org.jetbrains.kotlin.backend.konan.util.removeSuffixIfPresent import org.jetbrains.kotlin.backend.konan.util.suffixIfNot import org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.target.Distribution 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 @@ -32,12 +30,12 @@ interface SearchPathResolver { } fun defaultResolver(repositories: List, target: KonanTarget): SearchPathResolver = - defaultResolver(repositories, Distribution(target)) + defaultResolver(repositories, target, Distribution()) -fun defaultResolver(repositories: List, distribution: Distribution): SearchPathResolver = +fun defaultResolver(repositories: List, target: KonanTarget, distribution: Distribution): SearchPathResolver = KonanLibrarySearchPathResolver( repositories, - distribution.target, + target, distribution.klib, distribution.localKonanDir ) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index 03add130348..77482f57e10 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -362,7 +362,9 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { val staticData = StaticData(context) - val runtimeFile = context.config.distribution.runtime + private val target = context.config.target + + val runtimeFile = context.config.distribution.runtime(target) val runtime = Runtime(runtimeFile) // TODO: dispose init { @@ -416,7 +418,17 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { null } - private val personalityFunctionName = when (context.config.targetManager.target) { + val tlsMode by lazy { + when (target) { + KonanTarget.WASM32, + is KonanTarget.ZEPHYR + -> LLVMThreadLocalMode.LLVMNotThreadLocal + else + -> LLVMThreadLocalMode.LLVMGeneralDynamicTLSModel + } + } + + private val personalityFunctionName = when (target) { KonanTarget.MINGW -> "__gxx_personality_seh0" else -> "__gxx_personality_v0" } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index ae39ccd87fb..884608eb565 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -2228,7 +2228,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map isLU // x86_64 KonanTarget.IPHONE -> false // aarch64 else -> TODO() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt index 44ed646cb20..05ba3b08667 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/LlvmUtils.kt @@ -205,7 +205,7 @@ internal fun ContextUtils.addGlobal(name: String, type: LLVMTypeRef, isExported: assert(LLVMGetNamedGlobal(context.llvmModule, name) == null) val result = LLVMAddGlobal(context.llvmModule, type, name)!! if (threadLocal) - LLVMSetThreadLocalMode(result, runtime.tlsMode) + LLVMSetThreadLocalMode(result, context.llvm.tlsMode) return result } @@ -219,12 +219,12 @@ internal fun ContextUtils.importGlobal(name: String, type: LLVMTypeRef, origin: assert (getGlobalType(found) == type) assert (LLVMGetInitializer(found) == null) if (threadLocal) - assert(LLVMGetThreadLocalMode(found) == runtime.tlsMode) + assert(LLVMGetThreadLocalMode(found) == context.llvm.tlsMode) return found } else { val result = LLVMAddGlobal(context.llvmModule, type, name)!! if (threadLocal) - LLVMSetThreadLocalMode(result, runtime.tlsMode) + LLVMSetThreadLocalMode(result, context.llvm.tlsMode) return result } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt index 158ce66c4ea..16be5b2863e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Runtime.kt @@ -46,11 +46,6 @@ class Runtime(bitcodeFile: String) { val target = LLVMGetTarget(llvmModule)!!.toKString() - // TODO: deduce TLS model from explicit config parameter. - val tlsMode by lazy { - if (target.indexOf("wasm") != -1) LLVMThreadLocalMode.LLVMNotThreadLocal - else LLVMThreadLocalMode.LLVMGeneralDynamicTLSModel - } val dataLayout = LLVMGetDataLayout(llvmModule)!!.toKString() val targetData = LLVMCreateTargetData(dataLayout)!! diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt index 27f95e9696d..4fa16a39776 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -1007,4 +1007,4 @@ private val ReturnableTypeBridge.objCEncoding: String get() = when (this) { HashCodeBridge -> "L" // NSUInteger = unsigned long; // TODO: `unsigned int` on watchOS } -internal fun Context.is64Bit(): Boolean = this.config.targetManager.target.architecture.bitness == 64 +internal fun Context.is64Bit(): Boolean = this.config.target.architecture.bitness == 64 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 3fb891906ba..de2c950de42 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 @@ -31,7 +31,7 @@ import org.jetbrains.kotlin.name.isSubpackageOf internal class ObjCExport(val context: Context) { - private val target get() = context.config.targetManager.target + private val target get() = context.config.target internal fun produceObjCFramework() { if (context.config.produce != CompilerOutputKind.FRAMEWORK) return diff --git a/backend.native/debugger-tests/src/main/kotlin/org/jetbrains/kotlin/compiletest/DistProperties.kt b/backend.native/debugger-tests/src/main/kotlin/org/jetbrains/kotlin/compiletest/DistProperties.kt index 647fdb4d5bc..ccceae8033a 100644 --- a/backend.native/debugger-tests/src/main/kotlin/org/jetbrains/kotlin/compiletest/DistProperties.kt +++ b/backend.native/debugger-tests/src/main/kotlin/org/jetbrains/kotlin/compiletest/DistProperties.kt @@ -1,14 +1,14 @@ package org.jetbrains.kotlin.compiletest import org.jetbrains.kotlin.konan.target.Family -import org.jetbrains.kotlin.konan.target.TargetManager +import org.jetbrains.kotlin.konan.target.HostManager import java.nio.file.Path import java.nio.file.Paths object DistProperties { private val dist: Path = Paths.get(requireProp("konan.home")) - private val konancDriver = if (TargetManager.host.family == Family.WINDOWS) "konanc.bat" else "konanc" + private val konancDriver = if (HostManager.host.family == Family.WINDOWS) "konanc.bat" else "konanc" val konanc: Path = dist.resolve("bin/$konancDriver") val lldb: Path = Paths.get("lldb") val lldbPrettyPrinters: Path = dist.resolve("tools/konan_lldb.py") diff --git a/build.gradle b/build.gradle index 30ee99e30d8..a7ac8a59078 100644 --- a/build.gradle +++ b/build.gradle @@ -23,24 +23,10 @@ defaultTasks 'clean', 'dist' convention.plugins.platformInfo = new PlatformInfo() ext { - konanPropertiesFile = project(':backend.native').file('konan.properties') - konanProperties = PropertiesKt.loadProperties(konanPropertiesFile.absolutePath) - - String DEPENDENCY_PROFILES_KEY = "dependencyProfiles" - def dependencyProfiles = konanProperties.getProperty(DEPENDENCY_PROFILES_KEY) - if (dependencyProfiles != "default alt") - throw new Error("unexpected $DEPENDENCY_PROFILES_KEY value: expected 'default alt', got '$dependencyProfiles'") - - // Force build to use only 'default' profile: - konanProperties.setProperty(DEPENDENCY_PROFILES_KEY, "default") - // Force build to use fixed Xcode version: - konanProperties.setProperty("useFixedXcodeVersion", "9.2") - // TODO: it actually affects only resolution made in :dependencies, - // that's why we assume that 'default' profile comes first (and check this above). - distDir = file('dist') dependenciesDir = DependencyProcessor.defaultDependenciesRoot - platformManager = new PlatformManager(konanProperties, dependenciesDir.absolutePath) + platformManager = new PlatformManager(DistributionKt.buildDistribution(projectDir.absolutePath)) + kotlinCompilerModule="org.jetbrains.kotlin:kotlin-compiler:${kotlinCompilerVersion}" kotlinStdLibModule="org.jetbrains.kotlin:kotlin-stdlib:${kotlinStdLibVersion}" kotlinReflectModule="org.jetbrains.kotlin:kotlin-reflect:${kotlinReflectVersion}" @@ -66,8 +52,9 @@ allprojects { } void setupHostAndTarget() { - ext.hostName = TargetManager.hostName - ext.targetList = TargetManager.enabled.collect { it.visibleName } as List + ext.hostName = platformManager.hostName + ext.targetList = platformManager.enabled.collect { it.visibleName } as List + ext.konanTargetList = platformManager.enabled as List } void setupClang(Project project) { @@ -135,15 +122,15 @@ void loadCommandLineProperties() { class PlatformInfo { boolean isMac() { - return TargetManager.hostIsMac + return HostManager.hostIsMac } boolean isWindows() { - return TargetManager.hostIsMingw + return HostManager.hostIsMingw } boolean isLinux() { - return TargetManager.hostIsLinux + return HostManager.hostIsLinux } Throwable unsupportedPlatformException() { @@ -243,7 +230,7 @@ task distCompiler(type: Copy) { exclude('**/*.bat') } } - from(konanPropertiesFile) { + from(project.file('konan')) { into('konan') } } @@ -345,7 +332,7 @@ dependencies { task bundle(type: (isWindows()) ? Zip : Tar) { dependsOn('crossDistPlatformLibs') dependsOn('crossDist') - def simpleOsName = TargetManager.simpleOsName() + def simpleOsName = HostManager.simpleOsName() baseName = "kotlin-native-$simpleOsName-${project.konanVersion}" from("$project.rootDir/dist") { include '**' @@ -399,7 +386,7 @@ task uploadBundle { server: project.findProperty("cdnUrl") ?: System.getenv("CDN_URL"), userid: project.findProperty("cdnUser") ?: System.getenv("CDN_USER"), password: project.findProperty("cdnPass") ?: System.getenv("CDN_PASS"), - remoteDir: "/builds/$kind/$konanVersion/${TargetManager.simpleOsName()}" + remoteDir: "/builds/$kind/$konanVersion/${HostManager.simpleOsName()}" ] ant { taskdef(name: 'ftp', 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 19ed6e047c8..bcb334f4bbc 100644 --- a/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/ExecClang.groovy +++ b/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/ExecClang.groovy @@ -32,12 +32,15 @@ class ExecClang { this.project = project } + private def platformManager = project.rootProject.platformManager + private List konanArgs(KonanTarget target) { - return project.rootProject.platform(target).clang.clangArgsForKonanSources + return platformManager.platform(target).clang.clangArgsForKonanSources } - private List konanArgs(String target) { - return konanArgs(new TargetManager(target).target) + private List konanArgs(String targetName) { + def target = platformManager.targetManager(targetName).target + return konanArgs(target) } // The bare ones invoke clang with system default sysroot. diff --git a/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/KonanTest.groovy b/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/KonanTest.groovy index c63abc6a7bb..2e47ed27250 100644 --- a/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/KonanTest.groovy +++ b/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/KonanTest.groovy @@ -30,15 +30,12 @@ abstract class KonanTest extends JavaExec { public boolean inDevelopersRun = false public String source - def targetManager = new TargetManager(project.testTarget) - def target = targetManager.target - def backendNative = project.project(":backend.native") - def runtimeProject = project.project(":runtime") + def platformManager = project.rootProject.platformManager + def target = platformManager.targetManager(project.testTarget).target def dist = project.rootProject.file(project.findProperty("konan.home") ?: "dist") def dependenciesDir = project.rootProject.dependenciesDir def konancDriver = project.isWindows() ? "konanc.bat" : "konanc" def konanc = new File("${dist.canonicalPath}/bin/$konancDriver").absolutePath - def mainC = 'main.c' def outputSourceSetName = "testOutputLocal" def enableKonanAssertions = true String outputDirectory = null @@ -227,7 +224,7 @@ fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation = ob createOutputDirectory() def program = buildExePath() - def suffix = targetManager.target.family.exeSuffix + def suffix = target.family.exeSuffix def exe = "$program.$suffix" compileTest(buildCompileList(), program) @@ -282,19 +279,17 @@ fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation = ob } List executionCommandLine(String exe) { - def properties = project.rootProject.konanProperties - def targetToolchain = TargetPropertiesKt.hostTargetString(properties, "targetToolchain", target) - def absoluteTargetToolchain = "$dependenciesDir/$targetToolchain" - if (target == KonanTarget.WASM32) { + + def absoluteTargetToolchain = platformManager.platform(target).absoluteTargetToolchain + def absoluteTargetSysRoot = platformManager.platform(target).absoluteTargetSysRoot + if (target instanceof KonanTarget.WASM32) { def d8 = "$absoluteTargetToolchain/bin/d8" def launcherJs = "${exe}.js" return [d8, '--expose-wasm', launcherJs, '--', exe] - } else if (target == KonanTarget.LINUX_MIPS32 || target == KonanTarget.LINUX_MIPSEL32) { - def targetSysroot = TargetPropertiesKt.targetString(properties, "targetSysRoot", target) - def absoluteTargetSysroot = "$dependenciesDir/$targetSysroot" - def qemu = target == KonanTarget.LINUX_MIPS32 ? "qemu-mips" : "qemu-mipsel" + } else if (target instanceof KonanTarget.LINUX_MIPS32 || target instanceof KonanTarget.LINUX_MIPSEL32) { + def qemu = target instanceof KonanTarget.LINUX_MIPS32 ? "qemu-mips" : "qemu-mipsel" def absoluteQemu = "$absoluteTargetToolchain/bin/$qemu" - return [absoluteQemu, "-L", absoluteTargetSysroot, exe] + return [absoluteQemu, "-L", absoluteTargetSysRoot, exe] } else { return [exe] } @@ -548,7 +543,7 @@ class DynamicKonanTest extends KonanTest { void compileTest(List filesToCompile, String exe) { def libname = "testlib" def dylib = "$outputDirectory/$libname" - def realExe = "${exe}.${targetManager.target.family.exeSuffix}" + def realExe = "${exe}.${target.family.exeSuffix}" runCompiler(filesToCompile, dylib, ['-produce', 'dynamic'] + ((flags != null) ? flags :[])) runClang([cSource], realExe, ['-I', outputDirectory, '-L', outputDirectory, '-l', libname]) 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 a1acf8657c0..5007519942d 100644 --- a/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy +++ b/buildSrc/plugins/src/main/groovy/org/jetbrains/kotlin/NativeInteropPlugin.groovy @@ -147,7 +147,6 @@ class NamedNativeInteropConfig implements Named { } File getNativeLibsDir() { - def target = new TargetManager(target).target.visibleName return new File(project.buildDir, "nativelibs/$target") } @@ -158,9 +157,12 @@ class NamedNativeInteropConfig implements Named { NamedNativeInteropConfig(Project project, String name, String target = null, String flavor = 'jvm') { this.name = name this.project = project - this.target = target this.flavor = flavor + def platformManager = project.rootProject.ext.platformManager + def targetManager = platformManager.targetManager(target) + this.target = targetManager.targetName + this.headers = [] this.linkFiles = project.files() @@ -197,7 +199,7 @@ class NamedNativeInteropConfig implements Named { new File(project.findProject(":Interop:Indexer").buildDir, "nativelibs"), new File(project.findProject(":Interop:Runtime").buildDir, "nativelibs") ).asPath - systemProperties "konan.home": project.rootProject.file("dist") + systemProperties "konan.home": project.rootProject.projectDir environment "LIBCLANG_DISABLE_CRASH_RECOVERY": "1" outputs.dir generatedSrcDir @@ -213,7 +215,6 @@ class NamedNativeInteropConfig implements Named { linkerOpts += linkFiles.files - args '-properties', project.findProject(":backend.native").file("konan.properties") args '-generated', generatedSrcDir args '-natives', nativeLibsDir args '-flavor', this.flavor diff --git a/buildSrc/plugins/src/main/kotlin/org/jetbrains/kotlin/KLibInstall.kt b/buildSrc/plugins/src/main/kotlin/org/jetbrains/kotlin/KLibInstall.kt index fd43cf42b3f..0552aabb6a5 100644 --- a/buildSrc/plugins/src/main/kotlin/org/jetbrains/kotlin/KLibInstall.kt +++ b/buildSrc/plugins/src/main/kotlin/org/jetbrains/kotlin/KLibInstall.kt @@ -7,7 +7,7 @@ import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.OutputDirectory import org.jetbrains.kotlin.konan.target.KonanTarget -import org.jetbrains.kotlin.konan.target.TargetManager +import org.jetbrains.kotlin.konan.target.HostManager import java.io.File // TODO: Implement as a part of the gradle plugin @@ -24,12 +24,13 @@ open class KlibInstall: Exec() { } @Input - var target: String = TargetManager.hostName + var target: String = HostManager.hostName override fun configure(config: Closure<*>): Task { val result = super.configure(config) - val konanHome = project.rootProject.file(project.findProperty("konan.home") ?: "dist") - val suffix = if (TargetManager.host == KonanTarget.MINGW) ".bat" else "" + val konanHomePath = project.findProperty("konan.home") ?: "dist" + val konanHome = project.rootProject.file(konanHomePath) + val suffix = if (HostManager.host == KonanTarget.MINGW) ".bat" else "" val klibProgram = "$konanHome/bin/klib$suffix" doFirst { diff --git a/dependencies/build.gradle b/dependencies/build.gradle index 4b1be8b08cf..e9b9aa5190d 100644 --- a/dependencies/build.gradle +++ b/dependencies/build.gradle @@ -139,8 +139,7 @@ task update_kotlin_compiler(type: DefaultTask) { } abstract class NativeDep extends DefaultTask { - protected final String hostSystem = TargetManager.longerSystemName(); - static final String baseUrl = "https://jetbrains.bintray.com/kotlin-native-dependencies" + static final String baseUrl = "https://download.jetbrains.com/kotlin/native" @Input abstract String getFileName() @@ -198,11 +197,11 @@ class TgzNativeDep extends NativeDep { class HelperNativeDep extends TgzNativeDep { - Properties konanProperties = new Properties() + KonanPropertiesLoader konanPropertiesLoader = null @TaskAction public void downloadAndExtract() { - def downloader = new DependencyProcessor(baseOutDir, konanProperties, [baseName], baseUrl, false) + def downloader = new DependencyProcessor(baseOutDir, konanPropertiesLoader, baseUrl, false) downloader.showInfo = false downloader.run() } @@ -237,18 +236,15 @@ enum DependencyKind { String toString() { return name } } -TargetManager.enabled.each { target -> - def konanProperties = ConfigurablesImplKt.loadConfigurables( - target, - rootProject.ext.konanProperties, - rootProject.ext.dependenciesDir.canonicalPath - ) +def platformManager = rootProject.ext.platformManager - konanProperties.dependencies.each { dependency -> +platformManager.enabled.each { target -> + def loader = platformManager.loader(target) + loader.dependencies.each { dependency -> if (tasks.findByName(dependency) == null) { task "${dependency}"(type: HelperNativeDep) { baseName = dependency - it.konanProperties = rootProject.ext.konanProperties + it.konanPropertiesLoader = loader } } } @@ -256,14 +252,14 @@ TargetManager.enabled.each { target -> // Also resolves all dependencies: final DependencyProcessor dependencyProcessor = new DependencyProcessor( project.rootProject.ext.dependenciesDir, - rootProject.ext.konanProperties, - konanProperties.dependencies, + loader.properties, + loader.dependencies, HelperNativeDep.baseUrl, false ) DependencyKind.values().each { kind -> - def dir = kind.getDirectory(konanProperties) + def dir = kind.getDirectory(loader) if (dir != null) { String path = dependencyProcessor.resolveRelative(dir).canonicalPath rootProject.ext.set(kind.getPropertyName(target), path) 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 4f5ccd8c6d7..07e1ab052d0 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 @@ -16,12 +16,15 @@ package org.jetbrains.kotlin.cli.klib -import kotlin.system.exitProcess -// TODO: Extract these as a shared jar? -import org.jetbrains.kotlin.backend.konan.library.impl.* +// TODO: Extract `library` package as a shared jar? import org.jetbrains.kotlin.backend.konan.library.KonanLibrarySearchPathResolver +import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl +import org.jetbrains.kotlin.backend.konan.library.impl.UnzippedKonanLibrary +import org.jetbrains.kotlin.backend.konan.library.impl.ZippedKonanLibrary import org.jetbrains.kotlin.konan.file.File -import org.jetbrains.kotlin.konan.target.TargetManager +import org.jetbrains.kotlin.konan.target.PlatformManager +import org.jetbrains.kotlin.konan.target.customerDistribution +import kotlin.system.exitProcess fun printUsage() { println("Usage: klib ") @@ -167,7 +170,7 @@ fun libraryInRepoOrCurrentDir(repository: File, name: String): File { fun main(args: Array) { val command = Command(args) - val targetManager = TargetManager(command.options["-target"]?.last()) + val targetManager = PlatformManager().targetManager(command.options["-target"]?.last()) val target = targetManager.targetName val repository = command.options["-repository"]?.last() diff --git a/backend.native/konan.properties b/konan/konan.properties similarity index 96% rename from backend.native/konan.properties rename to konan/konan.properties index 02b285684ae..5e2fff6e7c0 100644 --- a/backend.native/konan.properties +++ b/konan/konan.properties @@ -330,17 +330,4 @@ llcNooptFlags.wasm32 = -O1 llcOptFlags.wasm32 = -O3 llcDebugFlags.wasm32 = -O0 # The stack size is in bytes. -s2wasmFlags.wasm32 = --allocate-stack 1048576 --import-memory - -# Zephyr RTOS. -targetToolchain.linux-zephyr = target-gcc-toolchain-6-2017q2-linux-armemb/arm-none-eabi -dependencies.linux-zephyr = \ - clang-llvm-5.0.0-linux-x86-64 \ - target-gcc-toolchain-6-2017q2-linux-armemb \ - target-sysroot-2-wasm \ - zephyr-host-tools-1-linux \ - zephyr-zephyr-v1.10.0 - -quadruple.zephyr = armv7m-none-eabi -targetSysRoot.zephyr = target-sysroot-2-wasm -entrySelector.zephyr = --defsym main=Konan_main +s2wasmFlags.wasm32 = --allocate-stack 1048576 --import-memory \ No newline at end of file diff --git a/konan/platforms/zephyr/stm32f4_disco b/konan/platforms/zephyr/stm32f4_disco new file mode 100644 index 00000000000..45e30ddb1cd --- /dev/null +++ b/konan/platforms/zephyr/stm32f4_disco @@ -0,0 +1,36 @@ +# +# 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. +# + +# Zephyr RTOS. +# STM32 F4 Discovery + +quadruple.zephyr_stm32f4_disco = armv7m-none-eabi +targetSysRoot.zephyr_stm32f4_disco = target-sysroot-2-wasm +entrySelector.zephyr_stm32f4_disco = --defsym main=Konan_main + +boardSpecificClangFlags.zephyr_stm32f4_disco = -mabi=aapcs -mthumb -mcpu=cortex-m4 + +targetToolchain.linux-zephyr_stm32f4_disco = gcc-arm-none-eabi-7-2017-q4-major-linux/arm-none-eabi +dependencies.linux-zephyr_stm32f4_disco = \ + clang-llvm-5.0.0-linux-x86-64 \ + gcc-arm-none-eabi-7-2017-q4-major-linux \ + target-sysroot-2-wasm + +targetToolchain.osx-zephyr_stm32f4_disco = gcc-arm-none-eabi-7-2017-q4-major-mac/arm-none-eabi +dependencies.osx-zephyr_stm32f4_disco = \ + gcc-arm-none-eabi-7-2017-q4-major-mac \ + clang-llvm-5.0.0-darwin-macos \ + target-sysroot-2-wasm diff --git a/platformLibs/build.gradle b/platformLibs/build.gradle index e4a212363ab..63c2c416513 100644 --- a/platformLibs/build.gradle +++ b/platformLibs/build.gradle @@ -1,5 +1,7 @@ import org.jetbrains.kotlin.KlibInstall -import org.jetbrains.kotlin.konan.target.TargetManager +import org.jetbrains.kotlin.konan.target.* +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.KonanTarget.* import org.jetbrains.kotlin.konan.util.DefFile import static org.jetbrains.kotlin.konan.util.VisibleNamedKt.getVisibleName @@ -25,41 +27,36 @@ buildscript { } //#region Util functions. -private ArrayList targetDefFiles(String target) { - def platform = targetToPlatform(target) - def substitution = ['arch': target, - 'os' : targetToOs(target)] - file("src/platform/$platform") +private ArrayList targetDefFiles(KonanTarget target) { + def substitution = ['arch': target.visibleName, + 'os' : target.detailedName] + file("src/platform/${getVisibleName(target.family)}") .listFiles() .findAll { it.name.endsWith(".def") } // The libz.a/libz.so and zlib.h are missing in raspberrypi and mips sysroots. // Just workaround it until we have sysroots corrected. - .findAll { ! ((target == 'raspberrypi' || target == 'linux_mips32' || target == 'linux_mipsel32') && it.name == 'zlib.def') } + .findAll { ! ((target instanceof KonanTarget.RASPBERRYPI || + target instanceof KonanTarget.LINUX_MIPS32 || + target instanceof KonanTarget.LINUX_MIPSEL32) && it.name == 'zlib.def') } .collect { new DefFile(it, substitution) } } -private String targetToPlatform(String target) { - getVisibleName(new TargetManager(target).target.family) -} - -private String targetToOs(String target) { - new TargetManager(target).target.detailedName -} - private String defFileToLibName(String target, String name) { return "$target-$name".toString() } //#endregion -targetList.each { target -> +project.rootProject.ext.platformManager.enabled.each { target -> + + def targetName = target.visibleName ArrayList installTasks = [] targetDefFiles(target).each { df -> - def libName = defFileToLibName(target, df.name) + def libName = defFileToLibName(targetName, df.name) konanArtifacts { - interop (libName, targets: [target]) { + interop (libName, targets: [targetName]) { defFile df.file artifactName df.name noDefaultLibs true @@ -70,21 +67,21 @@ targetList.each { target -> } } - def libTask = konanArtifacts."$libName"."$target" - libTask.dependsOn df.config.depends.collect{ defFileToLibName(target, it) } - libTask.dependsOn ":${target}CrossDist" + def libTask = konanArtifacts."$libName"."$targetName" + libTask.dependsOn df.config.depends.collect{ defFileToLibName(targetName, it) } + libTask.dependsOn ":${targetName}CrossDist" task "$libName"(type: KlibInstall) { klib = libTask.artifact - repo = file("$konanHome/klib/platform/$target") - it.target = target + repo = file("$konanHome/klib/platform/$targetName") + it.target = targetName dependsOn libTask } installTasks.add(tasks[libName]) } - task "${target}Install" { + task "${targetName}Install" { dependsOn installTasks } } @@ -92,7 +89,7 @@ targetList.each { target -> // TODO: Don't install libraries here - copy them in the distPlatformLibs task task hostInstall { dependsOn tasks.withType(KlibInstall.class).findAll { - new TargetManager(it.target).target == TargetManager.host + it.target == HostManager.hostName } } diff --git a/runtime/src/main/cpp/Math.cpp b/runtime/src/main/cpp/Math.cpp index 4fd0c2aed21..91ddeebef5a 100644 --- a/runtime/src/main/cpp/Math.cpp +++ b/runtime/src/main/cpp/Math.cpp @@ -27,13 +27,6 @@ #define KONAN_NEED_ASINH_ACOSH 0 #endif -#if KONAN_WASM || __ZEPHYR__ -#define KONAN_NO_MATH 1 -#else -#define KONAN_NO_MATH 0 -#endif - - #ifdef KONAN_NEED_ASINH_ACOSH namespace { @@ -99,7 +92,7 @@ namespace { extern "C" { -#if !KONAN_NO_MATH // There is a platform math library. +#ifndef KONAN_NO_MATH // There is a platform math library. // region Double math. @@ -357,6 +350,6 @@ KLong Kotlin_math_absl(KLong x) { NotImplemented(); } KLong Kotlin_math_minl(KLong a, KLong b) { NotImplemented(); } KLong Kotlin_math_maxl(KLong a, KLong b) { NotImplemented(); } -#endif // #if !KONAN_NO_MATH +#endif // #ifndef KONAN_NO_MATH } // extern "C" diff --git a/runtime/src/main/cpp/Porting.cpp b/runtime/src/main/cpp/Porting.cpp index 2031992d3f4..be703a02f30 100644 --- a/runtime/src/main/cpp/Porting.cpp +++ b/runtime/src/main/cpp/Porting.cpp @@ -32,12 +32,17 @@ #include +#include "Common.h" #include "Porting.h" -#if KONAN_WASM || __ZEPHYR__ +#if KONAN_WASM || KONAN_ZEPHYR extern "C" void Konan_abort(const char*); extern "C" void Konan_exit(int32_t status); #endif +#ifdef KONAN_ZEPHYR +// In Zephyr's Newlib strnlen(3) is not included from string.h by default. +extern "C" size_t strnlen(const char* buffer, size_t maxSize); +#endif namespace konan { @@ -70,9 +75,13 @@ void consoleErrorUtf8(const void* utf8, uint32_t sizeBytes) { } uint32_t consoleReadUtf8(void* utf8, uint32_t maxSizeBytes) { +#ifdef KONAN_ZEPHYR + return 0; +#else char* result = ::fgets(reinterpret_cast(utf8), maxSizeBytes - 1, stdin); if (result == nullptr) return 0; return ::strlen(result); +#endif } #if KONAN_INTERNAL_SNPRINTF @@ -124,7 +133,7 @@ static void onThreadExitInit() { void onThreadExit(void (*destructor)()) { #if KONAN_NO_THREADS -#if KONAN_WASM || __ZEPHYR__ +#if KONAN_WASM || KONAN_ZEPHYR // No way to do that. #else #error "How to do onThreadExit()?" @@ -141,11 +150,11 @@ void onThreadExit(void (*destructor)()) { } // Process execution. -void abort() { +void abort(void) { ::abort(); } -#if KONAN_WASM || __ZEPHYR__ +#if KONAN_WASM || KONAN_ZEPHYR void exit(int32_t status) { Konan_exit(status); } @@ -159,7 +168,7 @@ void exit(int32_t status) { // memcpy/memmove are not here intentionally, as frequently implemented/optimized // by C compiler. void* memmem(const void *big, size_t bigLen, const void *little, size_t littleLen) { -#if KONAN_WINDOWS || KONAN_WASM || __ZEPHYR__ +#if KONAN_NO_MEMMEM for (size_t i = 0; i + littleLen <= bigLen; ++i) { void* pos = ((char*)big) + i; if (::memcmp(little, pos, littleLen) == 0) return pos; @@ -180,11 +189,9 @@ int snprintf(char* buffer, size_t size, const char* format, ...) { return rv; } -#if !__ZEPHYR__ size_t strnlen(const char* buffer, size_t maxSize) { return ::strnlen(buffer, maxSize); } -#endif // Memory operations. #if KONAN_INTERNAL_DLMALLOC @@ -207,7 +214,14 @@ void free(void* pointer) { #if KONAN_INTERNAL_NOW +#ifdef KONAN_ZEPHYR +void Konan_date_now(uint64_t* arg) { + // TODO: so how will we support time for embedded? + *arg = 0LL; +} +#else extern "C" void Konan_date_now(uint64_t*); +#endif uint64_t getTimeMillis() { uint64_t now; @@ -243,7 +257,7 @@ uint64_t getTimeMicros() { #if KONAN_INTERNAL_DLMALLOC // This function is being called when memory allocator needs more RAM. -#if KONAN_WASM || __ZEPHYR__ +#if KONAN_WASM // This one is an interface to query module.env.memory.buffer.byteLength extern "C" unsigned long Konan_heap_upper(); @@ -304,12 +318,17 @@ long getpagesize() { } // namespace konan extern "C" { -#if KONAN_WASM || __ZEPHYR__ - - // TODO: get rid of these. +// TODO: get rid of these. +#if (KONAN_WASM || KONAN_ZEPHYR) + void _ZNKSt3__120__vector_base_commonILb1EE20__throw_length_errorEv(void) { + Konan_abort("TODO: throw_length_error not implemented."); + } void _ZNKSt3__220__vector_base_commonILb1EE20__throw_length_errorEv(void) { Konan_abort("TODO: throw_length_error not implemented."); } + void _ZNKSt3__121__basic_string_commonILb1EE20__throw_length_errorEv(void) { + Konan_abort("TODO: throw_length_error not implemented."); + } void _ZNKSt3__221__basic_string_commonILb1EE20__throw_length_errorEv(void) { Konan_abort("TODO: throw_length_error not implemented."); } @@ -336,6 +355,9 @@ extern "C" { } return prime; } + int _ZNSt3__112__next_primeEj(unsigned long n) { + return _ZNSt3__212__next_primeEj(n); + } void __assert_fail(const char * assertion, const char * file, unsigned int line, const char * function) { char buf[1024]; konan::snprintf(buf, sizeof(buf), "%s:%d in %s: runtime assert: %s\n", file, line, function, assertion); @@ -351,9 +373,10 @@ extern "C" { double pow(double x, double y) { return __builtin_pow(x, y); } +#endif +#ifdef KONAN_WASM // Some string.h functions. - void *memcpy(void *dst, const void *src, size_t n) { for (long i = 0; i != n; ++i) *((char*)dst + i) = *((char*)src + i); @@ -401,60 +424,39 @@ extern "C" { } #endif -#if __ZEPHYR__ - - /* Support the alias for the __aeabi_memcpy which may - assume memory alignment. */ - void __aeabi_memcpy4 (void *dest, const void *source, size_t n) - __attribute__ ((alias ("memcpy"))); - - void __aeabi_memcpy8 (void *dest, const void *source, size_t n) - __attribute__ ((alias ("memcpy"))); - - void __aeabi_memcpy (void *dest, const void *source, size_t n) - __attribute__ ((alias ("memcpy"))); - - /* Support the alias for the __aeabi_memmove which may - assume memory alignment. */ - void __aeabi_memmove4 (void *dest, const void *source, size_t n) - __attribute__ ((alias ("memmove"))); - - void __aeabi_memmove8 (void *dest, const void *source, size_t n) - __attribute__ ((alias ("memmove"))); - - void __aeabi_memmove (void *dest, const void *source, size_t n) - __attribute__ ((alias ("memmove"))); +#ifdef KONAN_ZEPHYR + RUNTIME_USED void Konan_abort(const char*) { + while(1) {} + } /* Support the alias for the __aeabi_memset which may assume memory alignment. */ - void __aeabi_memset4 (void *dest, size_t n, int c) + RUNTIME_USED void __aeabi_memset4 (void *dest, size_t n, int c) __attribute__ ((alias ("__aeabi_memset"))); - void __aeabi_memset8 (void *dest, size_t n, int c) + RUNTIME_USED void __aeabi_memset8 (void *dest, size_t n, int c) __attribute__ ((alias ("__aeabi_memset"))); /* Support the routine __aeabi_memset. Can't alias to memset because it's not defined in the same translation unit. */ - void __aeabi_memset (void *dest, size_t n, int c) + RUNTIME_USED void __aeabi_memset (void *dest, size_t n, int c) { /*Note that relative to ANSI memset, __aeabi_memset hase the order of its second and third arguments reversed. */ memset (dest, c, n); } - /* Support the alias for the __aeabi_memclr which may assume memory alignment. */ - void __aeabi_memclr4 (void *dest, size_t n) + RUNTIME_USED void __aeabi_memclr4 (void *dest, size_t n) __attribute__ ((alias ("__aeabi_memclr"))); - void __aeabi_memclr8 (void *dest, size_t n) + RUNTIME_USED void __aeabi_memclr8 (void *dest, size_t n) __attribute__ ((alias ("__aeabi_memclr"))); /* Support the routine __aeabi_memclr. */ - void __aeabi_memclr (void *dest, size_t n) + RUNTIME_USED void __aeabi_memclr (void *dest, size_t n) { __aeabi_memset (dest, n, 0); } - -#endif +#endif // KONAN_ZEPHYR } diff --git a/runtime/src/main/cpp/Porting.h b/runtime/src/main/cpp/Porting.h index dcee456628e..781c81d9ea0 100644 --- a/runtime/src/main/cpp/Porting.h +++ b/runtime/src/main/cpp/Porting.h @@ -32,7 +32,7 @@ void consoleErrorUtf8(const void* utf8, uint32_t sizeBytes); uint32_t consoleReadUtf8(void* utf8, uint32_t maxSizeBytes); // Process control. -void abort(); +void abort(void); void exit(int32_t status); // Thread control. diff --git a/runtime/src/main/cpp/Types.h b/runtime/src/main/cpp/Types.h index 7db903d2f61..850f19ef586 100644 --- a/runtime/src/main/cpp/Types.h +++ b/runtime/src/main/cpp/Types.h @@ -19,8 +19,8 @@ #include -#if (KONAN_WASM || __ZEPHYR__) && !defined(assert) -// assert() is needed by WASM STL. +#if (KONAN_WASM || KONAN_ZEPHYR) && !defined(assert) +// assert() is needed by STLport. #define assert(cond) if (!(cond)) abort() #endif diff --git a/runtime/src/main/cpp/dlmalloc/malloc.cpp b/runtime/src/main/cpp/dlmalloc/malloc.cpp index 7cce18210c1..35f4f3cce66 100644 --- a/runtime/src/main/cpp/dlmalloc/malloc.cpp +++ b/runtime/src/main/cpp/dlmalloc/malloc.cpp @@ -525,7 +525,7 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP /**** Start of Konan-specific dlmalloc configuration. ****/ #define USE_DL_PREFIX 1 -#if KONAN_WASM || __ZEPHYR__ +#if KONAN_WASM #define USE_LOCKS 0 #define LACKS_TIME_H 1 #define NO_MALLOC_STATS 1 diff --git a/samples/konan.sh b/samples/konan.sh index 5df5d4d46cd..2b71a177d17 100644 --- a/samples/konan.sh +++ b/samples/konan.sh @@ -4,4 +4,7 @@ if [ -z "$KONAN_HOME" ]; then PATH="$DIR/../../dist/bin:$DIR/../../bin:$PATH" else PATH="$KONAN_HOME/bin:$PATH" -fi \ No newline at end of file +fi + +KONAN_USER_DIR="$HOME/.konan" +KONAN_DEPS="$KONAN_USER_DIR/dependencies" diff --git a/samples/zephyr/CMakeLists.txt b/samples/zephyr/CMakeLists.txt index 5b4e05b9997..3a7ab86fc85 100644 --- a/samples/zephyr/CMakeLists.txt +++ b/samples/zephyr/CMakeLists.txt @@ -1,4 +1,4 @@ include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) project(NONE) -target_sources(app PRIVATE build/program.o) +target_sources(app PRIVATE build/program.o src/main.c src/blinky.c) diff --git a/samples/zephyr/build.sh b/samples/zephyr/build.sh index a00cd5c08dc..7c252e43295 100755 --- a/samples/zephyr/build.sh +++ b/samples/zephyr/build.sh @@ -1,18 +1,47 @@ #!/usr/bin/env bash +BOARD=stm32f4_disco +#export ZEPHYR_BASE="PLEASE_SET_ZEPHYR_BASE" +export ZEPHYR_BASE=~/kotlin-native/zephyr + +if [ "$ZEPHYR_BASE" == "PLEASE_SET_ZEPHYR_BASE" ] ; then + echo "Please set ZEPHYR_BASE in this build.sh." + exit 1 +fi + DIR=$(cd "$(dirname "${BASH_SOURCE[0]}" )" && pwd ) source "$DIR/../konan.sh" +if [ x$TARGET == x ]; then +case "$OSTYPE" in + darwin*) TOOLCHAIN=gcc-arm-none-eabi-7-2017-q4-major-mac ;; + linux*) TOOLCHAIN=gcc-arm-none-eabi-7-2017-q4-major-linux ;; + *) echo "unknown: $OSTYPE" && exit 1;; +esac +fi + +GCC_ARM="$KONAN_DEPS/$TOOLCHAIN" + mkdir -p $DIR/build && cd $DIR/build -konanc $DIR/src/main.kt -target zephyr +konanc $DIR/src/main.kt -target zephyr_$BOARD -linkerOpts -L$GCC_ARM/arm-none-eabi/lib/thumb -linkerOpts -lsupc++ -opt || exit 1 -DEP="$HOME/.konan/dependencies" -export ZEPHYR_BASE="$DEP/zephyr-zephyr-v1.10.0" export ZEPHYR_GCC_VARIANT=gccarmemb -export GCCARMEMB_TOOLCHAIN_PATH="$DEP/target-gcc-toolchain-6-2017q2-linux-armemb/" -export PATH="$DEP/zephyr-host-tools-1-linux/bin:$PATH" +export GCCARMEMB_TOOLCHAIN_PATH=$GCC_ARM + +[ -f CMakeCache.txt ] || cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBOARD=$BOARD .. || exit 1 +make || exit 1 + +# make flash +# +# For our STM32 boards the OpenOCD unable to flash the binary, +# so we go with the following alternative utility: -[ -f CMakeCache.txt ] || cmake -DBOARD=qemu_cortex_m3 .. -make run +echo +echo "Now run 'make flash' to flash the .bin to the card." +echo +echo "Or, if that doesn't work, like, for example if you have an stm32f4-disco," +echo "run the following command:" +echo "st-flash --reset write build/zephyr/zephyr.bin 0x08000000" +echo diff --git a/samples/zephyr/prj.conf b/samples/zephyr/prj.conf index fa6ff34bed9..fba5a3d9d7f 100644 --- a/samples/zephyr/prj.conf +++ b/samples/zephyr/prj.conf @@ -1,4 +1,5 @@ -CONFIG_CPLUSPLUS=y +CONFIG_CPLUSPLUS=n CONFIG_PRINTK=y CONFIG_BOOT_BANNER=y CONFIG_BUILD_OUTPUT_BIN=y +CONFIG_NEWLIB_LIBC=y diff --git a/samples/zephyr/src/blinky.c b/samples/zephyr/src/blinky.c new file mode 100644 index 00000000000..13833717eb3 --- /dev/null +++ b/samples/zephyr/src/blinky.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +/* Change this if you have an LED connected to a custom port */ +#define PORT LED0_GPIO_PORT + +/* Change this if you have an LED connected to a custom pin */ +#define LED LED0_GPIO_PIN + +/* 1000 msec = 1 sec */ +#define SLEEP_TIME 1000 + +void blinky(int value) +{ + int cnt = 0; + struct device *dev; + + dev = device_get_binding(PORT); + /* Set LED pin as output */ + gpio_pin_configure(dev, LED, GPIO_DIR_OUT); + + while (1) { + /* Set pin to HIGH/LOW every 1 second */ + gpio_pin_write(dev, LED, cnt % 2); + cnt++; + k_sleep(SLEEP_TIME * value); + } +} diff --git a/samples/zephyr/src/main.c b/samples/zephyr/src/main.c new file mode 100644 index 00000000000..04d3cba4833 --- /dev/null +++ b/samples/zephyr/src/main.c @@ -0,0 +1,18 @@ +/* + * 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. + */ + +extern int Konan_main(int argc, const char** argv); + diff --git a/samples/zephyr/src/main.cpp b/samples/zephyr/src/main.cpp deleted file mode 100644 index 04bd688f5f3..00000000000 --- a/samples/zephyr/src/main.cpp +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) 2012-2014 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -void main(void) -{ - printk("Hello World! %s\n", CONFIG_ARCH); -} diff --git a/samples/zephyr/src/main.kt b/samples/zephyr/src/main.kt index 1e42b4ff19a..311e56dca2b 100644 --- a/samples/zephyr/src/main.kt +++ b/samples/zephyr/src/main.kt @@ -1,3 +1,24 @@ +/* + * 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. + */ + +@SymbolName("blinky") +external fun blinky(value: Int) + +val x = 1 + fun main(args: Array) { - println("Hello World!") + blinky(x) } 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 436f5b357f8..159607044bf 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 @@ -81,19 +81,20 @@ class ClangArgs(private val configurables: Configurables) : Configurables by con "-nostdinc", "-Xclang", "-nobuiltininc", "-Xclang", "-nostdsysteminc", "-Xclang", "-isystem$absoluteTargetSysRoot/include/libcxx", "-Xclang", "-isystem$absoluteTargetSysRoot/lib/libcxxabi/include", "-Xclang", "-isystem$absoluteTargetSysRoot/include/compat", "-Xclang", "-isystem$absoluteTargetSysRoot/include/libc") - KonanTarget.ZEPHYR -> - listOf("-target", targetArg!!, "-mabi=aapcs", "-mthumb", "-mcpu=cortex-m3", - "-Os", "-g", + + is KonanTarget.ZEPHYR -> + listOf("-target", targetArg!!, "-fno-rtti", "-fno-exceptions", "-fno-asynchronous-unwind-tables", "-fno-pie", "-fno-pic", "-nostdinc", - "-isystem$sysRoot/include/libcxx", - "-isystem$sysRoot/lib/libcxxabi/include", - "-isystem$sysRoot/include/compat", - "-isystem$sysRoot/include/libc") + "-isystem$absoluteTargetSysRoot/include/libcxx", + "-isystem$absoluteTargetSysRoot/lib/libcxxabi/include", + "-isystem$absoluteTargetSysRoot/include/compat", + "-isystem$absoluteTargetSysRoot/include/libc") + + (configurables as ZephyrConfigurables).boardSpecificClangFlags } return result @@ -114,7 +115,7 @@ class ClangArgs(private val configurables: Configurables) : Configurables by con listOf("-DUSE_GCC_UNWIND=1", "-DUSE_ELF_SYMBOLS=1", "-DELFSIZE=32") KonanTarget.MINGW -> - listOf("-DUSE_GCC_UNWIND=1", "-DUSE_PE_COFF_SYMBOLS=1", "-DKONAN_WINDOWS=1") + listOf("-DUSE_GCC_UNWIND=1", "-DUSE_PE_COFF_SYMBOLS=1", "-DKONAN_WINDOWS=1", "-DKONAN_NO_MEMMEM=1") KonanTarget.MACBOOK -> listOf("-DKONAN_OSX=1", "-DKONAN_OBJC_INTEROP=1") @@ -133,13 +134,16 @@ class ClangArgs(private val configurables: Configurables) : Configurables by con KonanTarget.WASM32 -> 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") - KonanTarget.ZEPHYR -> - listOf( "-D__ZEPHYR__=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") + "-DKONAN_NO_MATH=1", "-DKONAN_INTERNAL_DLMALLOC=1", "-DKONAN_INTERNAL_SNPRINTF=1", + "-DKONAN_INTERNAL_NOW=1", "-DKONAN_NO_MEMMEM") + + is KonanTarget.ZEPHYR -> + listOf( "-DKONAN_ZEPHYR=1", "-DKONAN_NO_FFI=1", "-DKONAN_NO_THREADS=1", "-DKONAN_NO_EXCEPTIONS=1", + "-DKONAN_NO_MATH=1", "-DKONAN_INTERNAL_SNPRINTF=1", "-DKONAN_INTERNAL_NOW=1", + "-DKONAN_NO_MEMMEM=1") } - private val host = TargetManager.host + private val host = HostManager.host private val binDir = when (host) { KonanTarget.LINUX -> "$absoluteTargetToolchain/bin" @@ -167,7 +171,7 @@ class ClangArgs(private val configurables: Configurables) : Configurables by con home.parentFile.absolutePath } - val hostCompilerArgsForJni = listOf("", TargetManager.jniHostPlatformIncludeDir).map { "-I$jdkDir/include/$it" }.toTypedArray() + val hostCompilerArgsForJni = listOf("", HostManager.jniHostPlatformIncludeDir).map { "-I$jdkDir/include/$it" }.toTypedArray() val clangArgs = (commonClangArgs + specificClangArgs).toTypedArray() 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 index c4b70f6214b..7fbf33f85ca 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Configurables.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Configurables.kt @@ -88,3 +88,8 @@ interface WasmConfigurables : NonAppleConfigurables { val optOptFlags get() = targetList("optOptFlags") val optDebugFlags get() = targetList("optDebugFlags") } + +interface ZephyrConfigurables : NonAppleConfigurables { + val boardSpecificClangFlags get() = targetList("boardSpecificClangFlags") +} + 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 index 6b1d5d9071e..45125bd77eb 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ConfigurablesImpl.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/ConfigurablesImpl.kt @@ -33,6 +33,9 @@ class MingwConfigurablesImpl(target: KonanTarget, properties: Properties, baseDi class WasmConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?) : WasmConfigurables, KonanPropertiesLoader(target, properties, baseDir) +class ZephyrConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?) + : ZephyrConfigurables, KonanPropertiesLoader(target, properties, baseDir) + fun loadConfigurables(target: KonanTarget, properties: Properties, baseDir: String?) = when (target) { KonanTarget.LINUX, KonanTarget.RASPBERRYPI -> @@ -47,5 +50,7 @@ fun loadConfigurables(target: KonanTarget, properties: Properties, baseDir: Stri MingwConfigurablesImpl(target, properties, baseDir) KonanTarget.WASM32 -> WasmConfigurablesImpl(target, properties, baseDir) + is KonanTarget.ZEPHYR -> + ZephyrConfigurablesImpl(target, properties, baseDir) } diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Distribution.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Distribution.kt new file mode 100644 index 00000000000..030e73278fc --- /dev/null +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Distribution.kt @@ -0,0 +1,89 @@ +/* + * 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 org.jetbrains.kotlin.konan.file.File +import org.jetbrains.kotlin.konan.properties.keepOnlyDefaultProfiles +import org.jetbrains.kotlin.konan.properties.loadProperties +import org.jetbrains.kotlin.konan.util.DependencyProcessor + +class Distribution( + private val onlyDefaultProfiles: Boolean = false, + private val konanHomeOverride: String? = null, + private val runtimeFileOverride: String? = null) { + + val localKonanDir = "${File.userHome}/.konan" + + private fun findKonanHome(): String { + if (konanHomeOverride != null) return konanHomeOverride + + val value = System.getProperty("konan.home", "dist") + val path = File(value).absolutePath + return path + } + + val konanHome = findKonanHome() + val konanSubdir = "$konanHome/konan" + val mainPropertyFileName = "$konanSubdir/konan.properties" + + private fun propertyFilesFromConfigDir(configDir: String, genericName: String): List { + val directory = File(configDir, "platforms/$genericName") + return if (directory.exists && directory.isDirectory) + directory.listFiles + else + emptyList() + } + + private fun preconfiguredPropertyFiles(genericName: String) = + propertyFilesFromConfigDir(konanSubdir, genericName) + + private fun userPropertyFiles(genericName: String) = + propertyFilesFromConfigDir(localKonanDir, genericName) + + fun additionalPropertyFiles(genericName: String) = + preconfiguredPropertyFiles(genericName) + userPropertyFiles(genericName) + + val properties by lazy { + val loaded = File(mainPropertyFileName).loadProperties() + HostManager.knownTargetTemplates.forEach { + additionalPropertyFiles(it).forEach { + val additional = it.loadProperties() + loaded.putAll(additional) + } + } + if (onlyDefaultProfiles) { + loaded.keepOnlyDefaultProfiles() + } + loaded + } + + val klib = "$konanHome/klib" + val stdlib = "$klib/common/stdlib" + + fun defaultNatives(target: KonanTarget) = "$konanHome/konan/targets/${target.visibleName}/native" + + fun runtime(target: KonanTarget) = runtimeFileOverride ?: "$stdlib/targets/${target.visibleName}/native/runtime.bc" + + val dependenciesDir = DependencyProcessor.defaultDependenciesRoot.absolutePath + + fun availableSubTarget(genericName: String) = + additionalPropertyFiles(genericName).map { it.name } +} + +fun buildDistribution(konanHomeOverride: String? = null) = Distribution(true, konanHomeOverride, null) + +fun customerDistribution(konanHomeOverride: String? = null) = Distribution(false, konanHomeOverride, null) 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 e04ef9178da..f0ae8cdf76a 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 @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.konan.util.DependencyProcessor interface TargetableExternalStorage { fun targetString(key: String): String? - fun targetList(key: String): List + fun targetList(key: String): List fun hostString(key: String): String? fun hostList(key: String): List fun hostTargetString(key: String): String? @@ -50,6 +50,7 @@ abstract class KonanPropertiesLoader(override val target: KonanTarget, val prope = properties.hostTargetString(key, target) override fun hostTargetList(key: String): List = properties.hostTargetList(key, target) + override fun absolute(value: String?): String = dependencyProcessor!!.resolveRelative(value!!).absolutePath private val dependencyProcessor by lazy { @@ -57,3 +58,16 @@ abstract class KonanPropertiesLoader(override val target: KonanTarget, val prope } } +fun Properties.keepOnlyDefaultProfiles() { + val DEPENDENCY_PROFILES_KEY = "dependencyProfiles" + val dependencyProfiles = this.getProperty(DEPENDENCY_PROFILES_KEY) + if (dependencyProfiles != "default alt") + error("unexpected $DEPENDENCY_PROFILES_KEY value: expected 'default alt', got '$dependencyProfiles'") + + // Force build to use only 'default' profile: + this.setProperty(DEPENDENCY_PROFILES_KEY, "default") + // Force build to use fixed Xcode version: + this.setProperty("useFixedXcodeVersion", "9.2") + // TODO: it actually affects only resolution made in :dependencies, + // that's why we assume that 'default' profile comes first (and check this above). +} diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt index 235aa909444..1ffd6d985b1 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/KonanTarget.kt @@ -16,9 +16,8 @@ package org.jetbrains.kotlin.konan.target -import org.jetbrains.kotlin.konan.util.visibleName -import org.jetbrains.kotlin.konan.util.Named import org.jetbrains.kotlin.konan.target.KonanTarget.* +import org.jetbrains.kotlin.konan.util.Named enum class Family(val exeSuffix:String, val dynamicPrefix: String, val dynamicSuffix: String) { OSX ("kexe", "lib", "dylib"), @@ -39,7 +38,7 @@ enum class Architecture(val bitness: Int) { WASM32(32); } -sealed class KonanTarget(override val name: String, val family: Family, val architecture: Architecture, val detailedName: String, var enabled: Boolean = false) : Named { +sealed class KonanTarget(override val name: String, val family: Family, val architecture: Architecture, val detailedName: String) : Named { object ANDROID_ARM32 : KonanTarget( "android_arm32", Family.ANDROID, Architecture.ARM32, "android_arm32") object ANDROID_ARM64 : KonanTarget( "android_arm64", Family.ANDROID, Architecture.ARM64, "android_arm64") object IPHONE : KonanTarget( "iphone", Family.IOS, Architecture.ARM64, "ios") @@ -51,23 +50,9 @@ sealed class KonanTarget(override val name: String, val family: Family, val arch object LINUX_MIPS32 : KonanTarget( "linux_mips32", Family.LINUX, Architecture.MIPS32, "linux_mips32") object LINUX_MIPSEL32 : KonanTarget( "linux_mipsel32", Family.LINUX, Architecture.MIPSEL32, "linux_mipsel32") object WASM32 : KonanTarget( "wasm32", Family.WASM, Architecture.WASM32, "wasm32") - // Tunable targets - class ZEPHYR(val subName: String) : KonanTarget("$zephyr_$subName", Family.ZEPHYR, Architecture.ARM32, "$zephyr_$subName") - - companion object { - protected val memberObjects = mutableListOf() - fun values() = memberObjects - } - - init { - memberObjects.add(this) - } - fun generateZephyrTargets(subtargets: List) { - subtargets.forEach { - object : ZEPHYR(it) - } - } + // Tunable targets + class ZEPHYR(val subName: String, val genericName: String = "zephyr") : KonanTarget("${genericName}_$subName", Family.ZEPHYR, Architecture.ARM32, "${genericName}_$subName") } fun hostTargetSuffix(host: KonanTarget, target: KonanTarget) = @@ -95,12 +80,61 @@ enum class CompilerOutputKind { open fun prefix(target: KonanTarget? = null): String = "" } -class TargetManager(val userRequest: String? = null) { - val targets = KonanTarget.values().associate{ it.visibleName to it } - val target = determineCurrent() - val targetName +interface TargetManager { + val target: KonanTarget + val targetName : String + fun list() : Unit + val hostTargetSuffix: String + val targetSuffix: String +} + +private class TargetManagerImpl(val userRequest: String?, val hostManager: HostManager): TargetManager { + override val target = determineCurrent() + override val targetName get() = target.visibleName + override fun list() { + hostManager.enabled.forEach { + val isDefault = if (it == target) "(default)" else "" + println(String.format("%1$-30s%2$-10s", "${it.visibleName}:", "$isDefault")) + } + } + + fun determineCurrent(): KonanTarget { + return if (userRequest == null || userRequest == "host") { + HostManager.host + } else { + hostManager.targets[hostManager.known(userRequest)]!! + } + } + + override val hostTargetSuffix get() = hostTargetSuffix(HostManager.host, target) + override val targetSuffix get() = target.detailedName +} + +open class HostManager internal constructor(protected val distribution: Distribution = Distribution()) { + + fun targetManager(userRequest: String? = null): TargetManager = TargetManagerImpl(userRequest, this) + + // TODO: need a better way to enumerated predefined targets. + private val predefinedTargets = listOf(ANDROID_ARM32, ANDROID_ARM64, IPHONE, IPHONE_SIM, LINUX, MINGW, MACBOOK, RASPBERRYPI, LINUX_MIPS32, LINUX_MIPSEL32, WASM32) + + private val zephyrSubtargets = distribution.availableSubTarget("zephyr").map { ZEPHYR(it) } + + private val configurableSubtargets = zephyrSubtargets + + val targetValues: List by lazy { + predefinedTargets + configurableSubtargets + } + + val targets = targetValues.associate{ it.visibleName to it } + + fun toKonanTargets(names: Iterable): List { + return names.map { + if (it == "host") HostManager.host + else targets[known(it)]!! + } + } fun known(name: String): String { if (targets[name] == null) { @@ -109,28 +143,44 @@ class TargetManager(val userRequest: String? = null) { return name } - fun list() { - targets.forEach { key, it -> - if (it.enabled) { - val isDefault = if (it == target) "(default)" else "" - println(String.format("%1$-30s%2$-10s", "$key:", "$isDefault")) - } - } + fun targetByName(name: String): KonanTarget { + if (name == "host") return host + val target = targets[name] + if (target == null) throw TargetSupportException("Unknown target name: $name") + return target } - fun determineCurrent(): KonanTarget { - return if (userRequest == null || userRequest == "host") { - host - } else { - targets[known(userRequest)]!! - } + val enabled: List by lazy { + when (host) { + KonanTarget.LINUX -> listOf( + KonanTarget.LINUX, + KonanTarget.RASPBERRYPI, + KonanTarget.LINUX_MIPS32, + KonanTarget.LINUX_MIPSEL32, + KonanTarget.ANDROID_ARM32, + KonanTarget.ANDROID_ARM64, + KonanTarget.WASM32 + ) + zephyrSubtargets + KonanTarget.MINGW -> listOf( + KonanTarget.MINGW, + KonanTarget.WASM32 + ) + KonanTarget.MACBOOK -> listOf( + KonanTarget.MACBOOK, + KonanTarget.IPHONE, + KonanTarget.IPHONE_SIM, + KonanTarget.ANDROID_ARM32, + KonanTarget.ANDROID_ARM64, + KonanTarget.WASM32 + ) + zephyrSubtargets + else -> + throw TargetSupportException("Unknown host platform: $host") + } } - val hostTargetSuffix get() = hostTargetSuffix(host, target) - val targetSuffix get() = target.detailedName + fun isEnabled(target: KonanTarget) = enabled.contains(target) companion object { - fun host_os(): String { val javaOsName = System.getProperty("os.name") return when { @@ -180,46 +230,16 @@ class TargetManager(val userRequest: String? = null) { else -> throw TargetSupportException("Unknown host target: ${host_os()} ${host_arch()}") } + val hostIsMac = (host == KonanTarget.MACBOOK) + val hostIsLinux = (host == KonanTarget.LINUX) + val hostIsMingw = (host == KonanTarget.MINGW) + val hostSuffix get() = host.detailedName @JvmStatic val hostName get() = host.visibleName - init { - when (host) { - KonanTarget.LINUX -> { - KonanTarget.LINUX.enabled = true - /*KonanTarget.RASPBERRYPI.enabled = true - KonanTarget.LINUX_MIPS32.enabled = true - KonanTarget.LINUX_MIPSEL32.enabled = true - KonanTarget.ANDROID_ARM32.enabled = true - KonanTarget.ANDROID_ARM64.enabled = true - KonanTarget.WASM32.enabled = true*/ - KonanTarget.ZEPHYR.enabled = true - } - KonanTarget.MINGW -> { - KonanTarget.MINGW.enabled = true - KonanTarget.WASM32.enabled = true - } - KonanTarget.MACBOOK -> { - KonanTarget.MACBOOK.enabled = true - KonanTarget.IPHONE.enabled = true - KonanTarget.IPHONE_SIM.enabled = true - KonanTarget.ANDROID_ARM32.enabled = true - KonanTarget.ANDROID_ARM64.enabled = true - KonanTarget.WASM32.enabled = true - } - else -> - throw TargetSupportException("Unknown host platform: $host") - } - } - - @JvmStatic - val enabled: List - get() = KonanTarget.values().filter { it.enabled } + val knownTargetTemplates = listOf("zephyr") - val hostIsMac = (host == KonanTarget.MACBOOK) - val hostIsLinux = (host == KonanTarget.LINUX) - val hostIsMingw = (host == KonanTarget.MINGW) } } diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Linker.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Linker.kt index 75f40da643d..274f0af2017 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Linker.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Linker.kt @@ -33,7 +33,7 @@ abstract class LinkerFlags(val configurables: Configurables) protected val llvmBin = "${configurables.absoluteLlvmHome}/bin" protected val llvmLib = "${configurables.absoluteLlvmHome}/lib" - private val libLTODir = when (TargetManager.host) { + private val libLTODir = when (HostManager.host) { KonanTarget.MACBOOK, KonanTarget.LINUX -> llvmLib KonanTarget.MINGW -> llvmBin else -> error("Don't know libLTO location for this platform.") @@ -288,7 +288,7 @@ open class WasmLinker(targetProperties: WasmConfigurables) open class ZephyrLinker(targetProperties: ZephyrConfigurables) : LinkerFlags(targetProperties), ZephyrConfigurables by targetProperties { - private val linker = "$targetToolchain/bin/ld" + private val linker = "$absoluteTargetToolchain/bin/ld" override val useCompilerDriverAsLinker: Boolean get() = false @@ -318,5 +318,7 @@ fun linker(configurables: Configurables): LinkerFlags = MingwLinker(configurables as MingwConfigurables) KonanTarget.WASM32 -> WasmLinker(configurables as WasmConfigurables) + is KonanTarget.ZEPHYR -> + ZephyrLinker(configurables as ZephyrConfigurables) } diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Platform.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Platform.kt index 3e31eb6325f..98d1eb7f9b6 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Platform.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/Platform.kt @@ -16,7 +16,7 @@ package org.jetbrains.kotlin.konan.target -import org.jetbrains.kotlin.konan.properties.* +import org.jetbrains.kotlin.konan.util.DependencyProcessor class Platform(val configurables: Configurables) : Configurables by configurables { @@ -29,13 +29,19 @@ class Platform(val configurables: 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)) +class PlatformManager(distribution: Distribution = Distribution()) : HostManager(distribution) { + + private val loaders = enabled.map { + it to loadConfigurables(it, distribution.properties, DependencyProcessor.defaultDependenciesRoot.absolutePath) + }.toMap() + + private val platforms = loaders.map { + it.key to Platform(it.value) }.toMap() fun platform(target: KonanTarget) = platforms[target]!! val hostPlatform = platforms[host]!! + + fun loader(target: KonanTarget) = loaders[target]!! } diff --git a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/TargetProperties.kt b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/TargetProperties.kt index dfcf91c4522..a70c81d61fb 100644 --- a/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/TargetProperties.kt +++ b/shared/src/main/kotlin/org/jetbrains/kotlin/konan/target/TargetProperties.kt @@ -19,10 +19,10 @@ package org.jetbrains.kotlin.konan.properties import org.jetbrains.kotlin.konan.target.* fun Properties.hostString(name: String): String? - = this.propertyString(name, TargetManager.host.detailedName) + = this.propertyString(name, HostManager.host.detailedName) fun Properties.hostList(name: String): List - = this.propertyList(name, TargetManager.host.detailedName) + = this.propertyList(name, HostManager.host.detailedName) fun Properties.targetString(name: String, target: KonanTarget): String? = this.propertyString(name, target.detailedName) @@ -31,7 +31,7 @@ fun Properties.targetList(name: String, target: KonanTarget): List = this.propertyList(name, target.detailedName) fun Properties.hostTargetString(name: String, target: KonanTarget): String? - = this.propertyString(name, hostTargetSuffix(TargetManager.host, target)) + = this.propertyString(name, hostTargetSuffix(HostManager.host, target)) fun Properties.hostTargetList(name: String, target: KonanTarget): List - = this.propertyList(name, hostTargetSuffix(TargetManager.host, target)) + = this.propertyList(name, hostTargetSuffix(HostManager.host, target)) \ No newline at end of file diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanBuildingConfig.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanBuildingConfig.kt index 53c73d1680f..7dd1c1f7e1d 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanBuildingConfig.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanBuildingConfig.kt @@ -27,9 +27,8 @@ import org.gradle.api.plugins.BasePlugin import org.gradle.internal.reflect.Instantiator import org.gradle.util.ConfigureUtil import org.jetbrains.kotlin.gradle.plugin.tasks.KonanBuildingTask +import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.KonanTarget -import org.jetbrains.kotlin.konan.target.TargetManager -import org.jetbrains.kotlin.konan.util.visibleName import java.io.File /** Base class for all Kotlin/Native artifacts. */ @@ -47,11 +46,11 @@ abstract class KonanBuildingConfig(private val name_: Stri internal val aggregateBuildTask: Task private val konanTargets: Iterable - get() = targets.map { TargetManager(it).target }.distinct() + get() = project.platformManager.toKonanTargets(targets).distinct() init { for (target in konanTargets) { - if (!target.enabled) { + if (!project.platformManager.isEnabled(target)) { project.logger.warn("The target is not enabled on the current host: ${target.visibleName}") continue } @@ -109,7 +108,7 @@ abstract class KonanBuildingConfig(private val name_: Stri } protected fun createHostTaskIfDeclared(): Task? = - this[TargetManager.host]?.let { hostBuild -> + this[HostManager.host]?.let { hostBuild -> project.tasks.create(generateHostTaskName()) { it.group = BasePlugin.BUILD_GROUP it.description = generateHostTaskDescription(it, hostBuild.konanTarget) @@ -120,7 +119,7 @@ abstract class KonanBuildingConfig(private val name_: Stri internal operator fun get(target: KonanTarget) = targetToTask[target] fun getByTarget(target: String) = findByTarget(target) ?: throw NoSuchElementException("No such target for artifact $name: ${target}") - fun findByTarget(target: String) = this[TargetManager(target).target] + fun findByTarget(target: String) = this[project.platformManager.targetByName(target)] fun getArtifactByTarget(target: String) = getByTarget(target).artifact fun findArtifactByTarget(target: String) = findByTarget(target)?.artifact @@ -145,9 +144,9 @@ abstract class KonanBuildingConfig(private val name_: Stri fun dependsOn(vararg dependencies: Any?) = forEach { it.dependsOn(*dependencies) } fun target(targetString: String, configureAction: T.() -> Unit) { - val target = TargetManager(targetString).target + val target = project.platformManager.targetByName(targetString) - if (!target.enabled) { + if (!project.platformManager.isEnabled(target)) { project.logger.warn("Target '$targetString' of artifact '$name' is not supported on the current host") return } diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanPlugin.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanPlugin.kt index 8f66da147cc..84e6d4d446b 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanPlugin.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanPlugin.kt @@ -24,8 +24,8 @@ import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry import org.jetbrains.kotlin.gradle.plugin.KonanPlugin.Companion.COMPILE_ALL_TASK_NAME import org.jetbrains.kotlin.gradle.plugin.tasks.* import org.jetbrains.kotlin.konan.target.KonanTarget -import org.jetbrains.kotlin.konan.target.TargetManager -import org.jetbrains.kotlin.konan.util.visibleName +import org.jetbrains.kotlin.konan.target.PlatformManager +import org.jetbrains.kotlin.konan.target.customerDistribution import java.io.File import java.util.* import javax.inject.Inject @@ -74,8 +74,14 @@ internal val Project.konanArtifactsContainer: NamedDomainObjectContainer> +internal val Project.platformManager: PlatformManager + get() = findProperty("platformManager") as PlatformManager? ?: + PlatformManager(customerDistribution(konanHome)) + internal val Project.konanTargets: List - get() = konanExtension.konanTargets + get() = platformManager.toKonanTargets(konanExtension.targets) + .filter{ platformManager.isEnabled(it) } + .distinct() @Suppress("UNCHECKED_CAST") internal val Project.konanExtension: KonanExtension @@ -227,11 +233,7 @@ open class KonanExtension { var targets = mutableListOf("host") var languageVersion: String? = null var apiVersion: String? = null - val jvmArgs = mutableListOf() - - internal val konanTargets: List - get() = targets.map { TargetManager(it).target }.distinct() } class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderRegistry) diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanBaseTasks.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanBaseTasks.kt index b8accd3f951..be8efb09a85 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanBaseTasks.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanBaseTasks.kt @@ -28,16 +28,16 @@ import org.gradle.util.ConfigureUtil import org.jetbrains.kotlin.gradle.plugin.KonanArtifactSpec import org.jetbrains.kotlin.gradle.plugin.KonanArtifactWithLibrariesSpec import org.jetbrains.kotlin.gradle.plugin.KonanLibrariesSpec +import org.jetbrains.kotlin.gradle.plugin.konanTargets +import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.KonanTarget -import org.jetbrains.kotlin.konan.target.TargetManager -import org.jetbrains.kotlin.konan.util.visibleName import java.io.File internal val Project.host - get() = TargetManager.host.visibleName + get() = HostManager.host.visibleName internal val Project.simpleOsName - get() = TargetManager.simpleOsName() + get() = HostManager.simpleOsName() /** A task with a KonanTarget specified. */ abstract class KonanTargetableTask: DefaultTask() { @@ -48,11 +48,8 @@ abstract class KonanTargetableTask: DefaultTask() { this.konanTarget = target } - val targetIsSupported: Boolean - @Internal get() = konanTarget.enabled - val isCrossCompile: Boolean - @Internal get() = (konanTarget != TargetManager.host) + @Internal get() = (konanTarget != HostManager.host) val target: String @Internal get() = konanTarget.visibleName diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanCompilerDownloadTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanCompilerDownloadTask.kt index 788a31b3a85..e5612b48893 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanCompilerDownloadTask.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanCompilerDownloadTask.kt @@ -75,7 +75,7 @@ open class KonanCompilerDownloadTask : DefaultTask() { // Download dependencies if a user said so. if (downloadDependencies) { val runner = KonanCompilerRunner(project) - project.konanExtension.konanTargets.forEach { + project.konanTargets.forEach { runner.run("--check_dependencies", "-target", it.visibleName) } } diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanGenerateCMakeTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanGenerateCMakeTask.kt index 9fd8767f944..6a8f03e5bb5 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanGenerateCMakeTask.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanGenerateCMakeTask.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.gradle.plugin.KonanLibrary import org.jetbrains.kotlin.gradle.plugin.KonanProgram import org.jetbrains.kotlin.gradle.plugin.konanArtifactsContainer import org.jetbrains.kotlin.konan.target.Family -import org.jetbrains.kotlin.konan.target.TargetManager +import org.jetbrains.kotlin.konan.target.HostManager import java.io.File open class KonanGenerateCMakeTask : DefaultTask() { @@ -48,6 +48,8 @@ open class KonanGenerateCMakeTask : DefaultTask() { .mkdir() } + private val host = HostManager.host + private fun generateCMakeLists( projectName: String, interops: List, @@ -67,7 +69,7 @@ open class KonanGenerateCMakeTask : DefaultTask() { appendln() for (interop in interops) { - val task = interop[TargetManager.host] ?: continue + val task = interop[host] ?: continue appendln( Call("cinterop") .arg("NAME", interop.name) @@ -77,7 +79,7 @@ open class KonanGenerateCMakeTask : DefaultTask() { } for (library in libraries) { - val task = library[TargetManager.host] ?: continue + val task = library[host] ?: continue appendln( Call("konanc_library") .arg("NAME", library.name) @@ -87,7 +89,7 @@ open class KonanGenerateCMakeTask : DefaultTask() { } for (program in programs) { - val task = program[TargetManager.host] ?: continue + val task = program[host] ?: continue appendln( Call("konanc_executable") .arg("NAME", program.name) @@ -101,7 +103,7 @@ open class KonanGenerateCMakeTask : DefaultTask() { private val File.relativePath get() = relativeTo(project.projectDir) private val String.crossPlatformPath get() = - if (TargetManager.host.family == Family.WINDOWS) replace('\\', '/') else this + if (host.family == Family.WINDOWS) replace('\\', '/') else this private val FileCollection.asCMakeSourceList: List get() = files.map { it.relativePath.toString().crossPlatformPath } diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanInteropTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanInteropTask.kt index be8239fa55e..b2659561ca4 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanInteropTask.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanInteropTask.kt @@ -62,8 +62,6 @@ open class KonanInteropTask: KonanBuildingTask(), KonanInteropSpec { @InputFiles val linkFiles = mutableSetOf() override fun buildArgs() = mutableListOf().apply { - addArg("-properties", "${project.konanHome}/konan/konan.properties") - addArg("-o", artifact.canonicalPath) addArgIfNotNull("-target", konanTarget.visibleName) diff --git a/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/CMakeSpecification.groovy b/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/CMakeSpecification.groovy index 0ea48fa636b..3912db2401c 100644 --- a/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/CMakeSpecification.groovy +++ b/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/CMakeSpecification.groovy @@ -1,14 +1,14 @@ package org.jetbrains.kotlin.gradle.plugin.test import org.jetbrains.kotlin.konan.target.Family -import org.jetbrains.kotlin.konan.target.TargetManager +import org.jetbrains.kotlin.konan.target.HostManager class CMakeSpecification extends BaseKonanSpecification { def 'Plugin should generate CMake from project without additional settings'() { when: def sdlIncludePath def sdlLinkOptions - switch (TargetManager.host.family) { + switch (HostManager.host.family) { case Family.WINDOWS: sdlIncludePath = "C:/SDL2/include" sdlLinkOptions = "C:/SDL2/lib" @@ -22,7 +22,7 @@ class CMakeSpecification extends BaseKonanSpecification { sdlLinkOptions = "-L/usr/lib/x86_64-linux-gnu" break default: - throw IllegalStateException("Unknown host: $TargetManager.host") + throw IllegalStateException("Unknown host: ${HostManager.hostName}") break } diff --git a/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/KonanProject.groovy b/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/KonanProject.groovy index 7b5abea5dfa..dd6b2fe6864 100644 --- a/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/KonanProject.groovy +++ b/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/KonanProject.groovy @@ -1,7 +1,7 @@ package org.jetbrains.kotlin.gradle.plugin.test import org.gradle.testkit.runner.GradleRunner -import org.jetbrains.kotlin.konan.target.TargetManager +import org.jetbrains.kotlin.konan.target.HostManager import java.nio.file.Files import java.nio.file.Path @@ -25,7 +25,7 @@ class KonanProject { static String DEFAULT_ARTIFACT_NAME = 'main' static String DEFAULT_INTEROP_NAME = "stdio" - static String HOST = TargetManager.hostName + static String HOST = HostManager.hostName File projectDir Path projectPath diff --git a/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/PathSpecification.groovy b/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/PathSpecification.groovy index 45e87e8de3c..dc50353bdef 100644 --- a/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/PathSpecification.groovy +++ b/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/PathSpecification.groovy @@ -1,7 +1,7 @@ package org.jetbrains.kotlin.gradle.plugin.test import org.gradle.testkit.runner.TaskOutcome -import org.jetbrains.kotlin.konan.target.TargetManager +import org.jetbrains.kotlin.konan.target.PlatformManager class PathSpecification extends BaseKonanSpecification { @@ -9,14 +9,13 @@ class PathSpecification extends BaseKonanSpecification { project.konanBuildDir.toPath().resolve(path).toFile().exists() } + def platformManager = new PlatformManager() + def 'Plugin should provide a correct path to the artifacts created'() { expect: def project = KonanProject.createEmpty( projectDirectory, - new TargetManager('host') - .getTargets() - .findAll { k, v -> v.enabled } - .collect { k, v -> k } + platformManager.enabled.collect { t -> t.visibleName } ) { KonanProject it -> it.generateSrcFile("main.kt") it.generateDefFile("interop.def", "") @@ -71,9 +70,10 @@ class PathSpecification extends BaseKonanSpecification { def project = KonanProject.create(projectDirectory) project.propertiesFile.write("konan.home=fakepath") def result = project.createRunner().withArguments('build').buildAndFail() + def task = result.task(project.defaultCompilationTask()) then: - result.task(project.defaultCompilationTask()).outcome == TaskOutcome.FAILED + task == null || task.outcome == TaskOutcome.FAILED } def 'Plugin should stop building if the stub generator classpath is empty'() { @@ -81,9 +81,10 @@ class PathSpecification extends BaseKonanSpecification { def project = KonanProject.createWithInterop(projectDirectory) project.propertiesFile.write("konan.home=fakepath") def result = project.createRunner().withArguments('build').buildAndFail() + def task = result.task(project.compilationTask(KonanProject.DEFAULT_INTEROP_NAME)) then: - result.task(project.compilationTask(KonanProject.DEFAULT_INTEROP_NAME)).outcome == TaskOutcome.FAILED + task == null || task.outcome == TaskOutcome.FAILED } def 'Plugin should remove custom output directories'() { diff --git a/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/TaskSpecification.groovy b/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/TaskSpecification.groovy index 1a58e9f9fd1..fa4ca6bf562 100644 --- a/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/TaskSpecification.groovy +++ b/tools/kotlin-native-gradle-plugin/src/test/groovy/org/jetbrains/kotlin/gradle/plugin/test/TaskSpecification.groovy @@ -3,7 +3,7 @@ package org.jetbrains.kotlin.gradle.plugin.test import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.TaskOutcome import org.jetbrains.kotlin.konan.target.KonanTarget -import org.jetbrains.kotlin.konan.target.TargetManager +import org.jetbrains.kotlin.konan.target.HostManager import spock.lang.Requires import spock.lang.Unroll @@ -58,7 +58,7 @@ class TaskSpecification extends BaseKonanSpecification { "includeDirs" | "" } - @Requires({ TargetManager.host == KonanTarget.MACBOOK }) + @Requires({ HostManager.host instanceof KonanTarget.MACBOOK }) def 'Plugin should create framework tasks only for Apple targets'() { when: def project = KonanProject.createEmpty(projectDirectory) { KonanProject it -> @@ -91,7 +91,7 @@ class TaskSpecification extends BaseKonanSpecification { """.stripIndent()) } def result = project.createRunner().withArguments('tasks', '--all').build() - def hostName = TargetManager.getHostName() + def hostName = HostManager.hostName then: compilationTaskExists (result, 'defaultTarget', hostName) diff --git a/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/InteropCompiler.kt b/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/InteropCompiler.kt index 365cab6ebf3..84d28fa1d68 100644 --- a/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/InteropCompiler.kt +++ b/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/InteropCompiler.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.backend.konan.library.impl.KonanLibrary import org.jetbrains.kotlin.backend.konan.library.resolveLibrariesRecursive import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.properties.loadProperties -import org.jetbrains.kotlin.konan.target.TargetManager +import org.jetbrains.kotlin.konan.target.PlatformManager import org.jetbrains.kotlin.native.interop.gen.jvm.interop import org.jetbrains.kotlin.utils.addIfNotNull @@ -35,7 +35,7 @@ fun invokeInterop(flavor: String, args: Array): Array { val cinteropArgFilter = listOf(NODEFAULTLIBS, PURGE_USER_LIBS) var outputFileName = "nativelib" - var target = "host" + var targetRequest = "host" val libraries = mutableListOf() val repos = mutableListOf() var noDefaultLibs = false @@ -46,7 +46,7 @@ fun invokeInterop(flavor: String, args: Array): Array { if (arg.startsWith("-o")) outputFileName = nextArg ?: outputFileName if (arg == "-target") - target = nextArg ?: target + targetRequest = nextArg ?: targetRequest if (arg == "-library") libraries.addIfNotNull(nextArg) if (arg == "-r" || arg == "-repo") @@ -64,10 +64,10 @@ fun invokeInterop(flavor: String, args: Array): Array { val cstubsName ="cstubs" val manifest = File(buildDir, "manifest.properties") - val targetManager = TargetManager(target) - val resolver = defaultResolver(repos, targetManager.target) + val target = PlatformManager().targetManager(targetRequest).target + val resolver = defaultResolver(repos, target) val allLibraries = resolver.resolveLibrariesRecursive( - libraries, targetManager.target, noStdLib = true, noDefaultLibs = noDefaultLibs + libraries, target, noStdLib = true, noDefaultLibs = noDefaultLibs ) val importArgs = allLibraries.flatMap { @@ -104,7 +104,7 @@ fun invokeInterop(flavor: String, args: Array): Array { generatedDir.path, "-produce", "library", "-o", outputFileName, - "-target", target, + "-target", target.visibleName, "-manifest", manifest.path) + nativeStubs + cinteropArgsToCompiler +