From 48742b7f3f30606023668612abb8f6a0c2325187 Mon Sep 17 00:00:00 2001 From: Alexander Gorshenev Date: Mon, 22 May 2017 15:35:21 +0300 Subject: [PATCH] Library search path resolution. --- .../org/jetbrains/kotlin/cli/bc/K2Native.kt | 2 + .../cli/bc/K2NativeCompilerArguments.java | 3 + .../kotlin/backend/konan/Distribution.kt | 4 + .../kotlin/backend/konan/KonanConfig.kt | 13 ++- .../backend/konan/KonanConfigurationKeys.kt | 2 + .../konan/library/SearchPathResolver.kt | 84 +++++++++++++++++++ .../kotlin/backend/konan/util/NoJavaUtil.kt | 7 ++ 7 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/SearchPathResolver.kt 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 898c2d4824a..6ce33c6192b 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 @@ -101,6 +101,8 @@ class K2Native : CLICompiler() { put(NATIVE_LIBRARY_FILES, arguments.nativeLibraries.toNonNullList()) + put(REPOSITORIES, + arguments.repositories.toNonNullList()) // TODO: Collect all the explicit file names into an object // and teach the compiler to work with temporaries and -save-temps. diff --git a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.java b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.java index f7782e91a51..fb05fea558e 100644 --- a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.java +++ b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.java @@ -83,6 +83,9 @@ public class K2NativeCompilerArguments extends CommonCompilerArguments { @Argument(value = "--print_bitcode", description = "Print llvm bitcode") public boolean printBitCode; + @Argument(value = "-repo", shortName = "-r", valueDescription = "", description = "Library search path") + public String[] repositories; + @Argument(value = "--verify_ir", description = "Verify IR") public boolean verifyIr; diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Distribution.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Distribution.kt index 0705ed4016d..56f2627049c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Distribution.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Distribution.kt @@ -27,6 +27,10 @@ class Distribution(val config: CompilerConfiguration) { val hostSuffix = TargetManager.host.suffix init { if (!targetManager.crossCompile) assert(suffix == hostSuffix) } + private fun findUserHome() = File(System.getProperty("user.home")).absolutePath + val userHome = findUserHome() + val localKonanDir = "$userHome/.konan" + private fun findKonanHome(): String { val value = System.getProperty("konan.home", "dist") val path = File(value).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 15176fa7023..e16e61daac6 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 @@ -19,12 +19,13 @@ package org.jetbrains.kotlin.backend.konan import com.intellij.openapi.project.Project import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader import org.jetbrains.kotlin.backend.konan.library.SplitLibraryReader +import org.jetbrains.kotlin.backend.konan.library.KonanLibrarySearchPathResolver import org.jetbrains.kotlin.backend.konan.util.profile import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl -import java.io.File +import org.jetbrains.kotlin.backend.konan.util.File class KonanConfig(val project: Project, val configuration: CompilerConfiguration) { @@ -40,14 +41,20 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration if (configuration.get(KonanConfigKeys.NOSTDLIB) ?: false) { return fromCommandLine } - return fromCommandLine + distribution.stdlib + return fromCommandLine + "stdlib" } + private val repositories = configuration.getList(KonanConfigKeys.REPOSITORIES) ?: emptyList() + private val resolver = KonanLibrarySearchPathResolver(repositories, distribution) + private val librariesFound: List by lazy { + libraryNames.map{it -> resolver.resolve(it)} + } + internal val libraries: List by lazy { val currentAbiVersion = configuration.get(KonanConfigKeys.ABI_VERSION)!! val target = targetManager.currentName // Here we have chosen a particular KonanLibraryReader implementation. - libraryNames.map{it -> SplitLibraryReader(it, currentAbiVersion, target)} + librariesFound.map{it -> SplitLibraryReader(it, currentAbiVersion, target)} } private val loadedDescriptors = loadLibMetadata() 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 c5bca4dd385..9fc523efa29 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 @@ -53,6 +53,8 @@ class KonanConfigKeys { = CompilerConfigurationKey.create("assume 'main' entry point to be provided by external libraries") val LINKER_ARGS: CompilerConfigurationKey> = CompilerConfigurationKey.create("additional linker arguments") + val REPOSITORIES: CompilerConfigurationKey> + = CompilerConfigurationKey.create("library search path repositories") val TARGET: CompilerConfigurationKey = CompilerConfigurationKey.create("target we compile for") val LIST_TARGETS: CompilerConfigurationKey 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 new file mode 100644 index 00000000000..d34a06d2097 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/SearchPathResolver.kt @@ -0,0 +1,84 @@ +/* + * 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.library + +import org.jetbrains.kotlin.backend.konan.Distribution +import org.jetbrains.kotlin.backend.konan.KonanProperties +import org.jetbrains.kotlin.backend.konan.util.File + +interface SearchPathResolver { + val searchRoots: List + fun resolve(givenPath: String): File +} + +fun String.suffixIfNot(suffix: String) = + if (this.endsWith(suffix)) this else "$this$suffix" + +fun String.removeSuffixIfPresent(suffix: String) = + if (this.endsWith(suffix)) this.dropLast(suffix.length) else this + +class KonanLibrarySearchPathResolver(repositories: List, + val distribution: Distribution): SearchPathResolver { + + private val properties = distribution.properties + val localHead: File + get() = File(distribution.localKonanDir).klib + + val distHead: File + get() = File(distribution.klib) + + val currentDirHead: File + get() = File.userDir.klib + + private val repoRoots: List by lazy { + repositories.map{File(it).klib} + } + + // This is the place where we specify the order of library search. + override val searchRoots: List by lazy { + listOf(currentDirHead) + repoRoots + listOf(localHead, distHead) + } + + private fun found(candidate: File): File? { + val noSuffix = File(candidate.path.removeSuffixIfPresent(".klib")) + val withSuffix = File(candidate.path.suffixIfNot(".klib")) + if (withSuffix.exists) { + // We always returing the name without suffix here. + return noSuffix + } + if (noSuffix.exists) { + return noSuffix + } + return null + } + + override fun resolve(givenPath: String): File { + val given = File(givenPath) + if (given.isAbsolute) { + found(given)?.apply{return this} + } else { + searchRoots.forEach{ + found(File(it, givenPath))?.apply{return this} + } + } + error("Could not find \"$givenPath\" in any of the provided locations.") + } + + private val File.klib + get() = File(this, "klib") +} + diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/NoJavaUtil.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/NoJavaUtil.kt index 300c07b9615..54fdffdb034 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/NoJavaUtil.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/util/NoJavaUtil.kt @@ -44,6 +44,8 @@ class File(val path: String) { get() = javaFile.isDirectory() val isFile get() = javaFile.isFile() + val isAbsolute + get() = javaFile.isAbsolute() val listFiles get() = javaFile.listFiles()!!.toList() @@ -58,6 +60,11 @@ class File(val path: String) { // TODO: Consider removeing these after konanazing java.util.Properties. fun bufferedReader() = javaFile.bufferedReader() fun outputStream() = javaFile.outputStream() + + companion object { + val userDir + get() = File(System.getProperty("user.dir")) + } }