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 335a4fad413..5c4cfb7a83b 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 @@ -44,7 +44,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration } private val repositories = configuration.getList(KonanConfigKeys.REPOSITORIES) ?: emptyList() - private val resolver = KonanLibrarySearchPathResolver(repositories, distribution) + private val resolver = KonanLibrarySearchPathResolver(repositories, distribution.klib, distribution.localKonanDir) private val librariesFound: List by lazy { libraryNames.map{it -> resolver.resolve(it)} } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanTarget.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanTarget.kt index 4797b49a137..a1770ffa597 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanTarget.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanTarget.kt @@ -29,7 +29,8 @@ enum class KonanTarget(val suffix: String, var enabled: Boolean = false) { RASPBERRYPI("raspberrypi") } -class TargetManager(val config: CompilerConfiguration) { +class TargetManager(val userRequest: String? = null) { + constructor(config: CompilerConfiguration) : this(config.get(KonanConfigKeys.TARGET)) val targets = KonanTarget.values().associate{ it.name.toLowerCase() to it } val current = determineCurrent() val currentName @@ -79,7 +80,6 @@ class TargetManager(val config: CompilerConfiguration) { } fun determineCurrent(): KonanTarget { - val userRequest = config.get(KonanConfigKeys.TARGET) return if (userRequest == null || userRequest == "host") { host } else { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibrary.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibrary.kt index 8aad84984f1..baeea368e0e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibrary.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibrary.kt @@ -185,8 +185,6 @@ class SplitLibraryWriter(override val libDir: File, override val target: String? override fun commit() { if (!nopack) { - // This is no-op for the Split library. - // Or should we zip the directory? libDir.zipDirAs(klibFile) libDir.deleteRecursively() } 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 d99ba7774d2..df658667990 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,8 +16,6 @@ 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 import org.jetbrains.kotlin.backend.konan.util.suffixIfNot import org.jetbrains.kotlin.backend.konan.util.removeSuffixIfPresent @@ -28,14 +26,13 @@ interface SearchPathResolver { } class KonanLibrarySearchPathResolver(repositories: List, - val distribution: Distribution): SearchPathResolver { + val distributionKlib: String, val localKonanDir: String): SearchPathResolver { - private val properties = distribution.properties val localHead: File - get() = File(distribution.localKonanDir).klib + get() = File(localKonanDir).klib val distHead: File - get() = File(distribution.klib) + get() = File(distributionKlib) val currentDirHead: File get() = File.userDir 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 63892014568..a7d3142b6c7 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 @@ -110,7 +110,7 @@ fun Path.recursiveCopyTo(destPath: Path) { } } -fun File.copyTo(destination: File) { - Files.copy(this.toPath(), destination.toPath()) +fun File.copyTo(destination: File, vararg options: StandardCopyOption) { + Files.copy(this.toPath(), destination.toPath(), *options) } diff --git a/build.gradle b/build.gradle index b5069cfbceb..45f14747746 100644 --- a/build.gradle +++ b/build.gradle @@ -28,6 +28,9 @@ allprojects { repositories { mavenCentral() + maven { + url kotlinCompilerRepo + } } loadCommandLineProperties() @@ -250,6 +253,7 @@ task distCompiler(type: Copy) { dependsOn ':backend.native:jars' dependsOn ':tools:helpers:jar' dependsOn ':utilities:jar' + dependsOn ':klib:jar' destinationDir file('dist') @@ -293,6 +297,10 @@ task distCompiler(type: Copy) { into('konan/lib') } + from(project(':klib').file('build/libs')) { + into('konan/lib') + } + from(file('cmd')) { fileMode(0755) into('bin') diff --git a/cmd/klib b/cmd/klib new file mode 100755 index 00000000000..8d47e413e0d --- /dev/null +++ b/cmd/klib @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +# 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. + +DIR="${BASH_SOURCE[0]%/*}" +: ${DIR:="."} + +"${DIR}"/run_konan klib "$@" diff --git a/cmd/run_konan b/cmd/run_konan index e263d2f0fe8..4fe959e777e 100755 --- a/cmd/run_konan +++ b/cmd/run_konan @@ -80,11 +80,11 @@ STUB_GENERATOR_JAR="${KONAN_HOME}/konan/lib/StubGenerator.jar" INTEROP_INDEXER_JAR="${KONAN_HOME}/konan/lib/Indexer.jar" INTEROP_JAR="${KONAN_HOME}/konan/lib/Runtime.jar" HELPERS_JAR="${KONAN_HOME}/konan/lib/helpers.jar" +KLIB_JAR="${KONAN_HOME}/konan/lib/klib.jar" UTILITIES_JAR="${KONAN_HOME}/konan/lib/utilities.jar" -KONAN_CLASSPATH="$KOTLIN_JAR:$INTEROP_JAR:$STUB_GENERATOR_JAR:$INTEROP_INDEXER_JAR:$KONAN_JAR:$HELPERS_JAR:$UTILITIES_JAR" -#KONAN_COMPILER=org.jetbrains.kotlin.cli.bc.K2NativeKt -KONAN_COMPILER=org.jetbrains.kotlin.cli.utilities.MainKt +KONAN_CLASSPATH="$KOTLIN_JAR:$INTEROP_JAR:$STUB_GENERATOR_JAR:$INTEROP_INDEXER_JAR:$KONAN_JAR:$HELPERS_JAR:$KLIB_JAR:$UTILITIES_JAR" +TOOL_CLASS=org.jetbrains.kotlin.cli.utilities.MainKt LIBCLANG_DISABLE_CRASH_RECOVERY=1 \ -"$JAVACMD" "${java_opts[@]}" "${java_args[@]}" -cp "$KONAN_CLASSPATH" "$KONAN_COMPILER" "$TOOL_NAME" "${konan_args[@]}" +"$JAVACMD" "${java_opts[@]}" "${java_args[@]}" -cp "$KONAN_CLASSPATH" "$TOOL_CLASS" "$TOOL_NAME" "${konan_args[@]}" diff --git a/klib/build.gradle b/klib/build.gradle new file mode 100644 index 00000000000..2957ccbe892 --- /dev/null +++ b/klib/build.gradle @@ -0,0 +1,32 @@ +/* + * 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. + */ + +buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +apply plugin: 'kotlin' + +dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + compile project(path: ':backend.native', configuration: 'cli_bc') +} 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 new file mode 100644 index 00000000000..9b64accf49f --- /dev/null +++ b/klib/src/main/kotlin/org/jetbrains/kotlin/cli/klib/main.kt @@ -0,0 +1,130 @@ +package org.jetbrains.kotlin.cli.klib + +import kotlin.system.exitProcess +import java.util.Properties +// TODO: Extract these as a shared jar? +import org.jetbrains.kotlin.backend.konan.library.SplitLibraryReader +import org.jetbrains.kotlin.backend.konan.util.File +import org.jetbrains.kotlin.backend.konan.util.copyTo +import org.jetbrains.kotlin.backend.konan.TargetManager + +fun printUsage() { + println("Usage: klib ") + println("where the commands are:") + println("\tinfo\tgeneral information about the library") + println("\tinstall\tinstall the library to the local repository") + println("\tlist\tcontents of the library") + println("\tremove\tremove the library from the local repository") + println("and the options are:") + println("\t-repository \twork with the specified repository") + println("\t-target \tinspect specifics of the given target") +} + +private fun parseArgs(args: Array): Map> { + val commandLine = mutableMapOf>() + for (index in 0..args.size - 1 step 2) { + val key = args[index] + if (key[0] != '-') { + throw IllegalArgumentException("Expected a flag with initial dash: $key") + } + if (index + 1 == args.size) { + throw IllegalArgumentException("Expected an value after $key") + } + val value = listOf(args[index + 1]) + commandLine[key]?.addAll(value) ?: commandLine.put(key, value.toMutableList()) + } + return commandLine +} + + +class Command(args: Array){ + init { + if (args.size < 2) { + printUsage() + exitProcess(0) + } + } + val verb = args[0] + val library = args[1] + val options = parseArgs(args.drop(2).toTypedArray()) +} + +fun warn(text: String) { + println("warning: $text") +} + +fun error(text: String) { + println("error: $text") + exitProcess(1) +} + +class Library(val name: String, val repository: String, val target: String) { + + val file = File(name) + val repositoryFile = File(repository) + + // TODO: need to do something here. + val currentAbiVersion = 1 + + val splitLibrary = SplitLibraryReader(file, currentAbiVersion, target) + val manifestFile = splitLibrary.manifestFile + + fun info() { + val header = Properties() + manifestFile.bufferedReader().use { reader -> + header.load(reader) + } + val headerAbiVersion = header.getProperty("abi_version")!! + val moduleName = header.getProperty("module_name")!! + println("Module name: $moduleName") + println("ABI version: $headerAbiVersion") + } + + fun install() { + remove() + val baseName = splitLibrary.klibFile.name + val newKlibName = File(repositoryFile, baseName) + splitLibrary.klibFile.copyTo(newKlibName) + } + + fun remove() { + repositoryFile.mkdirs() + val baseName = splitLibrary.klibFile.name + val newDirName = File(repositoryFile, splitLibrary.libDir.name) + val newKlibName = File(repositoryFile, baseName) + newKlibName.deleteRecursively() + newDirName.deleteRecursively() + } + + fun list() { + // TODO: implement printing deserialized module protobuf. + println("Module listing not implemented yet.") + } +} + +fun main(args: Array) { + val command = Command(args) + + val targetManager = TargetManager(command.options["target"]?.last()) + val target = targetManager.currentName + + val repository = command.options["repository"]?.last() + val repositoryList = repository ?.let { listOf(it) } ?: emptyList() + + val userHome = File(System.getProperty("user.home")).absolutePath + val userKonan = File(userHome, ".konan") + val userRepo = File(userKonan, "klib") + + val library = Library(command.library, repository ?: userRepo.path, target) + + warn("IMPORTANT: the library format is unstable now. It can change with any new git commit without warning!") + + when (command.verb) { + "info" -> library.info() + "install" -> library.install() + "list" -> library.list() + "remove" -> library.remove() + else -> error("Unknown command ${command.verb}.") + } +} + diff --git a/settings.gradle b/settings.gradle index 3185a93de9f..f6ae4714819 100644 --- a/settings.gradle +++ b/settings.gradle @@ -19,6 +19,7 @@ include ':Interop:Indexer' include ':Interop:StubGenerator' include ':Interop:Runtime' include ':llvmDebugInfoC' +include ':klib' include ':backend.native' include ':runtime' include ':common' diff --git a/utilities/build.gradle b/utilities/build.gradle index 6e2f57c023a..425e255f193 100644 --- a/utilities/build.gradle +++ b/utilities/build.gradle @@ -25,9 +25,6 @@ buildscript { } apply plugin: 'kotlin' -apply plugin: 'application' - -mainClassName = "org.jetbrains.kotlin.cli.utilities.MainKt" dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" diff --git a/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/main.kt b/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/main.kt index d32c506cdc8..e3eafbd0953 100644 --- a/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/main.kt +++ b/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/main.kt @@ -3,6 +3,7 @@ package org.jetbrains.kotlin.cli.utilities import org.jetbrains.kotlin.backend.konan.util.File import org.jetbrains.kotlin.cli.bc.main as konancMain import org.jetbrains.kotlin.native.interop.gen.jvm.main as cinteropMain +import org.jetbrains.kotlin.cli.klib.main as klibMain fun invokeCinterop(args: Array) { var outputFileName = "nativelib" @@ -46,9 +47,9 @@ fun main(args: Array) { "cinterop" -> invokeCinterop(utilityArgs) "klib" -> - println("would run: klib $utilityArgs") + klibMain(utilityArgs) else -> - println("Unexpected utility name") + error("Unexpected utility name") } }