Depend on kotlin-native-shared from a separate repo
Kotlin-native-shared was copied in a separate repository. This patch removes this subproject from the K/N repo and adds a dependency on an artifact built from this separate repo.
This commit is contained in:
committed by
Ilya Matveev
parent
575cbf48c3
commit
a2370920db
@@ -18,10 +18,10 @@ buildscript {
|
||||
ext.rootBuildDirectory = file('../..')
|
||||
|
||||
apply from: "$rootBuildDirectory/gradle/kotlinGradlePlugin.gradle"
|
||||
apply from: "$rootBuildDirectory/gradle/kotlinNativeShared.gradle"
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-stdlib:$buildKotlinVersion"
|
||||
classpath "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
||||
}
|
||||
}
|
||||
apply plugin: 'kotlin'
|
||||
|
||||
@@ -21,10 +21,10 @@ buildscript {
|
||||
ext.rootBuildDirectory = file('../..')
|
||||
|
||||
apply from: "$rootBuildDirectory/gradle/kotlinGradlePlugin.gradle"
|
||||
apply from: "$rootBuildDirectory/gradle/kotlinNativeShared.gradle"
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-stdlib:$buildKotlinVersion"
|
||||
classpath "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
||||
}
|
||||
}
|
||||
import org.jetbrains.kotlin.konan.target.ClangArgs
|
||||
|
||||
@@ -34,7 +34,7 @@ dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$buildKotlinVersion"
|
||||
compile "org.jetbrains.kotlin:kotlin-compiler:$buildKotlinVersion"
|
||||
compile project(':Interop:Indexer')
|
||||
compile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
||||
compile kotlinNativeSharedModule
|
||||
}
|
||||
|
||||
compileKotlin {
|
||||
|
||||
@@ -111,6 +111,7 @@ configurations {
|
||||
kotlin_stdlib_jar
|
||||
kotlin_reflect_jar
|
||||
kotlin_script_runtime_jar
|
||||
kotlin_native_shared_jar
|
||||
kotlin_common_stdlib_src
|
||||
kotlin_test_common_src
|
||||
kotlin_test_annotations_common_src
|
||||
@@ -132,6 +133,7 @@ dependencies {
|
||||
kotlin_stdlib_jar "$kotlinStdLibModule@jar"
|
||||
kotlin_reflect_jar "$kotlinReflectModule@jar"
|
||||
kotlin_script_runtime_jar "$kotlinScriptRuntimeModule@jar"
|
||||
kotlin_native_shared_jar "$kotlinNativeSharedModule@jar"
|
||||
kotlin_common_stdlib_src kotlinCommonStdlibModule
|
||||
kotlin_test_common_src kotlinTestCommonModule
|
||||
kotlin_test_annotations_common_src kotlinTestAnnotationsCommonModule
|
||||
@@ -141,11 +143,11 @@ dependencies {
|
||||
compilerCompile kotlinCompilerModule
|
||||
compilerCompile kotlinNativeInterop['llvm'].configuration
|
||||
compilerCompile kotlinNativeInterop['hash'].configuration
|
||||
compilerCompile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
||||
compilerCompile kotlinNativeSharedModule
|
||||
compilerCompile "org.jetbrains.kotlin:konan.serializer:$konanVersion"
|
||||
|
||||
cli_bcCompile kotlinCompilerModule
|
||||
cli_bcCompile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
||||
cli_bcCompile kotlinNativeSharedModule
|
||||
cli_bcCompile sourceSets.compiler.output
|
||||
cli_bcCompile "org.jetbrains.kotlin:konan.serializer:$konanVersion"
|
||||
|
||||
@@ -268,7 +270,7 @@ jar {
|
||||
dependsOn ':runtime:hostRuntime', 'external_jars'
|
||||
}
|
||||
|
||||
def externalJars = ['compiler', 'stdlib', 'reflect', 'script_runtime']
|
||||
def externalJars = ['compiler', 'stdlib', 'reflect', 'script_runtime', 'native_shared']
|
||||
|
||||
task trove4jCopy(type: Copy) {
|
||||
from configurations.getByName("trove4j_jar") {
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.konan.CURRENT
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
|
||||
+1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.library.impl.buildLibrary
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.parseBitcodeFile
|
||||
import org.jetbrains.kotlin.konan.CURRENT
|
||||
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryVersioning
|
||||
|
||||
+3
-6
@@ -13,18 +13,15 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_W
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.konan.TempFiles
|
||||
import org.jetbrains.kotlin.konan.*
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibrary
|
||||
import org.jetbrains.kotlin.konan.library.defaultResolver
|
||||
import org.jetbrains.kotlin.konan.library.libraryResolver
|
||||
import org.jetbrains.kotlin.konan.properties.loadProperties
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.library.resolver.TopologicalLibraryOrder
|
||||
import org.jetbrains.kotlin.konan.library.toUnresolvedLibraries
|
||||
import org.jetbrains.kotlin.konan.parseKonanVersion
|
||||
|
||||
class KonanConfig(val project: Project, val configuration: CompilerConfiguration) {
|
||||
|
||||
@@ -89,8 +86,8 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
libraryNames.filter { it.contains(File.separator) },
|
||||
target,
|
||||
distribution,
|
||||
::resolverLogger,
|
||||
compatibleCompilerVersions = compatibleCompilerVersions
|
||||
compatibleCompilerVersions + KonanVersion.CURRENT,
|
||||
::resolverLogger
|
||||
).libraryResolver()
|
||||
|
||||
internal val resolvedLibraries by lazy {
|
||||
|
||||
+1
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.SourceManager.FileEntry
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
|
||||
import org.jetbrains.kotlin.konan.CURRENT
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
@@ -4,7 +4,7 @@ apply plugin: 'kotlin'
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$buildKotlinVersion"
|
||||
compile project(path: ':backend.native', configuration: 'cli_bc')
|
||||
compile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
||||
compile kotlinNativeSharedModule
|
||||
compile 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
|
||||
+14
-8
@@ -18,14 +18,16 @@ import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.konan.properties.*
|
||||
import org.jetbrains.kotlin.konan.util.*
|
||||
import org.jetbrains.kotlin.CopySamples
|
||||
import org.jetbrains.kotlin.konan.*
|
||||
|
||||
buildscript {
|
||||
apply from: "gradle/kotlinGradlePlugin.gradle"
|
||||
apply from: "gradle/kotlinNativeShared.gradle"
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
||||
classpath "org.jetbrains.kotlin:kotlin-native-version:$konanVersion"
|
||||
}
|
||||
}
|
||||
import org.jetbrains.kotlin.konan.*
|
||||
|
||||
// Allows generating wrappers for the root build and all the samples during execution of the default 'wrapper' task.
|
||||
// Run './gradlew wrapper --gradle-version <version>' to update all the wrappers.
|
||||
@@ -52,13 +54,14 @@ ext {
|
||||
kotlinTestAnnotationsCommonModule="org.jetbrains.kotlin:kotlin-test-annotations-common:${kotlinVersion}:sources"
|
||||
kotlinReflectModule="org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}"
|
||||
kotlinScriptRuntimeModule="org.jetbrains.kotlin:kotlin-script-runtime:${kotlinVersion}"
|
||||
kotlinNativeSharedModule="org.jetbrains.kotlin:kotlin-native-shared:$sharedVersion"
|
||||
|
||||
konanVersionFull = KonanVersion.Companion.CURRENT
|
||||
konanVersionFull = KonanVersionGeneratedKt.getCurrentKonanVersion()
|
||||
|
||||
if (konanVersionFull.meta == MetaVersion.RELEASE) {
|
||||
gradlePluginVersion = kotlinVersion
|
||||
} else {
|
||||
gradlePluginVersion = "$kotlinVersion-native-${KonanVersion.Companion.CURRENT.toString()}"
|
||||
gradlePluginVersion = "$kotlinVersion-native-${konanVersionFull.toString()}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +77,9 @@ allprojects {
|
||||
maven {
|
||||
url kotlinCompilerRepo
|
||||
}
|
||||
maven {
|
||||
url sharedRepo
|
||||
}
|
||||
}
|
||||
|
||||
setupHostAndTarget()
|
||||
@@ -189,8 +195,8 @@ class PlatformInfo {
|
||||
}
|
||||
}
|
||||
|
||||
task sharedJar {
|
||||
dependsOn gradle.includedBuild('kotlin-native-shared').task(':jar')
|
||||
task versionJar {
|
||||
dependsOn gradle.includedBuild('kotlin-native-version').task(':jar')
|
||||
}
|
||||
|
||||
task gradlePluginJar {
|
||||
@@ -221,7 +227,7 @@ task distCompiler(type: Copy) {
|
||||
dependsOn ':backend.native:jar'
|
||||
dependsOn ':utilities:jar'
|
||||
dependsOn ':klib:jar'
|
||||
dependsOn ':sharedJar'
|
||||
dependsOn ':versionJar'
|
||||
|
||||
destinationDir distDir
|
||||
|
||||
@@ -281,7 +287,7 @@ task distCompiler(type: Copy) {
|
||||
into('konan/lib')
|
||||
}
|
||||
|
||||
from(file("${gradle.includedBuild('kotlin-native-shared').projectDir}/build/libs")) {
|
||||
from(file("${gradle.includedBuild('kotlin-native-version').projectDir}/build/libs")) {
|
||||
into('konan/lib')
|
||||
}
|
||||
|
||||
|
||||
+10
-1
@@ -29,6 +29,15 @@ allprojects {
|
||||
url 'https://cache-redirector.jetbrains.com/maven-central'
|
||||
}
|
||||
|
||||
maven { url "https://kotlin.bintray.com/kotlinx" }
|
||||
maven {
|
||||
url "https://kotlin.bintray.com/kotlinx"
|
||||
}
|
||||
maven {
|
||||
url sharedRepo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
runtime project(':plugins')
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
apply plugin: 'groovy'
|
||||
apply plugin: 'kotlin'
|
||||
|
||||
buildscript {
|
||||
ext.rootBuildDirectory = "$rootDir/.."
|
||||
@@ -37,9 +38,7 @@ dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$buildKotlinVersion"
|
||||
compile "org.jetbrains.kotlin:kotlin-reflect:$buildKotlinVersion"
|
||||
compile group: 'com.ullink.slack', name: 'simpleslackapi', version: '0.6.0'
|
||||
// An artifact from the included build 'shared' cannot be used here due to https://github.com/gradle/gradle/issues/3768
|
||||
// TODO: Remove this hack when the bug is fixed
|
||||
compile project(':shared')
|
||||
compile "org.jetbrains.kotlin:kotlin-native-shared:$sharedVersion"
|
||||
compile "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.10.0"
|
||||
}
|
||||
|
||||
|
||||
@@ -14,5 +14,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
include 'shared'
|
||||
include 'plugins'
|
||||
|
||||
@@ -1,45 +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.
|
||||
*/
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
gradleProperties = new Properties()
|
||||
gradleProperties.load(new FileInputStream("$projectDir/../../gradle.properties"))
|
||||
buildKotlinVersion = gradleProperties."buildKotlinVersion"
|
||||
buildKotlinCompilerRepo = gradleProperties."buildKotlinCompilerRepo"
|
||||
|
||||
}
|
||||
|
||||
apply from: '../../gradle/kotlinGradlePlugin.gradle'
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin'
|
||||
|
||||
// We reuse the source code from the Project in buildSrc.
|
||||
sourceSets.main.kotlin.srcDirs = ["$projectDir/../../shared/src/main/kotlin"]
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url buildKotlinCompilerRepo
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$buildKotlinVersion"
|
||||
}
|
||||
|
||||
rootProject.dependencies {
|
||||
runtime project(path)
|
||||
}
|
||||
+3
-2
@@ -85,13 +85,14 @@ KOTLIN_SCRIPT_RUNTIME_JAR="${KONAN_HOME}/konan/lib/kotlin-script-runtime.jar"
|
||||
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"
|
||||
SHARED_JAR="${KONAN_HOME}/konan/lib/shared.jar"
|
||||
SHARED_JAR="${KONAN_HOME}/konan/lib/kotlin-native-shared.jar"
|
||||
EXTRACTED_METADATA_JAR="${KONAN_HOME}/konan/lib/konan.metadata.jar"
|
||||
EXTRACTED_SERIALIZER_JAR="${KONAN_HOME}/konan/lib/konan.serializer.jar"
|
||||
KLIB_JAR="${KONAN_HOME}/konan/lib/klib.jar"
|
||||
UTILITIES_JAR="${KONAN_HOME}/konan/lib/utilities.jar"
|
||||
TROVE_JAR="${KONAN_HOME}/konan/lib/trove4j.jar"
|
||||
KONAN_CLASSPATH="$KOTLIN_JAR:$KOTLIN_STDLIB_JAR:$KOTLIN_REFLECT_JAR:$KOTLIN_SCRIPT_RUNTIME_JAR:$INTEROP_JAR:$STUB_GENERATOR_JAR:$INTEROP_INDEXER_JAR:$KONAN_JAR:$KLIB_JAR:$UTILITIES_JAR:$SHARED_JAR:$EXTRACTED_METADATA_JAR:$EXTRACTED_SERIALIZER_JAR:$TROVE_JAR"
|
||||
VERSION_JAR="${KONAN_HOME}/konan/lib/version.jar"
|
||||
KONAN_CLASSPATH="$KOTLIN_JAR:$KOTLIN_STDLIB_JAR:$KOTLIN_REFLECT_JAR:$KOTLIN_SCRIPT_RUNTIME_JAR:$INTEROP_JAR:$STUB_GENERATOR_JAR:$INTEROP_INDEXER_JAR:$KONAN_JAR:$KLIB_JAR:$UTILITIES_JAR:$SHARED_JAR:$EXTRACTED_METADATA_JAR:$EXTRACTED_SERIALIZER_JAR:$TROVE_JAR:$VERSION_JAR"
|
||||
TOOL_CLASS=org.jetbrains.kotlin.cli.utilities.MainKt
|
||||
|
||||
LIBCLANG_DISABLE_CRASH_RECOVERY=1 \
|
||||
|
||||
+3
-2
@@ -54,7 +54,7 @@ if not "!ARG!" == "" (
|
||||
set "NATIVE_LIB=%_KONAN_HOME%\konan\nativelib"
|
||||
set "KONAN_LIB=%_KONAN_HOME%\konan\lib"
|
||||
|
||||
set "SHARED_JAR=%KONAN_LIB%\shared.jar"
|
||||
set "SHARED_JAR=%KONAN_LIB%\kotlin-native-shared.jar"
|
||||
set "EXTRACTED_METADATA_JAR=%KONAN_LIB%\konan.metadata.jar"
|
||||
set "EXTRACTED_SERIALIZER_JAR=%KONAN_LIB%\konan.serializer.jar"
|
||||
set "INTEROP_INDEXER_JAR=%KONAN_LIB%\Indexer.jar"
|
||||
@@ -68,8 +68,9 @@ set "KOTLIN_SCRIPT_RUNTIME_JAR=%KONAN_LIB%\kotlin-script-runtime.jar"
|
||||
set "STUB_GENERATOR_JAR=%KONAN_LIB%\StubGenerator.jar"
|
||||
set "UTILITIES_JAR=%KONAN_LIB%\utilities.jar"
|
||||
set TROVE_JAR="%KONAN_LIB%\lib\trove4j.jar"
|
||||
set "VERSION_JAR=%KONAN_LIB%\version.jar"
|
||||
|
||||
set "KONAN_CLASSPATH=%KOTLIN_JAR%;%KOTLIN_STDLIB_JAR%;%KOTLIN_REFLECT_JAR%;%KOTLIN_SCRIPT_RUNTIME_JAR%;%INTEROP_RUNTIME_JAR%;%KONAN_JAR%;%STUB_GENERATOR_JAR%;%INTEROP_INDEXER_JAR%;%SHARED_JAR%;%EXTRACTED_METADATA_JAR%;%EXTRACTED_SERIALIZER_JAR%;%KLIB_JAR%;%UTILITIES_JAR%;%TROVE_JAR%"
|
||||
set "KONAN_CLASSPATH=%KOTLIN_JAR%;%KOTLIN_STDLIB_JAR%;%KOTLIN_REFLECT_JAR%;%KOTLIN_SCRIPT_RUNTIME_JAR%;%INTEROP_RUNTIME_JAR%;%KONAN_JAR%;%STUB_GENERATOR_JAR%;%INTEROP_INDEXER_JAR%;%SHARED_JAR%;%EXTRACTED_METADATA_JAR%;%EXTRACTED_SERIALIZER_JAR%;%KLIB_JAR%;%UTILITIES_JAR%;%TROVE_JAR%;%VERSION_JAR%"
|
||||
|
||||
set JAVA_OPTS=-ea ^
|
||||
-Xmx3G ^
|
||||
|
||||
@@ -33,11 +33,15 @@ repositories {
|
||||
maven {
|
||||
url buildKotlinCompilerRepo
|
||||
}
|
||||
maven {
|
||||
url sharedRepo
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$buildKotlinVersion"
|
||||
compile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
||||
compile "org.jetbrains.kotlin:kotlin-native-shared:$sharedVersion"
|
||||
compile "org.jetbrains.kotlin:kotlin-native-version"
|
||||
compile "org.jetbrains.kotlin:kotlin-compiler:$kotlinVersion"
|
||||
compile "org.jetbrains.kotlin:konan.metadata:$konanVersion"
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ remoteRoot=konan_tests
|
||||
kotlinCompilerRepo=https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_dev_CompilerAllPlugins),number:1.3.40-dev-392,branch:default:true,pinned:true/artifacts/content/maven
|
||||
kotlinVersion=1.3.40-dev-392
|
||||
testKotlinVersion=1.3.40-dev-392
|
||||
sharedRepo=https://teamcity.jetbrains.com/guestAuth/repository/download/Kotlin_KotlinNativeShared_BuildAndTest/2051827:id/maven
|
||||
sharedVersion=1.2.0
|
||||
konanVersion=1.3.0
|
||||
org.gradle.jvmargs='-Dfile.encoding=UTF-8'
|
||||
org.gradle.workers.max=4
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
if (!hasProperty('sharedVersion')) {
|
||||
throw new GradleException('Please ensure the "sharedVersion" property is defined before applying this script.')
|
||||
}
|
||||
|
||||
if (!hasProperty('sharedRepo')) {
|
||||
throw new GradleException('Please ensure the "sharedRepo" property is defined before applying this script.')
|
||||
}
|
||||
|
||||
project.buildscript {
|
||||
repositories {
|
||||
maven { url sharedRepo }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-native-shared:$sharedVersion"
|
||||
// An included build with generated Kotlin/Native version.
|
||||
classpath "org.jetbrains.kotlin:kotlin-native-version"
|
||||
}
|
||||
}
|
||||
@@ -20,10 +20,10 @@ buildscript {
|
||||
ext.rootBuildDirectory = file('..')
|
||||
|
||||
apply from: "$rootBuildDirectory/gradle/kotlinGradlePlugin.gradle"
|
||||
apply from: "$rootBuildDirectory/gradle/kotlinNativeShared.gradle"
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-stdlib:$buildKotlinVersion"
|
||||
classpath "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
||||
}
|
||||
}
|
||||
import org.jetbrains.kotlin.konan.target.ClangArgs
|
||||
|
||||
@@ -17,16 +17,8 @@
|
||||
apply plugin: "cpp"
|
||||
apply plugin: "c"
|
||||
|
||||
buildscript {
|
||||
ext.rootBuildDirectory = file('..')
|
||||
apply from: "${rootProject.projectDir}/gradle/kotlinGradlePlugin.gradle"
|
||||
|
||||
apply from: "$rootBuildDirectory/gradle/kotlinGradlePlugin.gradle"
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-stdlib:$buildKotlinVersion"
|
||||
classpath "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
||||
}
|
||||
}
|
||||
import org.jetbrains.kotlin.konan.target.ClangArgs
|
||||
|
||||
model {
|
||||
|
||||
@@ -21,10 +21,10 @@ buildscript {
|
||||
ext.rootBuildDirectory = file('..')
|
||||
|
||||
apply from: "$rootBuildDirectory/gradle/kotlinGradlePlugin.gradle"
|
||||
apply from: "$rootBuildDirectory/gradle/kotlinNativeShared.gradle"
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-stdlib:$buildKotlinVersion"
|
||||
classpath "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
||||
}
|
||||
}
|
||||
import org.jetbrains.kotlin.konan.target.ClangArgs
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ include ':utilities'
|
||||
//include ':tools:benchmarksAnalyzer'
|
||||
include ':platformLibs'
|
||||
|
||||
includeBuild 'shared'
|
||||
includeBuild 'version'
|
||||
includeBuild 'extracted/konan.metadata'
|
||||
includeBuild 'extracted/konan.serializer'
|
||||
includeBuild 'tools/kotlin-native-gradle-plugin'
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
package org.jetbrains.kotlin
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.tasks.*
|
||||
import java.io.File
|
||||
|
||||
|
||||
open class VersionGenerator: DefaultTask() {
|
||||
@OutputDirectory
|
||||
val versionSourceDirectory = project.file("build/generated")
|
||||
@OutputFile
|
||||
val versionFile:File = project.file("${versionSourceDirectory.path}/org/jetbrains/kotlin/konan/KonanVersion.kt")
|
||||
|
||||
val konanVersion: String
|
||||
@Input get() = project.properties["konanVersion"].toString()
|
||||
|
||||
val buildNumber: String?
|
||||
// TeamCity passes all configuration parameters into a build script as project properties.
|
||||
// Thus we can use them here instead of environment variables.
|
||||
@Optional @Input get() = project.findProperty("build.number")?.toString()
|
||||
|
||||
val meta: String
|
||||
@Input get() = project.properties["konanMetaVersion"]?.let {
|
||||
"MetaVersion.${it.toString().toUpperCase()}"
|
||||
} ?: "MetaVersion.DEV"
|
||||
|
||||
|
||||
override fun configure(closure: Closure<*>): Task {
|
||||
val result = super.configure(closure)
|
||||
doFirst {
|
||||
val content = buildString {
|
||||
operator fun String.unaryPlus() = this@buildString.append(this)
|
||||
val version = konanVersion.split(".")
|
||||
val major = version[0].toInt()
|
||||
val minor = version[1].toInt()
|
||||
val maintenance = if (version.size > 2) version[2].toInt() else 0
|
||||
project.logger.info("BUILD_NUMBER: $buildNumber")
|
||||
val build = buildNumber?.let {
|
||||
it.split("-")[2].toInt() //7-dev-buildcount
|
||||
}?: -1
|
||||
|
||||
+ """
|
||||
|package org.jetbrains.kotlin.konan
|
||||
|
|
||||
|import java.io.Serializable
|
||||
|
|
||||
|interface KonanVersion : Serializable {
|
||||
| val meta: MetaVersion
|
||||
| val major: Int
|
||||
| val minor: Int
|
||||
| val maintenance: Int
|
||||
| val build: Int
|
||||
|
|
||||
| fun toString(showMeta: Boolean, showBuild: Boolean): String
|
||||
|
|
||||
| companion object {
|
||||
| val CURRENT = KonanVersionImpl($meta, $major, $minor, $maintenance, $build)
|
||||
| }
|
||||
|}
|
||||
|
|
||||
|data class KonanVersionImpl(
|
||||
| override val meta: MetaVersion = MetaVersion.DEV,
|
||||
| override val major: Int,
|
||||
| override val minor: Int,
|
||||
| override val maintenance: Int,
|
||||
| override val build: Int
|
||||
|) : KonanVersion {
|
||||
|
|
||||
| override fun toString(showMeta: Boolean, showBuild: Boolean) = buildString {
|
||||
| append(major)
|
||||
| append('.')
|
||||
| append(minor)
|
||||
| if (maintenance != 0) {
|
||||
| append('.')
|
||||
| append(maintenance)
|
||||
| }
|
||||
| if (showMeta) {
|
||||
| append('-')
|
||||
| append(meta.metaString)
|
||||
| }
|
||||
| if (showBuild && build != -1) {
|
||||
| append('-')
|
||||
| append(build)
|
||||
| }
|
||||
| }
|
||||
|
|
||||
| private val isRelease: Boolean
|
||||
| get() = meta == MetaVersion.RELEASE
|
||||
|
|
||||
| private val versionString by lazy { toString(!isRelease, !isRelease) }
|
||||
|
|
||||
| override fun toString() = versionString
|
||||
|}
|
||||
|fun String.parseKonanVersion(): KonanVersion {
|
||||
| val (major, minor, maintenance, meta, build) =
|
||||
| Regex(""${'"'}([0-9]+)\.([0-9]+)(?:\.([0-9]+))?(?:-(\p{Alpha}\p{Alnum}*))?(?:-([0-9]+))?""${'"'})
|
||||
| .matchEntire(this)!!.destructured
|
||||
| return KonanVersionImpl(
|
||||
| MetaVersion.findAppropriate(meta),
|
||||
| major.toInt(),
|
||||
| minor.toInt(),
|
||||
| maintenance.toIntOrNull() ?: 0,
|
||||
| build.toIntOrNull() ?: -1)
|
||||
|}
|
||||
""".trimMargin()
|
||||
}
|
||||
versionFile.printWriter().use {
|
||||
it.println(content)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
rootProject.name = "kotlin-native-shared"
|
||||
@@ -1,73 +0,0 @@
|
||||
package org.jetbrains.kotlin.konan.library
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
import org.jetbrains.kotlin.konan.properties.propertyList
|
||||
|
||||
const val KLIB_PROPERTY_ABI_VERSION = "abi_version"
|
||||
const val KLIB_PROPERTY_COMPILER_VERSION = "compiler_version"
|
||||
const val KLIB_PROPERTY_DEPENDENCY_VERSION = "dependency_version"
|
||||
const val KLIB_PROPERTY_LIBRARY_VERSION = "library_version"
|
||||
const val KLIB_PROPERTY_UNIQUE_NAME = "unique_name"
|
||||
const val KLIB_PROPERTY_LINKED_OPTS = "linkerOpts"
|
||||
const val KLIB_PROPERTY_DEPENDS = "depends"
|
||||
const val KLIB_PROPERTY_INTEROP = "interop"
|
||||
const val KLIB_PROPERTY_PACKAGE = "package"
|
||||
const val KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS = "exportForwardDeclarations"
|
||||
const val KLIB_PROPERTY_INCLUDED_HEADERS = "includedHeaders"
|
||||
|
||||
/**
|
||||
* An abstraction for getting access to the information stored inside of Kotlin/Native library.
|
||||
*/
|
||||
interface KonanLibrary {
|
||||
|
||||
val libraryName: String
|
||||
val libraryFile: File
|
||||
|
||||
// Whether this library is default (provided by Kotlin/Native distribution)?
|
||||
val isDefault: Boolean
|
||||
|
||||
// Properties:
|
||||
val manifestProperties: Properties
|
||||
val linkerOpts: List<String>
|
||||
|
||||
// Paths:
|
||||
val bitcodePaths: List<String>
|
||||
val includedPaths: List<String>
|
||||
|
||||
val targetList: List<String>
|
||||
val versions: KonanLibraryVersioning
|
||||
|
||||
val dataFlowGraph: ByteArray?
|
||||
val moduleHeaderData: ByteArray
|
||||
fun packageMetadataParts(fqName: String): Set<String>
|
||||
fun packageMetadata(fqName: String, partName: String): ByteArray
|
||||
|
||||
val irHeader: ByteArray?
|
||||
fun irDeclaration(index: Long, isLocal: Boolean): ByteArray
|
||||
}
|
||||
|
||||
val KonanLibrary.uniqueName
|
||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_UNIQUE_NAME)!!
|
||||
|
||||
val KonanLibrary.unresolvedDependencies: List<UnresolvedLibrary>
|
||||
get() = manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS)
|
||||
.map {
|
||||
UnresolvedLibrary(it, manifestProperties.getProperty("dependency_version_$it"))
|
||||
}
|
||||
|
||||
val KonanLibrary.isInterop
|
||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_INTEROP) == "true"
|
||||
|
||||
val KonanLibrary.packageFqName
|
||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_PACKAGE)
|
||||
|
||||
val KonanLibrary.exportForwardDeclarations
|
||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS)
|
||||
.split(' ').asSequence()
|
||||
.map { it.trim() }
|
||||
.filter { it.isNotEmpty() }
|
||||
.toList()
|
||||
|
||||
val KonanLibrary.includedHeaders
|
||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_INCLUDED_HEADERS).split(' ')
|
||||
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
* Copyright 2010-2019 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.library
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
|
||||
/**
|
||||
* This scheme describes the Kotlin/Native Library (KLIB) layout.
|
||||
*/
|
||||
interface KonanLibraryLayout {
|
||||
|
||||
val libraryName: String
|
||||
|
||||
val libDir: File
|
||||
val target: KonanTarget?
|
||||
// This is a default implementation. Can't make it an assignment.
|
||||
get() = null
|
||||
|
||||
val manifestFile
|
||||
get() = File(libDir, "manifest")
|
||||
val resourcesDir
|
||||
get() = File(libDir, "resources")
|
||||
|
||||
val targetsDir
|
||||
get() = File(libDir, "targets")
|
||||
val targetDir
|
||||
get() = File(targetsDir, target!!.visibleName)
|
||||
|
||||
val kotlinDir
|
||||
get() = File(targetDir, "kotlin")
|
||||
val nativeDir
|
||||
get() = File(targetDir, "native")
|
||||
val includedDir
|
||||
get() = File(targetDir, "included")
|
||||
|
||||
val linkdataDir
|
||||
get() = File(libDir, "linkdata")
|
||||
val moduleHeaderFile
|
||||
get() = File(linkdataDir, "module")
|
||||
val dataFlowGraphFile
|
||||
get() = File(linkdataDir, "module_data_flow_graph")
|
||||
|
||||
fun packageFragmentsDir(packageName: String)
|
||||
= File(linkdataDir, if (packageName == "") "root_package" else "package_$packageName")
|
||||
|
||||
fun packageFragmentFile(packageFqName: String, partName: String) =
|
||||
File(packageFragmentsDir(packageFqName), "$partName$KLIB_METADATA_FILE_EXTENSION_WITH_DOT")
|
||||
val irDir
|
||||
get() = File(libDir, "ir")
|
||||
val irFile
|
||||
get() = File(irDir, "irCombined.knd")
|
||||
val irHeader
|
||||
get() = File(irDir, "irHeaders.kni")
|
||||
val irIndex: File
|
||||
get() = File(irDir, "uniqIdTableDump.txt")
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package org.jetbrains.kotlin.konan.library
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.file.file
|
||||
import org.jetbrains.kotlin.konan.file.withMutableZipFileSystem
|
||||
import org.jetbrains.kotlin.konan.library.impl.DefaultMetadataReaderImpl
|
||||
import org.jetbrains.kotlin.konan.library.impl.KonanLibraryImpl
|
||||
import org.jetbrains.kotlin.konan.library.impl.zippedKonanLibraryChecks
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
|
||||
const val KLIB_FILE_EXTENSION = "klib"
|
||||
const val KLIB_FILE_EXTENSION_WITH_DOT = ".$KLIB_FILE_EXTENSION"
|
||||
|
||||
const val KLIB_METADATA_FILE_EXTENSION = "knm"
|
||||
const val KLIB_METADATA_FILE_EXTENSION_WITH_DOT = ".$KLIB_METADATA_FILE_EXTENSION"
|
||||
|
||||
fun File.unpackZippedKonanLibraryTo(newDir: File) {
|
||||
|
||||
// First, run validity checks for the given KLIB file.
|
||||
zippedKonanLibraryChecks(this)
|
||||
|
||||
if (newDir.exists) {
|
||||
if (newDir.isDirectory)
|
||||
newDir.deleteRecursively()
|
||||
else
|
||||
newDir.delete()
|
||||
}
|
||||
|
||||
this.withMutableZipFileSystem {
|
||||
it.file("/").recursiveCopyTo(newDir)
|
||||
}
|
||||
check(newDir.exists) { "Could not unpack $this as $newDir." }
|
||||
}
|
||||
|
||||
val List<String>.toUnresolvedLibraries
|
||||
get() = this.map {
|
||||
|
||||
val version = it.substringAfterLast('@', "")
|
||||
.let { if (it.isEmpty()) null else it}
|
||||
val name = it.substringBeforeLast('@')
|
||||
UnresolvedLibrary(name, version)
|
||||
}
|
||||
|
||||
fun createKonanLibrary(
|
||||
libraryFile: File,
|
||||
target: KonanTarget? = null,
|
||||
isDefault: Boolean = false,
|
||||
metadataReader: MetadataReader = DefaultMetadataReaderImpl
|
||||
): KonanLibrary = KonanLibraryImpl(libraryFile, target, isDefault, metadataReader)
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
package org.jetbrains.kotlin.konan.library
|
||||
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.parseKonanVersion
|
||||
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
import org.jetbrains.kotlin.konan.parseKonanAbiVersion
|
||||
|
||||
|
||||
data class KonanLibraryVersioning(
|
||||
val libraryVersion: String?,
|
||||
val compilerVersion: KonanVersion?,
|
||||
val abiVersion: KonanAbiVersion?
|
||||
)
|
||||
|
||||
fun Properties.writeKonanLibraryVersioning(versions: KonanLibraryVersioning) {
|
||||
versions.abiVersion ?. let { this.setProperty(KLIB_PROPERTY_ABI_VERSION, it.toString()) }
|
||||
versions.libraryVersion ?. let { this.setProperty(KLIB_PROPERTY_LIBRARY_VERSION, it) }
|
||||
versions.compilerVersion ?. let { this.setProperty(KLIB_PROPERTY_COMPILER_VERSION, "${versions.compilerVersion.toString(true, true)}") }
|
||||
}
|
||||
|
||||
fun Properties.readKonanLibraryVersioning(): KonanLibraryVersioning {
|
||||
val abiVersion = this.getProperty(KLIB_PROPERTY_ABI_VERSION)?.parseKonanAbiVersion()
|
||||
val libraryVersion = this.getProperty(KLIB_PROPERTY_LIBRARY_VERSION)
|
||||
val compilerVersion = this.getProperty(KLIB_PROPERTY_COMPILER_VERSION)?.parseKonanVersion()
|
||||
|
||||
return KonanLibraryVersioning(abiVersion = abiVersion, libraryVersion = libraryVersion, compilerVersion = compilerVersion)
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package org.jetbrains.kotlin.konan.library
|
||||
|
||||
interface MetadataReader {
|
||||
fun loadSerializedModule(libraryLayout: KonanLibraryLayout): ByteArray
|
||||
fun loadSerializedPackageFragment(libraryLayout: KonanLibraryLayout, fqName: String, partName: String): ByteArray
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
package org.jetbrains.kotlin.konan.library
|
||||
|
||||
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.library.impl.KonanLibraryImpl
|
||||
import org.jetbrains.kotlin.konan.target.Distribution
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.util.*
|
||||
|
||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove the constants below:
|
||||
const val KONAN_STDLIB_NAME = "stdlib"
|
||||
|
||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove this interface!
|
||||
interface SearchPathResolver : WithLogger {
|
||||
val searchRoots: List<File>
|
||||
fun resolutionSequence(givenPath: String): Sequence<File>
|
||||
fun resolve(unresolved: UnresolvedLibrary, isDefaultLink: Boolean = false): KonanLibraryImpl
|
||||
fun resolve(givenPath: String): KonanLibraryImpl
|
||||
fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean): List<KonanLibraryImpl>
|
||||
}
|
||||
|
||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove this interface!
|
||||
interface SearchPathResolverWithTarget: SearchPathResolver {
|
||||
val target: KonanTarget
|
||||
val knownAbiVersions: List<KonanAbiVersion>?
|
||||
val knownCompilerVersions: List<KonanVersion>?
|
||||
}
|
||||
|
||||
fun defaultResolver(
|
||||
repositories: List<String>,
|
||||
target: KonanTarget,
|
||||
distribution: Distribution = Distribution()
|
||||
): SearchPathResolverWithTarget = defaultResolver(repositories, emptyList(), target, distribution)
|
||||
|
||||
fun defaultResolver(
|
||||
repositories: List<String>,
|
||||
directLibs: List<String>,
|
||||
target: KonanTarget,
|
||||
distribution: Distribution,
|
||||
logger: Logger = ::dummyLogger,
|
||||
skipCurrentDir: Boolean = false,
|
||||
compatibleCompilerVersions: List<KonanVersion> = emptyList()
|
||||
): SearchPathResolverWithTarget = KonanLibraryProperResolver(
|
||||
repositories,
|
||||
directLibs,
|
||||
target,
|
||||
listOf(KonanAbiVersion.CURRENT),
|
||||
listOf(KonanVersion.CURRENT) + compatibleCompilerVersions,
|
||||
distribution.klib,
|
||||
distribution.localKonanDir.absolutePath,
|
||||
skipCurrentDir,
|
||||
logger)
|
||||
|
||||
fun resolverByName(
|
||||
repositories: List<String>,
|
||||
directLibs: List<String> = emptyList(),
|
||||
distributionKlib: String? = null,
|
||||
localKonanDir: String? = null,
|
||||
skipCurrentDir: Boolean = false
|
||||
): SearchPathResolver = KonanLibrarySearchPathResolver(repositories, directLibs, distributionKlib, localKonanDir, skipCurrentDir)
|
||||
|
||||
internal open class KonanLibrarySearchPathResolver(
|
||||
repositories: List<String>,
|
||||
directLibs: List<String>,
|
||||
val distributionKlib: String?,
|
||||
val localKonanDir: String?,
|
||||
val skipCurrentDir: Boolean,
|
||||
override val logger:Logger = ::dummyLogger
|
||||
) : SearchPathResolver {
|
||||
|
||||
val localHead: File?
|
||||
get() = localKonanDir?.File()?.klib
|
||||
|
||||
val distHead: File?
|
||||
get() = distributionKlib?.File()?.child("common")
|
||||
|
||||
open val distPlatformHead: File? = null
|
||||
|
||||
val currentDirHead: File?
|
||||
get() = if (!skipCurrentDir) File.userDir else null
|
||||
|
||||
private val repoRoots: List<File> by lazy { repositories.map { File(it) } }
|
||||
|
||||
private val directLibraries: List<KonanLibrary> by lazy {
|
||||
directLibs.mapNotNull { found(File(it)) }.map { createKonanLibrary(it, null) }
|
||||
}
|
||||
|
||||
// This is the place where we specify the order of library search.
|
||||
override val searchRoots: List<File> by lazy {
|
||||
(listOf(currentDirHead) + repoRoots + listOf(localHead, distHead, distPlatformHead)).filterNotNull()
|
||||
}
|
||||
|
||||
private fun found(candidate: File): File? {
|
||||
fun check(file: File): Boolean =
|
||||
file.exists && (file.isFile || File(file, "manifest").exists)
|
||||
|
||||
val noSuffix = File(candidate.path.removeSuffixIfPresent(KLIB_FILE_EXTENSION_WITH_DOT))
|
||||
val withSuffix = File(candidate.path.suffixIfNot(KLIB_FILE_EXTENSION_WITH_DOT))
|
||||
return when {
|
||||
check(withSuffix) -> withSuffix
|
||||
check(noSuffix) -> noSuffix
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override fun resolutionSequence(givenPath: String): Sequence<File> {
|
||||
val given = File(givenPath)
|
||||
val sequence = if (given.isAbsolute) {
|
||||
sequenceOf(found(given))
|
||||
} else {
|
||||
// Search among user-provided libraries by unique name.
|
||||
// It's a workaround for maven publication. When a library is published without Gradle metadata,
|
||||
// it has a complex file name (e.g. foo-macos_x64-1.0.klib). But a dependency on this lib in manifests
|
||||
// of other libs uses its unique name written in the manifest (i.e just 'foo'). So we cannot resolve this
|
||||
// library by its filename. But we have this library's file (we've downloaded it using maven dependency
|
||||
// resolution) so we can pass it to the compiler directly. This code takes this into account and looks for
|
||||
// a library dependencies also in libs passed to the compiler as files (passed to the resolver as the
|
||||
// 'directLibraries' property).
|
||||
val directLibs = directLibraries.asSequence().filter {
|
||||
it.uniqueName == givenPath
|
||||
}.map {
|
||||
it.libraryFile
|
||||
}
|
||||
// Search among libraries in repositoreis by library filename.
|
||||
val repoLibs = searchRoots.asSequence().map {
|
||||
found(File(it, givenPath))
|
||||
}
|
||||
directLibs + repoLibs
|
||||
}
|
||||
return sequence.filterNotNull()
|
||||
}
|
||||
|
||||
override fun resolve(unresolved: UnresolvedLibrary, isDefaultLink: Boolean): KonanLibraryImpl {
|
||||
val givenPath = unresolved.path
|
||||
return resolutionSequence(givenPath).firstOrNull() ?. let {
|
||||
createKonanLibrary(it, null, isDefaultLink) as KonanLibraryImpl
|
||||
} ?: error("Could not find \"$givenPath\" in ${searchRoots.map { it.absolutePath }}.")
|
||||
}
|
||||
|
||||
override fun resolve(givenPath: String) = resolve(UnresolvedLibrary(givenPath, null), false)
|
||||
|
||||
|
||||
private val File.klib
|
||||
get() = File(this, "klib")
|
||||
|
||||
// The libraries from the default root are linked automatically.
|
||||
val defaultRoots: List<File>
|
||||
get() = listOfNotNull(distHead, distPlatformHead).filter { it.exists }
|
||||
|
||||
override fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean): List<KonanLibraryImpl> {
|
||||
|
||||
val result = mutableListOf<KonanLibraryImpl>()
|
||||
|
||||
if (!noStdLib) {
|
||||
result.add(resolve(UnresolvedLibrary(KONAN_STDLIB_NAME, null), true))
|
||||
}
|
||||
|
||||
if (!noDefaultLibs) {
|
||||
val defaultLibs = defaultRoots.flatMap { it.listFiles }
|
||||
.filterNot { it.name.removeSuffixIfPresent(KLIB_FILE_EXTENSION_WITH_DOT) == KONAN_STDLIB_NAME }
|
||||
.map { UnresolvedLibrary(it.absolutePath, null) }
|
||||
.map {resolve(it, isDefaultLink = true) }
|
||||
result.addAll(defaultLibs)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
internal class KonanLibraryProperResolver(
|
||||
repositories: List<String>,
|
||||
directLibs: List<String>,
|
||||
override val target: KonanTarget,
|
||||
override val knownAbiVersions: List<KonanAbiVersion>?,
|
||||
override val knownCompilerVersions: List<KonanVersion>?,
|
||||
distributionKlib: String?,
|
||||
localKonanDir: String?,
|
||||
skipCurrentDir: Boolean,
|
||||
override val logger: Logger = ::dummyLogger
|
||||
) : KonanLibrarySearchPathResolver(repositories, directLibs, distributionKlib, localKonanDir, skipCurrentDir, logger),
|
||||
SearchPathResolverWithTarget
|
||||
{
|
||||
override val distPlatformHead: File?
|
||||
get() = distributionKlib?.File()?.child("platform")?.child(target.visibleName)
|
||||
|
||||
override fun resolve(unresolved: UnresolvedLibrary, isDefaultLink: Boolean): KonanLibraryImpl {
|
||||
val givenPath = unresolved.path
|
||||
val fileSequence = resolutionSequence(givenPath)
|
||||
val matching = fileSequence.map { createKonanLibrary(it, target, isDefaultLink) as KonanLibraryImpl }
|
||||
.map { it.takeIf { libraryMatch(it, unresolved) } }
|
||||
.filterNotNull()
|
||||
|
||||
return matching.firstOrNull() ?: error("Could not find \"$givenPath\" in ${searchRoots.map { it.absolutePath }}.")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun SearchPathResolverWithTarget.libraryMatch(candidate: KonanLibraryImpl, unresolved: UnresolvedLibrary): Boolean {
|
||||
val resolverTarget = this.target
|
||||
val candidatePath = candidate.libraryFile.absolutePath
|
||||
|
||||
val candidateCompilerVersion = candidate.versions.compilerVersion
|
||||
val candidateAbiVersion = candidate.versions.abiVersion
|
||||
val candidateLibraryVersion = candidate.versions.libraryVersion
|
||||
|
||||
if (!candidate.targetList.contains(resolverTarget.visibleName)) {
|
||||
logger("skipping $candidatePath. The target doesn't match. Expected '$resolverTarget', found ${candidate.targetList}")
|
||||
return false
|
||||
}
|
||||
|
||||
val abiVersionMatch = candidateAbiVersion != null &&
|
||||
knownAbiVersions != null &&
|
||||
knownAbiVersions!!.contains(candidateAbiVersion)
|
||||
|
||||
val compilerVersionMatch = candidateCompilerVersion != null &&
|
||||
knownCompilerVersions != null &&
|
||||
knownCompilerVersions!!.any { it.compatible(candidateCompilerVersion) }
|
||||
|
||||
if (!abiVersionMatch && !compilerVersionMatch) {
|
||||
logger("skipping $candidatePath. The abi versions don't match. Expected '${knownAbiVersions}', found '${candidateAbiVersion}'")
|
||||
|
||||
if (knownCompilerVersions != null) {
|
||||
val expected = knownCompilerVersions?.map { it.toString(false, false) }
|
||||
val found = candidateCompilerVersion?.toString(true, true)
|
||||
logger("The compiler versions don't match either. Expected '${expected}', found '${found}'")
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
if (candidateLibraryVersion != unresolved.libraryVersion &&
|
||||
candidateLibraryVersion != null &&
|
||||
unresolved.libraryVersion != null) {
|
||||
logger("skipping $candidatePath. The library versions don't match. Expected '${unresolved.libraryVersion}', found '${candidateLibraryVersion}'")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun KonanVersion.compatible(other: KonanVersion) =
|
||||
this.major == other.major
|
||||
&& this.minor == other.minor
|
||||
&& this.maintenance == other.maintenance
|
||||
@@ -1,10 +0,0 @@
|
||||
package org.jetbrains.kotlin.konan.library
|
||||
|
||||
data class UnresolvedLibrary(
|
||||
val path: String,
|
||||
val libraryVersion: String?) {
|
||||
|
||||
fun substitutePath(newPath: String): UnresolvedLibrary {
|
||||
return UnresolvedLibrary(newPath, libraryVersion)
|
||||
}
|
||||
}
|
||||
-94
@@ -1,94 +0,0 @@
|
||||
/**
|
||||
* Copyright 2010-2019 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.library.impl
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import java.io.RandomAccessFile
|
||||
import java.nio.channels.FileChannel
|
||||
|
||||
data class DeclarationId(val id: Long, val isLocal: Boolean)
|
||||
|
||||
class CombinedIrFileReader(file: File) {
|
||||
private val buffer = file.map(FileChannel.MapMode.READ_ONLY)
|
||||
private val declarationToOffsetSize = mutableMapOf<DeclarationId, Pair<Int, Int>>()
|
||||
|
||||
init {
|
||||
val declarationsCount = buffer.int
|
||||
for (i in 0 until declarationsCount) {
|
||||
val id = buffer.long
|
||||
val isLocal = buffer.int != 0
|
||||
val offset = buffer.int
|
||||
val size = buffer.int
|
||||
declarationToOffsetSize[DeclarationId(id, isLocal)] = offset to size
|
||||
}
|
||||
}
|
||||
|
||||
fun declarationBytes(id: DeclarationId): ByteArray {
|
||||
val offsetSize = declarationToOffsetSize[id] ?: throw Error("No declaration with $id here")
|
||||
val result = ByteArray(offsetSize.second)
|
||||
buffer.position(offsetSize.first)
|
||||
buffer.get(result, 0, offsetSize.second)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private const val SINGLE_INDEX_RECORD_SIZE = 20 // sizeof(Long) + 3 * sizeof(Int).
|
||||
private const val INDEX_HEADER_SIZE = 4 // sizeof(Int).
|
||||
|
||||
class CombinedIrFileWriter(val declarationCount: Int) {
|
||||
private var currentDeclaration = 0
|
||||
private var currentPosition = 0
|
||||
private val file = org.jetbrains.kotlin.konan.file.createTempFile("ir").deleteOnExit()
|
||||
private val randomAccessFile = RandomAccessFile(file.path, "rw")
|
||||
|
||||
init {
|
||||
randomAccessFile.writeInt(declarationCount)
|
||||
assert(randomAccessFile.filePointer.toInt() == INDEX_HEADER_SIZE)
|
||||
for (i in 0 until declarationCount) {
|
||||
randomAccessFile.writeLong(-1) // id
|
||||
randomAccessFile.writeInt(-1) // isLocal
|
||||
randomAccessFile.writeInt(-1) // offset
|
||||
randomAccessFile.writeInt(-1) // size
|
||||
}
|
||||
currentPosition = randomAccessFile.filePointer.toInt()
|
||||
assert(currentPosition == INDEX_HEADER_SIZE + SINGLE_INDEX_RECORD_SIZE * declarationCount)
|
||||
}
|
||||
|
||||
fun skipDeclaration() {
|
||||
currentDeclaration++
|
||||
}
|
||||
|
||||
fun addDeclaration(id: DeclarationId, bytes: ByteArray) {
|
||||
randomAccessFile.seek((currentDeclaration * SINGLE_INDEX_RECORD_SIZE + INDEX_HEADER_SIZE).toLong())
|
||||
randomAccessFile.writeLong(id.id)
|
||||
randomAccessFile.writeInt(if (id.isLocal) 1 else 0)
|
||||
randomAccessFile.writeInt(currentPosition)
|
||||
randomAccessFile.writeInt(bytes.size)
|
||||
randomAccessFile.seek(currentPosition.toLong())
|
||||
randomAccessFile.write(bytes)
|
||||
assert(randomAccessFile.filePointer < Int.MAX_VALUE.toLong())
|
||||
currentPosition = randomAccessFile.filePointer.toInt()
|
||||
currentDeclaration++
|
||||
}
|
||||
|
||||
fun finishWriting(): File {
|
||||
assert(currentDeclaration == declarationCount)
|
||||
randomAccessFile.close()
|
||||
return file
|
||||
}
|
||||
}
|
||||
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
package org.jetbrains.kotlin.konan.library.impl
|
||||
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryLayout
|
||||
import org.jetbrains.kotlin.konan.library.MetadataReader
|
||||
|
||||
internal object DefaultMetadataReaderImpl : MetadataReader {
|
||||
|
||||
override fun loadSerializedModule(libraryLayout: KonanLibraryLayout): ByteArray =
|
||||
libraryLayout.moduleHeaderFile.readBytes()
|
||||
|
||||
override fun loadSerializedPackageFragment(libraryLayout: KonanLibraryLayout, fqName: String, partName: String): ByteArray =
|
||||
libraryLayout.packageFragmentFile(fqName, partName).readBytes()
|
||||
|
||||
}
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.konan.library.impl
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.library.*
|
||||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
import org.jetbrains.kotlin.konan.properties.loadProperties
|
||||
import org.jetbrains.kotlin.konan.properties.propertyList
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.util.defaultTargetSubstitutions
|
||||
import org.jetbrains.kotlin.konan.util.substitute
|
||||
|
||||
class KonanLibraryImpl(
|
||||
override val libraryFile: File,
|
||||
internal val target: KonanTarget?,
|
||||
override val isDefault: Boolean,
|
||||
private val metadataReader: MetadataReader
|
||||
) : KonanLibrary {
|
||||
|
||||
// For the zipped libraries inPlace gives files from zip file system
|
||||
// whereas realFiles extracts them to /tmp.
|
||||
// For unzipped libraries inPlace and realFiles are the same
|
||||
// providing files in the library directory.
|
||||
|
||||
private val layout = createKonanLibraryLayout(libraryFile, target)
|
||||
|
||||
override val libraryName: String by lazy { layout.inPlace { it.libraryName } }
|
||||
|
||||
override val manifestProperties: Properties by lazy {
|
||||
val properties = layout.inPlace { it.manifestFile.loadProperties() }
|
||||
if (target != null) substitute(properties, defaultTargetSubstitutions(target))
|
||||
properties
|
||||
}
|
||||
|
||||
override val versions: KonanLibraryVersioning
|
||||
get() = manifestProperties.readKonanLibraryVersioning()
|
||||
|
||||
override val linkerOpts: List<String>
|
||||
get() = manifestProperties.propertyList(KLIB_PROPERTY_LINKED_OPTS)
|
||||
|
||||
override val bitcodePaths: List<String>
|
||||
get() = layout.realFiles { (it.kotlinDir.listFilesOrEmpty + it.nativeDir.listFilesOrEmpty).map { it.absolutePath } }
|
||||
|
||||
override val includedPaths: List<String>
|
||||
get() = layout.realFiles { it.includedDir.listFilesOrEmpty.map { it.absolutePath } }
|
||||
|
||||
override val targetList by lazy { layout.inPlace { it.targetsDir.listFiles.map { it.name } } }
|
||||
|
||||
override val dataFlowGraph by lazy { layout.inPlace { it.dataFlowGraphFile.let { if (it.exists) it.readBytes() else null } } }
|
||||
|
||||
override val moduleHeaderData: ByteArray by lazy { layout.inPlace { metadataReader.loadSerializedModule(it) } }
|
||||
|
||||
override fun packageMetadata(packageFqName: String, partName: String) =
|
||||
layout.inPlace { metadataReader.loadSerializedPackageFragment(it, packageFqName, partName) }
|
||||
|
||||
override fun packageMetadataParts(fqName: String): Set<String> =
|
||||
layout.inPlace { inPlaceLayout ->
|
||||
val fileList =
|
||||
inPlaceLayout.packageFragmentsDir(fqName)
|
||||
.listFiles
|
||||
.mapNotNull {
|
||||
it.name
|
||||
.substringBeforeLast(KLIB_METADATA_FILE_EXTENSION_WITH_DOT, missingDelimiterValue = "")
|
||||
.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
|
||||
fileList.toSortedSet().also {
|
||||
require(it.size == fileList.size) { "Duplicated names: ${fileList.groupingBy { it }.eachCount().filter { (_, count) -> count > 1 }}" }
|
||||
}
|
||||
}
|
||||
|
||||
override val irHeader: ByteArray? by lazy { layout.inPlace { library -> library.irHeader.let {
|
||||
if (it.exists) loadIrHeader() else null }
|
||||
}}
|
||||
|
||||
override fun irDeclaration(index: Long, isLocal: Boolean) = loadIrDeclaraton(index, isLocal)
|
||||
|
||||
override fun toString() = "$libraryName[default=$isDefault]"
|
||||
|
||||
private val combinedDeclarations: CombinedIrFileReader by lazy {
|
||||
CombinedIrFileReader(layout.realFiles {
|
||||
it.irFile
|
||||
})
|
||||
}
|
||||
private fun loadIrHeader(): ByteArray =
|
||||
layout.inPlace { it.irHeader.readBytes() }
|
||||
|
||||
private fun loadIrDeclaraton(index: Long, isLocal: Boolean) =
|
||||
combinedDeclarations.declarationBytes(DeclarationId(index, isLocal))
|
||||
}
|
||||
-91
@@ -1,91 +0,0 @@
|
||||
package org.jetbrains.kotlin.konan.library.impl
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.*
|
||||
import org.jetbrains.kotlin.konan.library.KLIB_FILE_EXTENSION
|
||||
import org.jetbrains.kotlin.konan.library.KLIB_FILE_EXTENSION_WITH_DOT
|
||||
import org.jetbrains.kotlin.konan.library.KonanLibraryLayout
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.util.removeSuffixIfPresent
|
||||
import java.nio.file.FileSystem
|
||||
|
||||
interface KonanLibraryLayoutImpl: KonanLibraryLayout {
|
||||
fun <T> inPlace(action: (KonanLibraryLayout) -> T): T
|
||||
fun <T> realFiles (action: (KonanLibraryLayout) -> T): T
|
||||
}
|
||||
|
||||
private class ZippedKonanLibraryLayout(val klibFile: File, override val target: KonanTarget?): KonanLibraryLayoutImpl {
|
||||
|
||||
init { zippedKonanLibraryChecks(klibFile) }
|
||||
|
||||
override val libraryName = klibFile.path.removeSuffixIfPresent(KLIB_FILE_EXTENSION_WITH_DOT)
|
||||
|
||||
override val libDir = File("/")
|
||||
|
||||
override fun <T> realFiles(action: (KonanLibraryLayout) -> T): T {
|
||||
return action(FileExtractor(this))!!
|
||||
}
|
||||
|
||||
override fun <T> inPlace(action: (KonanLibraryLayout) -> T): T {
|
||||
return klibFile.withZipFileSystem { zipFileSystem ->
|
||||
action(DirectFromZip(this, zipFileSystem))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun zippedKonanLibraryChecks(klibFile: File) {
|
||||
check(klibFile.exists) { "Could not find $klibFile." }
|
||||
check(klibFile.isFile) { "Expected $klibFile to be a regular file." }
|
||||
|
||||
val extension = klibFile.extension
|
||||
check(extension.isEmpty() || extension == KLIB_FILE_EXTENSION) { "Unexpected file extension: $extension" }
|
||||
}
|
||||
|
||||
private class UnzippedKonanLibraryLayout(override val libDir: File, override val target: KonanTarget?): KonanLibraryLayoutImpl {
|
||||
override val libraryName = libDir.path
|
||||
|
||||
override fun <T> inPlace(action: (KonanLibraryLayout) -> T): T = action(this)
|
||||
override fun <T> realFiles (action: (KonanLibraryLayout) -> T): T = inPlace(action)
|
||||
}
|
||||
|
||||
private class DirectFromZip(zippedLayout: ZippedKonanLibraryLayout, val zipFileSystem: FileSystem): KonanLibraryLayout {
|
||||
override val libraryName = zippedLayout.libraryName
|
||||
override val libDir = zipFileSystem.file(zippedLayout.libDir)
|
||||
}
|
||||
|
||||
/**
|
||||
* This class automatically extracts pieces of the library on first access. Use it if you need
|
||||
* to pass extracted files to an external tool. Otherwise, stick to [DirectFromZip].
|
||||
*/
|
||||
private class FileExtractor(val zippedLibraryLayout: ZippedKonanLibraryLayout): KonanLibraryLayout by zippedLibraryLayout {
|
||||
|
||||
override val manifestFile: File by lazy { extract(super.manifestFile) }
|
||||
|
||||
override val resourcesDir: File by lazy { extractDir(super.resourcesDir) }
|
||||
|
||||
override val includedDir: File by lazy { extractDir(super.includedDir) }
|
||||
|
||||
override val kotlinDir: File by lazy { extractDir(super.kotlinDir) }
|
||||
|
||||
override val nativeDir: File by lazy { extractDir(super.nativeDir) }
|
||||
|
||||
override val linkdataDir: File by lazy { extractDir(super.linkdataDir) }
|
||||
|
||||
override val irFile: File by lazy { extract(super.irFile) }
|
||||
|
||||
fun extract(file: File): File = zippedLibraryLayout.klibFile.withZipFileSystem { zipFileSystem ->
|
||||
val temporary = createTempFile(file.name)
|
||||
zipFileSystem.file(file).copyTo(temporary)
|
||||
temporary.deleteOnExit()
|
||||
temporary
|
||||
}
|
||||
|
||||
fun extractDir(directory: File): File = zippedLibraryLayout.klibFile.withZipFileSystem { zipFileSystem ->
|
||||
val temporary = createTempDir(directory.name)
|
||||
zipFileSystem.file(directory).recursiveCopyTo(temporary)
|
||||
temporary.deleteOnExitRecursively()
|
||||
temporary
|
||||
}
|
||||
}
|
||||
|
||||
internal fun createKonanLibraryLayout(klib: File, target: KonanTarget? = null) =
|
||||
if (klib.isFile) ZippedKonanLibraryLayout(klib, target) else UnzippedKonanLibraryLayout(klib, target)
|
||||
@@ -1,28 +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.konan
|
||||
|
||||
/**
|
||||
* This is a common ancestor of all Kotlin/Native exceptions.
|
||||
*/
|
||||
open class KonanException(message: String = "", cause: Throwable? = null) : Exception(message, cause)
|
||||
|
||||
/**
|
||||
* An error occured during external tool invocation. Such as non-zero exit code.
|
||||
*/
|
||||
class KonanExternalToolFailure(message: String, val toolName: String, cause: Throwable? = null) : KonanException(message, cause)
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* Copyright 2010-2019 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
|
||||
|
||||
fun String.parseKonanAbiVersion(): KonanAbiVersion {
|
||||
return KonanAbiVersion(this.toInt())
|
||||
}
|
||||
|
||||
data class KonanAbiVersion(val version: Int) {
|
||||
companion object {
|
||||
val CURRENT = KonanAbiVersion(8)
|
||||
}
|
||||
override fun toString() = "$version"
|
||||
}
|
||||
@@ -1,42 +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.konan
|
||||
|
||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove the whole file!
|
||||
|
||||
/**
|
||||
* https://en.wikipedia.org/wiki/Software_versioning
|
||||
* scheme major.minor[.build[.revision]].
|
||||
*/
|
||||
|
||||
enum class MetaVersion(val metaString: String) {
|
||||
DEV("dev"),
|
||||
EAP("eap"),
|
||||
ALPHA("alpha"),
|
||||
BETA("beta"),
|
||||
RC1("rc1"),
|
||||
RC2("rc2"),
|
||||
RELEASE("release");
|
||||
|
||||
companion object {
|
||||
|
||||
fun findAppropriate(metaString: String): MetaVersion {
|
||||
return MetaVersion.values().find { it.metaString.equals(metaString, ignoreCase = true) }
|
||||
?: if (metaString.isBlank()) RELEASE else error("Unknown meta version: $metaString")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.kotlin.konan
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.file.*
|
||||
|
||||
/**
|
||||
* Creates and stores temporary compiler outputs
|
||||
* If pathToTemporaryDir is given and is not empty then temporary outputs will be preserved
|
||||
*/
|
||||
class TempFiles(outputPath: String, pathToTemporaryDir: String? = null) {
|
||||
private val outputName = File(outputPath).name
|
||||
|
||||
val nativeBinaryFile by lazy { File(dir,"${outputName}.kt.bc") }
|
||||
val cAdapterCpp by lazy { File(dir, "api.cpp") }
|
||||
val cAdapterBitcode by lazy { File(dir, "api.bc") }
|
||||
|
||||
val nativeBinaryFileName get() = nativeBinaryFile.absolutePath
|
||||
val cAdapterCppName get() = cAdapterCpp.absolutePath
|
||||
val cAdapterBitcodeName get() = cAdapterBitcode.absolutePath
|
||||
|
||||
private val dir by lazy { if (pathToTemporaryDir == null || pathToTemporaryDir.isEmpty()) {
|
||||
createTempDir("konan_temp").deleteOnExit()
|
||||
} else {
|
||||
createDirForTemporaryFiles(pathToTemporaryDir)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createDirForTemporaryFiles(path: String): File {
|
||||
if (File(path).isFile) {
|
||||
throw IllegalArgumentException("Given file is not a directory: $path")
|
||||
}
|
||||
return File(path).apply {
|
||||
if (!exists) { mkdirs() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create file named {name}{suffix} inside temporary dir
|
||||
*/
|
||||
fun create(prefix: String, suffix: String = ""): File =
|
||||
File(dir, "$prefix$suffix")
|
||||
}
|
||||
|
||||
@@ -1,25 +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.konan.util
|
||||
|
||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove the whole file!
|
||||
|
||||
val <T : Enum<T>> T.visibleName get() = name.toLowerCase()
|
||||
interface Named {
|
||||
val name: String
|
||||
val visibleName get() = name
|
||||
}
|
||||
@@ -1,111 +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.konan.exec
|
||||
|
||||
import java.lang.ProcessBuilder
|
||||
import java.lang.ProcessBuilder.Redirect
|
||||
import org.jetbrains.kotlin.konan.KonanExternalToolFailure
|
||||
|
||||
|
||||
open class Command(initialCommand: List<String>) {
|
||||
|
||||
constructor(tool: String) : this(listOf(tool))
|
||||
constructor(vararg command: String) : this(command.toList<String>())
|
||||
protected val command = initialCommand.toMutableList()
|
||||
|
||||
val args: List<String>
|
||||
get() = command.drop(1)
|
||||
|
||||
operator fun String.unaryPlus(): Command {
|
||||
command += this
|
||||
return this@Command
|
||||
}
|
||||
|
||||
operator fun List<String>.unaryPlus(): Command {
|
||||
command.addAll(this)
|
||||
return this@Command
|
||||
}
|
||||
|
||||
var logger: ((() -> String)->Unit)? = null
|
||||
|
||||
fun logWith(newLogger: ((() -> String)->Unit)): Command {
|
||||
logger = newLogger
|
||||
return this
|
||||
}
|
||||
|
||||
open fun runProcess(): Int {
|
||||
val builder = ProcessBuilder(command)
|
||||
|
||||
builder.redirectOutput(Redirect.INHERIT)
|
||||
builder.redirectInput(Redirect.INHERIT)
|
||||
builder.redirectError(Redirect.INHERIT)
|
||||
|
||||
val process = builder.start()
|
||||
val exitCode = process.waitFor()
|
||||
return exitCode
|
||||
}
|
||||
|
||||
open fun execute() {
|
||||
log()
|
||||
|
||||
val code = runProcess()
|
||||
handleExitCode(code)
|
||||
}
|
||||
|
||||
/**
|
||||
* If withErrors is true then output from error stream will be added
|
||||
*/
|
||||
fun getOutputLines(withErrors: Boolean = false): List<String> =
|
||||
getResult(withErrors, handleError = true).outputLines
|
||||
|
||||
fun getResult(withErrors: Boolean, handleError: Boolean = false): Result {
|
||||
log()
|
||||
|
||||
val outputFile = createTempFile()
|
||||
outputFile.deleteOnExit()
|
||||
|
||||
try {
|
||||
val builder = ProcessBuilder(command)
|
||||
|
||||
builder.redirectInput(Redirect.INHERIT)
|
||||
builder.redirectError(Redirect.INHERIT)
|
||||
builder.redirectOutput(Redirect.to(outputFile))
|
||||
.redirectErrorStream(withErrors)
|
||||
// Note: getting process output could be done without redirecting to temporary file,
|
||||
// however this would require managing a thread to read `process.inputStream` because
|
||||
// it may have limited capacity.
|
||||
|
||||
val process = builder.start()
|
||||
val code = process.waitFor()
|
||||
if (handleError) handleExitCode(code)
|
||||
|
||||
return Result(code, outputFile.readLines())
|
||||
} finally {
|
||||
outputFile.delete()
|
||||
}
|
||||
}
|
||||
|
||||
class Result(val exitCode: Int, val outputLines: List<String>)
|
||||
|
||||
private fun handleExitCode(code: Int) {
|
||||
if (code != 0) throw KonanExternalToolFailure("The ${command[0]} command returned non-zero exit code: $code.", command[0])
|
||||
}
|
||||
|
||||
private fun log() {
|
||||
if (logger != null) logger!! { command.joinToString(" ") }
|
||||
}
|
||||
}
|
||||
@@ -1,233 +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.konan.file
|
||||
|
||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove the whole file!
|
||||
|
||||
import org.jetbrains.kotlin.konan.util.removeSuffixIfPresent
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStream
|
||||
import java.io.InputStreamReader
|
||||
import java.io.RandomAccessFile
|
||||
import java.net.URI
|
||||
import java.nio.MappedByteBuffer
|
||||
import java.nio.channels.FileChannel
|
||||
import java.nio.file.*
|
||||
import java.nio.file.attribute.BasicFileAttributes
|
||||
|
||||
data class File constructor(internal val javaPath: Path) {
|
||||
constructor(parent: Path, child: String): this(parent.resolve(child))
|
||||
constructor(parent: File, child: String): this(parent.javaPath.resolve(child))
|
||||
constructor(path: String): this(Paths.get(path))
|
||||
constructor(parent: String, child: String): this(Paths.get(parent, child))
|
||||
|
||||
val path: String
|
||||
get() = javaPath.toString()
|
||||
val absolutePath: String
|
||||
get() = javaPath.toAbsolutePath().toString()
|
||||
val absoluteFile: File
|
||||
get() = File(absolutePath)
|
||||
val name: String
|
||||
get() = javaPath.fileName.toString().removeSuffixIfPresent("/") // https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8153248
|
||||
val extension: String
|
||||
get() = name.substringAfterLast('.', "")
|
||||
val parent: String
|
||||
get() = javaPath.parent.toString()
|
||||
val parentFile: File
|
||||
get() = File(javaPath.parent)
|
||||
|
||||
val exists
|
||||
get() = Files.exists(javaPath)
|
||||
val isDirectory
|
||||
get() = Files.isDirectory(javaPath)
|
||||
val isFile
|
||||
get() = Files.isRegularFile(javaPath)
|
||||
val isAbsolute
|
||||
get() = javaPath.isAbsolute()
|
||||
val listFiles: List<File>
|
||||
get() = Files.newDirectoryStream(javaPath).use { stream -> stream.map { File(it) } }
|
||||
val listFilesOrEmpty: List<File>
|
||||
get() = if (exists) listFiles else emptyList()
|
||||
|
||||
fun child(name: String) = File(this, name)
|
||||
|
||||
fun copyTo(destination: File) {
|
||||
Files.copy(javaPath, destination.javaPath, StandardCopyOption.REPLACE_EXISTING)
|
||||
}
|
||||
|
||||
fun recursiveCopyTo(destination: File) {
|
||||
val sourcePath = javaPath
|
||||
val destPath = destination.javaPath
|
||||
sourcePath.recursiveCopyTo(destPath)
|
||||
}
|
||||
|
||||
fun mkdirs() = Files.createDirectories(javaPath)
|
||||
fun delete() = Files.deleteIfExists(javaPath)
|
||||
fun deleteRecursively() = postorder{Files.delete(it)}
|
||||
fun deleteOnExitRecursively() = preorder{File(it).deleteOnExit()}
|
||||
|
||||
fun preorder(task: (Path) -> Unit) {
|
||||
if (!this.exists) return
|
||||
|
||||
Files.walkFileTree(javaPath, object: SimpleFileVisitor<Path>() {
|
||||
override fun visitFile(file: Path?, attrs: BasicFileAttributes?): FileVisitResult {
|
||||
task(file!!)
|
||||
return FileVisitResult.CONTINUE
|
||||
}
|
||||
|
||||
override fun preVisitDirectory(dir: Path?, attrs: BasicFileAttributes?): FileVisitResult {
|
||||
task(dir!!)
|
||||
return FileVisitResult.CONTINUE
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
fun postorder(task: (Path) -> Unit) {
|
||||
if (!this.exists) return
|
||||
|
||||
Files.walkFileTree(javaPath, object: SimpleFileVisitor<Path>() {
|
||||
override fun visitFile(file: Path?, attrs: BasicFileAttributes?): FileVisitResult {
|
||||
task(file!!)
|
||||
return FileVisitResult.CONTINUE
|
||||
}
|
||||
|
||||
override fun postVisitDirectory(dir: Path?, exc: java.io.IOException?): FileVisitResult {
|
||||
task(dir!!)
|
||||
return FileVisitResult.CONTINUE
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun map(mode: FileChannel.MapMode = FileChannel.MapMode.READ_ONLY,
|
||||
start: Long = 0, size: Long = -1): MappedByteBuffer {
|
||||
val file = RandomAccessFile(path,
|
||||
if (mode == FileChannel.MapMode.READ_ONLY) "r" else "rw")
|
||||
val fileSize = if (mode == FileChannel.MapMode.READ_ONLY)
|
||||
file.length() else size.also { assert(size != -1L) }
|
||||
return file.channel.map(mode, start, fileSize) // Shall we .also { file.close() }?
|
||||
}
|
||||
|
||||
fun deleteOnExit(): File {
|
||||
// Works only on the default file system,
|
||||
// but that's okay for now.
|
||||
javaPath.toFile().deleteOnExit()
|
||||
return this // Allow streaming.
|
||||
}
|
||||
fun readBytes() = Files.readAllBytes(javaPath)
|
||||
fun writeBytes(bytes: ByteArray) = Files.write(javaPath, bytes)
|
||||
fun appendBytes(bytes: ByteArray)
|
||||
= Files.write(javaPath, bytes, StandardOpenOption.APPEND)
|
||||
|
||||
fun writeLines(lines: Iterable<String>) {
|
||||
Files.write(javaPath, lines)
|
||||
}
|
||||
|
||||
fun writeText(text: String): Unit = writeLines(listOf(text))
|
||||
|
||||
fun forEachLine(action: (String) -> Unit) {
|
||||
Files.lines(javaPath).use { lines ->
|
||||
lines.forEach { action(it) }
|
||||
}
|
||||
}
|
||||
|
||||
fun createAsSymlink(target: String) {
|
||||
val targetPath = Paths.get(target)
|
||||
if (Files.isSymbolicLink(this.javaPath) && Files.readSymbolicLink(javaPath) == targetPath) {
|
||||
return
|
||||
}
|
||||
Files.createSymbolicLink(this.javaPath, targetPath)
|
||||
}
|
||||
|
||||
override fun toString() = path
|
||||
|
||||
// TODO: Consider removeing these after konanazing java.util.Properties.
|
||||
fun bufferedReader() = Files.newBufferedReader(javaPath)
|
||||
fun outputStream() = Files.newOutputStream(javaPath)
|
||||
fun printWriter() = javaPath.toFile().printWriter()
|
||||
|
||||
companion object {
|
||||
val userDir
|
||||
get() = File(System.getProperty("user.dir"))
|
||||
|
||||
val userHome
|
||||
get() = File(System.getProperty("user.home"))
|
||||
|
||||
val javaHome
|
||||
get() = File(System.getProperty("java.home"))
|
||||
val pathSeparator = java.io.File.pathSeparator
|
||||
val separator = java.io.File.separator
|
||||
}
|
||||
|
||||
fun readStrings() = mutableListOf<String>().also { list -> forEachLine{list.add(it)}}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
val otherFile = other as? File ?: return false
|
||||
return otherFile.javaPath.toAbsolutePath() == javaPath.toAbsolutePath()
|
||||
}
|
||||
|
||||
override fun hashCode() = javaPath.toAbsolutePath().hashCode()
|
||||
}
|
||||
|
||||
fun String.File(): File = File(this)
|
||||
fun Path.File(): File = File(this)
|
||||
|
||||
fun createTempFile(name: String, suffix: String? = null)
|
||||
= Files.createTempFile(name, suffix).File()
|
||||
fun createTempDir(name: String): File
|
||||
= Files.createTempDirectory(name).File()
|
||||
|
||||
fun Path.recursiveCopyTo(destPath: Path) {
|
||||
val sourcePath = this
|
||||
Files.walk(sourcePath).forEach next@ { oldPath ->
|
||||
|
||||
val relative = sourcePath.relativize(oldPath)
|
||||
val destFs = destPath.getFileSystem()
|
||||
// We are copying files between file systems,
|
||||
// so pass the relative path through the String.
|
||||
val newPath = destFs.getPath(destPath.toString(), relative.toString())
|
||||
|
||||
// File systems don't allow replacing an existing root.
|
||||
if (newPath == newPath.getRoot()) return@next
|
||||
if (Files.isDirectory(newPath)) {
|
||||
Files.createDirectories(newPath)
|
||||
} else {
|
||||
Files.copy(oldPath, newPath, StandardCopyOption.REPLACE_EXISTING)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun bufferedReader(errorStream: InputStream?) = BufferedReader(InputStreamReader(errorStream))
|
||||
|
||||
// stdlib `use` function adapted for AutoCloseable.
|
||||
inline fun <T : AutoCloseable?, R> T.use(block: (T) -> R): R {
|
||||
var closed = false
|
||||
try {
|
||||
return block(this)
|
||||
} catch (e: Exception) {
|
||||
closed = true
|
||||
try {
|
||||
this?.close()
|
||||
} catch (closeException: Exception) {
|
||||
}
|
||||
throw e
|
||||
} finally {
|
||||
if (!closed) {
|
||||
this?.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +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.konan.file
|
||||
|
||||
val String.isJavaScript
|
||||
get() = this.endsWith(".js")
|
||||
|
||||
val String.isUnixStaticLib
|
||||
get() = this.endsWith(".a")
|
||||
|
||||
val String.isWindowsStaticLib
|
||||
get() = this.endsWith(".lib")
|
||||
|
||||
val String.isBitcode
|
||||
get() = this.endsWith(".bc")
|
||||
@@ -1,52 +0,0 @@
|
||||
package org.jetbrains.kotlin.konan.file
|
||||
|
||||
import java.net.URI
|
||||
import java.nio.file.*
|
||||
|
||||
private val File.zipUri: URI
|
||||
get() = URI.create("jar:${this.toPath().toUri()}")
|
||||
|
||||
fun File.zipFileSystem(mutable: Boolean = false): FileSystem {
|
||||
val zipUri = this.zipUri
|
||||
val attributes = hashMapOf("create" to mutable.toString())
|
||||
return try {
|
||||
FileSystems.newFileSystem(zipUri, attributes, null)
|
||||
} catch (e: FileSystemAlreadyExistsException) {
|
||||
FileSystems.getFileSystem(zipUri)
|
||||
}
|
||||
}
|
||||
|
||||
fun FileSystem.file(file: File) = File(this.getPath(file.path))
|
||||
|
||||
fun FileSystem.file(path: String) = File(this.getPath(path))
|
||||
|
||||
private fun File.toPath() = Paths.get(this.path)
|
||||
|
||||
fun File.zipDirAs(unixFile: File) {
|
||||
unixFile.withMutableZipFileSystem() {
|
||||
this.recursiveCopyTo(it.file("/"))
|
||||
}
|
||||
}
|
||||
|
||||
fun Path.unzipTo(directory: Path) {
|
||||
val zipUri = URI.create("jar:" + this.toUri())
|
||||
FileSystems.newFileSystem(zipUri, emptyMap<String, Any?>(), null).use { zipfs ->
|
||||
val zipPath = zipfs.getPath("/")
|
||||
zipPath.recursiveCopyTo(directory)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> File.withZipFileSystem(mutable: Boolean = false, action: (FileSystem) -> T): T {
|
||||
val zipFileSystem = this.zipFileSystem(mutable)
|
||||
return try {
|
||||
action(zipFileSystem)
|
||||
} finally {
|
||||
zipFileSystem.close()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> File.withZipFileSystem(action: (FileSystem) -> T): T
|
||||
= this.withZipFileSystem(false, action)
|
||||
|
||||
fun <T> File.withMutableZipFileSystem(action: (FileSystem) -> T): T
|
||||
= this.withZipFileSystem(true, action)
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* 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 -> in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.konan.target
|
||||
|
||||
import org.jetbrains.kotlin.konan.properties.KonanPropertiesLoader
|
||||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
import org.jetbrains.kotlin.konan.util.InternalServer
|
||||
|
||||
class AppleConfigurablesImpl(
|
||||
target: KonanTarget,
|
||||
properties: Properties,
|
||||
baseDir: String?
|
||||
) : AppleConfigurables, KonanPropertiesLoader(target, properties, baseDir) {
|
||||
|
||||
private val sdkDependency = this.targetSysRoot!!
|
||||
private val toolchainDependency = this.targetToolchain!!
|
||||
|
||||
override val absoluteTargetSysRoot: String get() = when (xcodePartsProvider) {
|
||||
is XcodePartsProvider.Local -> when (target) {
|
||||
KonanTarget.MACOS_X64 -> xcodePartsProvider.xcode.macosxSdk
|
||||
KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64 -> xcodePartsProvider.xcode.iphoneosSdk
|
||||
KonanTarget.IOS_X64 -> xcodePartsProvider.xcode.iphonesimulatorSdk
|
||||
else -> error(target)
|
||||
}
|
||||
XcodePartsProvider.InternalServer -> absolute(sdkDependency)
|
||||
}
|
||||
|
||||
override val absoluteTargetToolchain: String get() = when (xcodePartsProvider) {
|
||||
is XcodePartsProvider.Local -> xcodePartsProvider.xcode.toolchain
|
||||
XcodePartsProvider.InternalServer -> absolute(toolchainDependency)
|
||||
}
|
||||
|
||||
override val dependencies get() = super.dependencies + when (xcodePartsProvider) {
|
||||
is XcodePartsProvider.Local -> emptyList()
|
||||
XcodePartsProvider.InternalServer -> listOf(sdkDependency, toolchainDependency)
|
||||
}
|
||||
|
||||
private val xcodePartsProvider = if (InternalServer.isAvailable) {
|
||||
XcodePartsProvider.InternalServer
|
||||
} else {
|
||||
val xcode = Xcode.current
|
||||
properties.getProperty("useFixedXcodeVersion")?.let { requiredXcodeVersion ->
|
||||
val currentXcodeVersion = xcode.version
|
||||
|
||||
if (properties.getProperty("ignoreXcodeVersionCheck") != "true" &&
|
||||
currentXcodeVersion != requiredXcodeVersion) {
|
||||
error("expected Xcode version $requiredXcodeVersion, got $currentXcodeVersion, consider updating " +
|
||||
"Xcode or use \"ignoreXcodeVersionCheck\" variable in konan.properties")
|
||||
}
|
||||
}
|
||||
|
||||
XcodePartsProvider.Local(xcode)
|
||||
}
|
||||
|
||||
private sealed class XcodePartsProvider {
|
||||
class Local(val xcode: Xcode) : XcodePartsProvider()
|
||||
object InternalServer : XcodePartsProvider()
|
||||
}
|
||||
}
|
||||
@@ -1,317 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed -> in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.konan.target
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
|
||||
class ClangArgs(private val configurables: Configurables) : Configurables by configurables {
|
||||
|
||||
val targetArg = if (configurables is NonAppleConfigurables)
|
||||
configurables.targetArg
|
||||
else null
|
||||
|
||||
val specificClangArgs: List<String>
|
||||
get() {
|
||||
val result = when (target) {
|
||||
KonanTarget.LINUX_X64 ->
|
||||
listOf("--sysroot=$absoluteTargetSysRoot") +
|
||||
if (target != host) listOf("-target", targetArg!!) else emptyList()
|
||||
|
||||
KonanTarget.LINUX_ARM32_HFP ->
|
||||
listOf("-target", targetArg!!,
|
||||
"-mfpu=vfp", "-mfloat-abi=hard",
|
||||
"--sysroot=$absoluteTargetSysRoot",
|
||||
// TODO: those two are hacks.
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.8.3",
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.8.3/arm-linux-gnueabihf")
|
||||
|
||||
KonanTarget.LINUX_MIPS32 ->
|
||||
listOf("-target", targetArg!!,
|
||||
"--sysroot=$absoluteTargetSysRoot",
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.4",
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.4/mips-unknown-linux-gnu")
|
||||
|
||||
KonanTarget.LINUX_MIPSEL32 ->
|
||||
listOf("-target", targetArg!!,
|
||||
"--sysroot=$absoluteTargetSysRoot",
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.4",
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.4/mipsel-unknown-linux-gnu")
|
||||
|
||||
KonanTarget.MINGW_X64, KonanTarget.MINGW_X86 ->
|
||||
listOf("-target", targetArg!!, "--sysroot=$absoluteTargetSysRoot", "-Xclang", "-flto-visibility-public-std")
|
||||
|
||||
KonanTarget.MACOS_X64 ->
|
||||
listOf("--sysroot=$absoluteTargetSysRoot", "-mmacosx-version-min=10.11")
|
||||
|
||||
KonanTarget.IOS_ARM32 ->
|
||||
listOf("-stdlib=libc++", "-arch", "armv7", "-isysroot", absoluteTargetSysRoot, "-miphoneos-version-min=9.0.0")
|
||||
|
||||
KonanTarget.IOS_ARM64 ->
|
||||
listOf("-stdlib=libc++", "-arch", "arm64", "-isysroot", absoluteTargetSysRoot, "-miphoneos-version-min=9.0.0")
|
||||
|
||||
KonanTarget.IOS_X64 ->
|
||||
listOf("-stdlib=libc++", "-isysroot", absoluteTargetSysRoot, "-miphoneos-version-min=9.0.0")
|
||||
|
||||
KonanTarget.ANDROID_ARM32 ->
|
||||
listOf("-target", targetArg!!,
|
||||
"--sysroot=$absoluteTargetSysRoot",
|
||||
// HACKS!
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.x",
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.x/arm-linux-androideabi")
|
||||
|
||||
KonanTarget.ANDROID_ARM64 ->
|
||||
listOf("-target", targetArg!!,
|
||||
"--sysroot=$absoluteTargetSysRoot",
|
||||
// HACKS!
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.x",
|
||||
"-I$absoluteTargetSysRoot/usr/include/c++/4.9.x/aarch64-linux-android")
|
||||
|
||||
// By default wasm target forces `hidden` visibility which causes
|
||||
// linkage problems.
|
||||
KonanTarget.WASM32 ->
|
||||
listOf("-target", targetArg!!,
|
||||
"-fno-rtti",
|
||||
"-fno-exceptions",
|
||||
"-fvisibility=default",
|
||||
"-D_LIBCPP_ABI_VERSION=2",
|
||||
"-D_LIBCPP_NO_EXCEPTIONS=1",
|
||||
"-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")
|
||||
|
||||
is KonanTarget.ZEPHYR ->
|
||||
listOf("-target", targetArg!!,
|
||||
"-fno-rtti",
|
||||
"-fno-exceptions",
|
||||
"-fno-asynchronous-unwind-tables",
|
||||
"-fno-pie",
|
||||
"-fno-pic",
|
||||
"-fshort-enums",
|
||||
"-nostdinc",
|
||||
// TODO: make it a libGcc property?
|
||||
// We need to get rid of wasm sysroot first.
|
||||
"-isystem $targetToolchain/../lib/gcc/arm-none-eabi/7.2.1/include",
|
||||
"-isystem $targetToolchain/../lib/gcc/arm-none-eabi/7.2.1/include-fixed",
|
||||
"-isystem$absoluteTargetSysRoot/include/libcxx",
|
||||
"-isystem$absoluteTargetSysRoot/include/libc"
|
||||
) +
|
||||
(configurables as ZephyrConfigurables).boardSpecificClangFlags
|
||||
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
val clangArgsSpecificForKonanSources
|
||||
get() = when (target) {
|
||||
KonanTarget.LINUX_X64 ->
|
||||
listOf("-DUSE_GCC_UNWIND=1",
|
||||
"-DKONAN_LINUX=1",
|
||||
"-DKONAN_X64=1",
|
||||
"-DUSE_ELF_SYMBOLS=1",
|
||||
"-DELFSIZE=64",
|
||||
"-DKONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1")
|
||||
|
||||
KonanTarget.LINUX_ARM32_HFP ->
|
||||
listOf("-DUSE_GCC_UNWIND=1",
|
||||
"-DKONAN_LINUX=1",
|
||||
"-DKONAN_ARM32=1",
|
||||
"-DUSE_ELF_SYMBOLS=1",
|
||||
"-DELFSIZE=32",
|
||||
"-DKONAN_NO_UNALIGNED_ACCESS=1")
|
||||
|
||||
KonanTarget.LINUX_MIPS32 ->
|
||||
listOf("-DUSE_GCC_UNWIND=1",
|
||||
"-DKONAN_LINUX=1",
|
||||
"-DKONAN_MIPS32=1",
|
||||
"-DUSE_ELF_SYMBOLS=1",
|
||||
"-DELFSIZE=32",
|
||||
// TODO: reconsider, once target MIPS can do proper 64-bit load/store/CAS.
|
||||
"-DKONAN_NO_64BIT_ATOMIC=1",
|
||||
"-DKONAN_NO_UNALIGNED_ACCESS=1")
|
||||
|
||||
KonanTarget.LINUX_MIPSEL32 ->
|
||||
listOf("-DUSE_GCC_UNWIND=1",
|
||||
"-DKONAN_LINUX=1",
|
||||
"-DKONAN_MIPSEL32=1",
|
||||
"-DUSE_ELF_SYMBOLS=1",
|
||||
"-DELFSIZE=32",
|
||||
// TODO: reconsider, once target MIPS can do proper 64-bit load/store/CAS.
|
||||
"-DKONAN_NO_64BIT_ATOMIC=1",
|
||||
"-DKONAN_NO_UNALIGNED_ACCESS=1")
|
||||
|
||||
KonanTarget.MINGW_X64, KonanTarget.MINGW_X86 ->
|
||||
listOf("-DUSE_GCC_UNWIND=1",
|
||||
"-DUSE_PE_COFF_SYMBOLS=1",
|
||||
"-DKONAN_WINDOWS=1",
|
||||
if (target == KonanTarget.MINGW_X64) "-DKONAN_X64=1" else "-DKONAN_X86=1",
|
||||
"-DKONAN_NO_MEMMEM=1",
|
||||
"-DKONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1")
|
||||
|
||||
KonanTarget.MACOS_X64 ->
|
||||
listOf("-DKONAN_OSX=1",
|
||||
"-DKONAN_MACOSX=1",
|
||||
"-DKONAN_X64=1",
|
||||
"-DKONAN_OBJC_INTEROP=1",
|
||||
"-DKONAN_CORE_SYMBOLICATION=1",
|
||||
"-DKONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1")
|
||||
|
||||
KonanTarget.IOS_ARM32 ->
|
||||
listOf("-DKONAN_OBJC_INTEROP=1",
|
||||
"-DKONAN_IOS",
|
||||
"-DKONAN_ARM32=1",
|
||||
"-DKONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1",
|
||||
"-DKONAN_REPORT_BACKTRACE_TO_IOS_CRASH_LOG=1",
|
||||
"-DMACHSIZE=32",
|
||||
// While not 100% correct here, using atomic ops on iOS armv7 requires 8 byte alignment,
|
||||
// and general ABI requires 4-byte alignment on 64-bit long fields as mentioned in
|
||||
// https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html#//apple_ref/doc/uid/TP40009021-SW1
|
||||
// See https://github.com/ktorio/ktor/issues/941 for the context.
|
||||
"-DKONAN_NO_64BIT_ATOMIC=1",
|
||||
"-DKONAN_NO_UNALIGNED_ACCESS=1")
|
||||
|
||||
KonanTarget.IOS_ARM64 ->
|
||||
listOf("-DKONAN_OBJC_INTEROP=1",
|
||||
"-DKONAN_IOS=1",
|
||||
"-DKONAN_ARM64=1",
|
||||
"-DKONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1",
|
||||
"-DKONAN_REPORT_BACKTRACE_TO_IOS_CRASH_LOG=1",
|
||||
"-DMACHSIZE=64")
|
||||
|
||||
KonanTarget.IOS_X64 ->
|
||||
listOf("-DKONAN_OBJC_INTEROP=1",
|
||||
"-DKONAN_IOS=1",
|
||||
"-DKONAN_X64=1",
|
||||
"-DKONAN_CORE_SYMBOLICATION=1",
|
||||
"-DKONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1")
|
||||
|
||||
KonanTarget.ANDROID_ARM32 ->
|
||||
listOf("-D__ANDROID__",
|
||||
"-DUSE_GCC_UNWIND=1",
|
||||
"-DUSE_ELF_SYMBOLS=1",
|
||||
"-DELFSIZE=32",
|
||||
"-DKONAN_ANDROID=1",
|
||||
"-DKONAN_ARM32=1",
|
||||
"-DKONAN_NO_UNALIGNED_ACCESS=1")
|
||||
|
||||
KonanTarget.ANDROID_ARM64 ->
|
||||
listOf("-D__ANDROID__",
|
||||
"-DUSE_GCC_UNWIND=1",
|
||||
"-DUSE_ELF_SYMBOLS=1",
|
||||
"-DELFSIZE=64",
|
||||
"-DKONAN_ANDROID=1",
|
||||
"-DKONAN_ARM64=1",
|
||||
"-DKONAN_HAS_CXX11_EXCEPTION_FUNCTIONS=1")
|
||||
|
||||
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",
|
||||
"-DKONAN_NO_MEMMEM",
|
||||
"-DKONAN_NO_CTORS_SECTION=1")
|
||||
|
||||
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",
|
||||
"-DKONAN_NO_CTORS_SECTION=1",
|
||||
"-DKONAN_NO_UNALIGNED_ACCESS=1")
|
||||
}
|
||||
|
||||
private val host = HostManager.host
|
||||
|
||||
private val binDir = when (host) {
|
||||
KonanTarget.LINUX_X64 -> "$absoluteTargetToolchain/bin"
|
||||
KonanTarget.MINGW_X64 -> "$absoluteTargetToolchain/bin"
|
||||
KonanTarget.MACOS_X64 -> "$absoluteTargetToolchain/usr/bin"
|
||||
else -> throw TargetSupportException("Unexpected host platform")
|
||||
}
|
||||
|
||||
private val extraHostClangArgs =
|
||||
if (configurables is LinuxBasedConfigurables) {
|
||||
listOf("--gcc-toolchain=${configurables.absoluteGccToolchain}")
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
|
||||
val commonClangArgs = listOf("-B$binDir", "-fno-stack-protector") + extraHostClangArgs
|
||||
|
||||
val clangPaths = listOf("$absoluteLlvmHome/bin", binDir)
|
||||
|
||||
private val jdkDir by lazy {
|
||||
val home = File.javaHome.absoluteFile
|
||||
if (home.child("include").exists)
|
||||
home.absolutePath
|
||||
else
|
||||
home.parentFile.absolutePath
|
||||
}
|
||||
|
||||
val hostCompilerArgsForJni = listOf("", HostManager.jniHostPlatformIncludeDir).map { "-I$jdkDir/include/$it" }.toTypedArray()
|
||||
|
||||
val clangArgs = (commonClangArgs + specificClangArgs).toTypedArray()
|
||||
|
||||
val clangArgsForKonanSources =
|
||||
clangArgs + clangArgsSpecificForKonanSources
|
||||
|
||||
val targetLibclangArgs: List<String> =
|
||||
// libclang works not exactly the same way as the clang binary and
|
||||
// (in particular) uses different default header search path.
|
||||
// See e.g. http://lists.llvm.org/pipermail/cfe-dev/2013-November/033680.html
|
||||
// We workaround the problem with -isystem flag below.
|
||||
listOf("-isystem", "$absoluteLlvmHome/lib/clang/$llvmVersion/include", *clangArgs)
|
||||
|
||||
val targetClangCmd
|
||||
= listOf("${absoluteLlvmHome}/bin/clang") + clangArgs
|
||||
|
||||
val targetClangXXCmd
|
||||
= listOf("${absoluteLlvmHome}/bin/clang++") + clangArgs
|
||||
|
||||
fun clangC(vararg userArgs: String) = targetClangCmd + userArgs.asList()
|
||||
|
||||
fun clangCXX(vararg userArgs: String) = targetClangXXCmd + userArgs.asList()
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun filterGradleNativeSoftwareFlags(args: MutableList<String>) {
|
||||
args.remove("/usr/include") // HACK: over gradle-4.4.
|
||||
args.remove("-nostdinc") // HACK: over gradle-5.1.
|
||||
when (HostManager.host) {
|
||||
KonanTarget.LINUX_X64 -> args.remove("/usr/include/x86_64-linux-gnu") // HACK: over gradle-4.4.
|
||||
KonanTarget.MACOS_X64 -> {
|
||||
val indexToRemove = args.indexOf(args.find { it.contains("MacOSX.platform")}) // HACK: over gradle-4.7.
|
||||
if (indexToRemove != -1) {
|
||||
args.removeAt(indexToRemove - 1) // drop -I.
|
||||
args.removeAt(indexToRemove - 1) // drop /Application/Xcode.app/...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed -> in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.konan.target
|
||||
|
||||
import org.jetbrains.kotlin.konan.properties.*
|
||||
|
||||
interface Configurables : TargetableExternalStorage {
|
||||
|
||||
val target: KonanTarget
|
||||
|
||||
val llvmHome get() = hostString("llvmHome")
|
||||
val llvmVersion get() = hostString("llvmVersion")
|
||||
val libffiDir get() = hostString("libffiDir")
|
||||
|
||||
// TODO: Delegate to a map?
|
||||
val llvmLtoNooptFlags get() = targetList("llvmLtoNooptFlags")
|
||||
val llvmLtoOptFlags get() = targetList("llvmLtoOptFlags")
|
||||
val llvmLtoFlags get() = targetList("llvmLtoFlags")
|
||||
val llvmLtoDynamicFlags get() = targetList("llvmLtoDynamicFlags")
|
||||
val entrySelector get() = targetList("entrySelector")
|
||||
val linkerOptimizationFlags get() = targetList("linkerOptimizationFlags")
|
||||
val linkerKonanFlags get() = targetList("linkerKonanFlags")
|
||||
val linkerNoDebugFlags get() = targetList("linkerNoDebugFlags")
|
||||
val linkerDynamicFlags get() = targetList("linkerDynamicFlags")
|
||||
val llvmDebugOptFlags get() = targetList("llvmDebugOptFlags")
|
||||
val targetSysRoot get() = targetString("targetSysRoot")
|
||||
|
||||
// Notice: these ones are host-target.
|
||||
val targetToolchain get() = hostTargetString("targetToolchain")
|
||||
|
||||
val absoluteTargetSysRoot get() = absolute(targetSysRoot)
|
||||
val absoluteTargetToolchain get() = absolute(targetToolchain)
|
||||
val absoluteLlvmHome get() = absolute(llvmHome)
|
||||
}
|
||||
|
||||
interface NonAppleConfigurables : Configurables {
|
||||
val targetArg get() = targetString("quadruple")
|
||||
}
|
||||
|
||||
interface AppleConfigurables : Configurables {
|
||||
val arch get() = targetString("arch")!!
|
||||
val osVersionMin get() = targetString("osVersionMin")!!
|
||||
val osVersionMinFlagLd get() = targetString("osVersionMinFlagLd")!!
|
||||
}
|
||||
|
||||
interface MingwConfigurables : NonAppleConfigurables
|
||||
|
||||
interface LinuxBasedConfigurables : NonAppleConfigurables {
|
||||
val gccToolchain get() = hostString("gccToolchain")
|
||||
val absoluteGccToolchain get() = absolute(gccToolchain)
|
||||
|
||||
val libGcc get() = targetString("libGcc")!!
|
||||
val dynamicLinker get() = targetString("dynamicLinker")!!
|
||||
val pluginOptimizationFlags get() = targetList("pluginOptimizationFlags")
|
||||
val abiSpecificLibraries get() = targetList("abiSpecificLibraries")
|
||||
}
|
||||
|
||||
interface LinuxConfigurables : LinuxBasedConfigurables
|
||||
interface LinuxMIPSConfigurables : LinuxBasedConfigurables
|
||||
interface RaspberryPiConfigurables : LinuxBasedConfigurables
|
||||
interface AndroidConfigurables : NonAppleConfigurables
|
||||
|
||||
interface WasmConfigurables : NonAppleConfigurables {
|
||||
|
||||
val llcFlags get() = targetList("llcFlags")
|
||||
val llcNooptFlags get() = targetList("llcNooptFlags")
|
||||
val llcOptFlags get() = targetList("llcOptFlags")
|
||||
val llcDebugFlags get() = targetList("llcDebugFlags")
|
||||
|
||||
val optFlags get() = targetList("optFlags")
|
||||
val optNooptFlags get() = targetList("optNooptFlags")
|
||||
val optOptFlags get() = targetList("optOptFlags")
|
||||
val optDebugFlags get() = targetList("optDebugFlags")
|
||||
|
||||
val lldFlags get() = targetList("lld")
|
||||
}
|
||||
|
||||
interface ZephyrConfigurables : NonAppleConfigurables {
|
||||
val boardSpecificClangFlags get() = targetList("boardSpecificClangFlags")
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed -> in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.konan.target
|
||||
|
||||
import org.jetbrains.kotlin.konan.properties.*
|
||||
|
||||
class LinuxConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?)
|
||||
: LinuxConfigurables, KonanPropertiesLoader(target, properties, baseDir)
|
||||
|
||||
class LinuxMIPSConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?)
|
||||
: LinuxMIPSConfigurables, KonanPropertiesLoader(target, properties, baseDir)
|
||||
|
||||
class AndroidConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?)
|
||||
: AndroidConfigurables, KonanPropertiesLoader(target, properties, baseDir)
|
||||
|
||||
class MingwConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?)
|
||||
: MingwConfigurables, KonanPropertiesLoader(target, properties, baseDir)
|
||||
|
||||
class WasmConfigurablesImpl(target: KonanTarget, properties: Properties, baseDir: String?)
|
||||
: WasmConfigurables, KonanPropertiesLoader(target, properties, baseDir)
|
||||
|
||||
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_X64, KonanTarget.LINUX_ARM32_HFP ->
|
||||
LinuxConfigurablesImpl(target, properties, baseDir)
|
||||
KonanTarget.LINUX_MIPS32, KonanTarget.LINUX_MIPSEL32 ->
|
||||
LinuxMIPSConfigurablesImpl(target, properties, baseDir)
|
||||
KonanTarget.MACOS_X64, KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64, KonanTarget.IOS_X64 ->
|
||||
AppleConfigurablesImpl(target, properties, baseDir)
|
||||
KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64 ->
|
||||
AndroidConfigurablesImpl(target, properties, baseDir)
|
||||
KonanTarget.MINGW_X64, KonanTarget.MINGW_X86 ->
|
||||
MingwConfigurablesImpl(target, properties, baseDir)
|
||||
KonanTarget.WASM32 ->
|
||||
WasmConfigurablesImpl(target, properties, baseDir)
|
||||
is KonanTarget.ZEPHYR ->
|
||||
ZephyrConfigurablesImpl(target, properties, baseDir)
|
||||
}
|
||||
|
||||
@@ -1,94 +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.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 = DependencyProcessor.localKonanDir
|
||||
|
||||
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"
|
||||
val experimentalEnabled by lazy {
|
||||
File("$konanSubdir/experimentalTargetsEnabled").exists
|
||||
}
|
||||
|
||||
private fun propertyFilesFromConfigDir(configDir: String, genericName: String): List<File> {
|
||||
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.absolutePath, 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 launcherFiles = listOf("launcher.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)
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed -> in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.konan.properties
|
||||
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.target.Configurables
|
||||
import org.jetbrains.kotlin.konan.util.DependencyProcessor
|
||||
|
||||
interface TargetableExternalStorage {
|
||||
fun targetString(key: String): String?
|
||||
fun targetList(key: String): List<String>
|
||||
fun hostString(key: String): String?
|
||||
fun hostList(key: String): List<String>
|
||||
fun hostTargetString(key: String): String?
|
||||
fun hostTargetList(key: String): List<String>
|
||||
fun absolute(value: String?): String
|
||||
fun downloadDependencies()
|
||||
}
|
||||
|
||||
abstract class KonanPropertiesLoader(override val target: KonanTarget,
|
||||
val properties: Properties,
|
||||
val baseDir: String? = null) : Configurables {
|
||||
open val dependencies get() = hostTargetList("dependencies")
|
||||
|
||||
override fun downloadDependencies() {
|
||||
dependencyProcessor!!.run()
|
||||
}
|
||||
|
||||
override fun targetString(key: String): String?
|
||||
= properties.targetString(key, target)
|
||||
override fun targetList(key: String): List<String>
|
||||
= properties.targetList(key, target)
|
||||
override fun hostString(key: String): String?
|
||||
= properties.hostString(key)
|
||||
override fun hostList(key: String): List<String>
|
||||
= properties.hostList(key)
|
||||
override fun hostTargetString(key: String): String?
|
||||
= properties.hostTargetString(key, target)
|
||||
override fun hostTargetList(key: String): List<String>
|
||||
= properties.hostTargetList(key, target)
|
||||
|
||||
override fun absolute(value: String?): String =
|
||||
dependencyProcessor!!.resolveRelative(value!!).absolutePath
|
||||
private val dependencyProcessor by lazy {
|
||||
baseDir?.let { DependencyProcessor(java.io.File(it), this) }
|
||||
}
|
||||
}
|
||||
|
||||
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", "10.1")
|
||||
// TODO: it actually affects only resolution made in :dependencies,
|
||||
// that's why we assume that 'default' profile comes first (and check this above).
|
||||
}
|
||||
@@ -1,317 +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.konan.target
|
||||
|
||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove the whole file!
|
||||
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget.*
|
||||
import org.jetbrains.kotlin.konan.util.Named
|
||||
import java.io.Serializable
|
||||
|
||||
enum class Family(val exeSuffix:String, val dynamicPrefix: String, val dynamicSuffix: String,
|
||||
val staticPrefix: String, val staticSuffix: String) {
|
||||
OSX ("kexe", "lib", "dylib", "lib", "a"),
|
||||
IOS ("kexe", "lib", "dylib", "lib", "a"),
|
||||
LINUX ("kexe", "lib", "so" , "lib", "a"),
|
||||
MINGW ("exe" , "" , "dll" , "lib", "a"),
|
||||
ANDROID ("so" , "lib", "so" , "lib", "a"),
|
||||
WASM ("wasm", "" , "wasm" , "", "wasm"),
|
||||
ZEPHYR ("o" , "lib", "a" , "lib", "a")
|
||||
}
|
||||
|
||||
enum class Architecture(val bitness: Int) {
|
||||
X64(64),
|
||||
X86(32),
|
||||
ARM64(64),
|
||||
ARM32(32),
|
||||
MIPS32(32),
|
||||
MIPSEL32(32),
|
||||
WASM32(32);
|
||||
}
|
||||
|
||||
sealed class KonanTarget(override val name: String, val family: Family, val architecture: Architecture) : Named {
|
||||
object ANDROID_ARM32 : KonanTarget( "android_arm32", Family.ANDROID, Architecture.ARM32)
|
||||
object ANDROID_ARM64 : KonanTarget( "android_arm64", Family.ANDROID, Architecture.ARM64)
|
||||
object IOS_ARM32 : KonanTarget( "ios_arm32", Family.IOS, Architecture.ARM32)
|
||||
object IOS_ARM64 : KonanTarget( "ios_arm64", Family.IOS, Architecture.ARM64)
|
||||
object IOS_X64 : KonanTarget( "ios_x64", Family.IOS, Architecture.X64)
|
||||
object LINUX_X64 : KonanTarget( "linux_x64", Family.LINUX, Architecture.X64)
|
||||
object MINGW_X86 : KonanTarget( "mingw_x86", Family.MINGW, Architecture.X86)
|
||||
object MINGW_X64 : KonanTarget( "mingw_x64", Family.MINGW, Architecture.X64)
|
||||
object MACOS_X64 : KonanTarget( "macos_x64", Family.OSX, Architecture.X64)
|
||||
object LINUX_ARM32_HFP :KonanTarget( "linux_arm32_hfp", Family.LINUX, Architecture.ARM32)
|
||||
object LINUX_MIPS32 : KonanTarget( "linux_mips32", Family.LINUX, Architecture.MIPS32)
|
||||
object LINUX_MIPSEL32 : KonanTarget( "linux_mipsel32", Family.LINUX, Architecture.MIPSEL32)
|
||||
object WASM32 : KonanTarget( "wasm32", Family.WASM, Architecture.WASM32)
|
||||
|
||||
// Tunable targets
|
||||
class ZEPHYR(val subName: String, val genericName: String = "zephyr") : KonanTarget("${genericName}_$subName", Family.ZEPHYR, Architecture.ARM32)
|
||||
|
||||
override fun toString() = name
|
||||
}
|
||||
|
||||
fun hostTargetSuffix(host: KonanTarget, target: KonanTarget) =
|
||||
if (target == host) host.name else "${host.name}-${target.name}"
|
||||
|
||||
enum class CompilerOutputKind {
|
||||
PROGRAM {
|
||||
override fun suffix(target: KonanTarget?) = ".${target!!.family.exeSuffix}"
|
||||
},
|
||||
DYNAMIC {
|
||||
override fun suffix(target: KonanTarget?) = ".${target!!.family.dynamicSuffix}"
|
||||
override fun prefix(target: KonanTarget?) = "${target!!.family.dynamicPrefix}"
|
||||
},
|
||||
STATIC {
|
||||
override fun suffix(target: KonanTarget?) = ".${target!!.family.staticSuffix}"
|
||||
override fun prefix(target: KonanTarget?) = "${target!!.family.staticPrefix}"
|
||||
},
|
||||
FRAMEWORK {
|
||||
override fun suffix(target: KonanTarget?): String = ".framework"
|
||||
},
|
||||
LIBRARY {
|
||||
override fun suffix(target: KonanTarget?) = ".klib"
|
||||
},
|
||||
BITCODE {
|
||||
override fun suffix(target: KonanTarget?) = ".bc"
|
||||
};
|
||||
|
||||
abstract fun suffix(target: KonanTarget? = null): String
|
||||
open fun prefix(target: KonanTarget? = null): String = ""
|
||||
}
|
||||
|
||||
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 ""
|
||||
val aliasList = HostManager.listAliases(it.visibleName).joinToString(", ")
|
||||
println(String.format("%1$-30s%2$-10s%3\$s", "${it.visibleName}:", "$isDefault", aliasList))
|
||||
}
|
||||
}
|
||||
|
||||
fun determineCurrent(): KonanTarget {
|
||||
return if (userRequest == null || userRequest == "host") {
|
||||
HostManager.host
|
||||
} else {
|
||||
val resolvedAlias = HostManager.resolveAlias(userRequest)
|
||||
hostManager.targets[hostManager.known(resolvedAlias)]!!
|
||||
}
|
||||
}
|
||||
|
||||
override val hostTargetSuffix get() = hostTargetSuffix(HostManager.host, target)
|
||||
override val targetSuffix get() = target.name
|
||||
}
|
||||
|
||||
open class HostManager(protected val distribution: Distribution = Distribution(), experimental: Boolean = false) {
|
||||
|
||||
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,
|
||||
IOS_ARM32, IOS_ARM64, IOS_X64,
|
||||
LINUX_X64, LINUX_ARM32_HFP, LINUX_MIPS32, LINUX_MIPSEL32,
|
||||
MINGW_X64, MINGW_X86,
|
||||
MACOS_X64,
|
||||
WASM32)
|
||||
|
||||
private val zephyrSubtargets = distribution.availableSubTarget("zephyr").map { ZEPHYR(it) }
|
||||
|
||||
private val experimentalEnabled = experimental || distribution.experimentalEnabled
|
||||
|
||||
private val configurableSubtargets = zephyrSubtargets
|
||||
|
||||
val targetValues: List<KonanTarget> by lazy {
|
||||
predefinedTargets + configurableSubtargets
|
||||
}
|
||||
|
||||
val targets = targetValues.associate{ it.visibleName to it }
|
||||
|
||||
fun toKonanTargets(names: Iterable<String>): List<KonanTarget> {
|
||||
return names.map {
|
||||
if (it == "host") HostManager.host
|
||||
else targets[known(resolveAlias(it))]!!
|
||||
}
|
||||
}
|
||||
|
||||
fun known(name: String): String {
|
||||
if (targets[name] == null) {
|
||||
throw TargetSupportException("Unknown target: $name. Use -list_targets to see the list of available targets")
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
fun targetByName(name: String): KonanTarget {
|
||||
if (name == "host") return host
|
||||
val target = targets[resolveAlias(name)]
|
||||
if (target == null) throw TargetSupportException("Unknown target name: $name")
|
||||
return target
|
||||
}
|
||||
|
||||
val enabledRegular: List<KonanTarget> by lazy {
|
||||
when (host) {
|
||||
KonanTarget.LINUX_X64 -> listOf(
|
||||
KonanTarget.LINUX_X64,
|
||||
KonanTarget.LINUX_ARM32_HFP,
|
||||
KonanTarget.LINUX_MIPS32,
|
||||
KonanTarget.LINUX_MIPSEL32,
|
||||
KonanTarget.ANDROID_ARM32,
|
||||
KonanTarget.ANDROID_ARM64,
|
||||
KonanTarget.WASM32
|
||||
)
|
||||
KonanTarget.MINGW_X64 -> listOf(
|
||||
KonanTarget.MINGW_X64,
|
||||
KonanTarget.MINGW_X86,
|
||||
KonanTarget.LINUX_X64,
|
||||
KonanTarget.LINUX_ARM32_HFP,
|
||||
KonanTarget.ANDROID_ARM32,
|
||||
// TODO: toolchain to be fixed for that to work.
|
||||
// KonanTarget.ANDROID_ARM64,
|
||||
KonanTarget.WASM32
|
||||
)
|
||||
KonanTarget.MACOS_X64 -> listOf(
|
||||
KonanTarget.MACOS_X64,
|
||||
KonanTarget.IOS_ARM32,
|
||||
KonanTarget.IOS_ARM64,
|
||||
KonanTarget.IOS_X64,
|
||||
KonanTarget.LINUX_X64,
|
||||
KonanTarget.LINUX_ARM32_HFP,
|
||||
KonanTarget.ANDROID_ARM32,
|
||||
KonanTarget.ANDROID_ARM64,
|
||||
KonanTarget.WASM32
|
||||
)
|
||||
else ->
|
||||
throw TargetSupportException("Unknown host platform: $host")
|
||||
}
|
||||
}
|
||||
|
||||
val enabledExperimental: List<KonanTarget> by lazy {
|
||||
when (host) {
|
||||
KonanTarget.LINUX_X64 -> listOf(
|
||||
KonanTarget.MINGW_X86, KonanTarget.MINGW_X64
|
||||
) + zephyrSubtargets
|
||||
KonanTarget.MACOS_X64 -> listOf(
|
||||
KonanTarget.MINGW_X86, KonanTarget.MINGW_X64
|
||||
) + zephyrSubtargets
|
||||
KonanTarget.MINGW_X64 -> listOf<KonanTarget>(
|
||||
) + zephyrSubtargets
|
||||
else -> throw TargetSupportException("Unknown host platform: $host")
|
||||
}
|
||||
}
|
||||
|
||||
val enabled : List<KonanTarget>
|
||||
get() = if (experimentalEnabled) enabledRegular + enabledExperimental else enabledRegular
|
||||
|
||||
fun isEnabled(target: KonanTarget) = enabled.contains(target)
|
||||
|
||||
companion object {
|
||||
fun host_os(): String {
|
||||
val javaOsName = System.getProperty("os.name")
|
||||
return when {
|
||||
javaOsName == "Mac OS X" -> "osx"
|
||||
javaOsName == "Linux" -> "linux"
|
||||
javaOsName.startsWith("Windows") -> "windows"
|
||||
else -> throw TargetSupportException("Unknown operating system: ${javaOsName}")
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun simpleOsName(): String {
|
||||
val hostOs = host_os()
|
||||
return if (hostOs == "osx") "macos" else hostOs
|
||||
}
|
||||
|
||||
val jniHostPlatformIncludeDir: String
|
||||
get() = when(host) {
|
||||
KonanTarget.MACOS_X64 -> "darwin"
|
||||
KonanTarget.LINUX_X64 -> "linux"
|
||||
KonanTarget.MINGW_X64 ->"win32"
|
||||
else -> throw TargetSupportException("Unknown host: $host.")
|
||||
}
|
||||
|
||||
fun host_arch(): String {
|
||||
val javaArch = System.getProperty("os.arch")
|
||||
return when (javaArch) {
|
||||
"x86_64" -> "x86_64"
|
||||
"amd64" -> "x86_64"
|
||||
"arm64" -> "arm64"
|
||||
else -> throw TargetSupportException("Unknown hardware platform: ${javaArch}")
|
||||
}
|
||||
}
|
||||
|
||||
val host: KonanTarget = when (host_os()) {
|
||||
"osx" -> KonanTarget.MACOS_X64
|
||||
"linux" -> KonanTarget.LINUX_X64
|
||||
"windows" -> KonanTarget.MINGW_X64
|
||||
else -> throw TargetSupportException("Unknown host target: ${host_os()} ${host_arch()}")
|
||||
}
|
||||
|
||||
// Note Hotspot-specific VM option enforcing C1-only, critical for decent compilation speed.
|
||||
val defaultJvmArgs = listOf("-XX:TieredStopAtLevel=1", "-ea", "-Dfile.encoding=UTF-8")
|
||||
val regularJvmArgs = defaultJvmArgs + "-Xmx3G"
|
||||
|
||||
val hostIsMac = (host.family == Family.OSX)
|
||||
val hostIsLinux = (host.family == Family.LINUX)
|
||||
val hostIsMingw = (host.family == Family.MINGW)
|
||||
|
||||
val hostSuffix get() = host.name
|
||||
@JvmStatic
|
||||
val hostName get() = host.name
|
||||
|
||||
val knownTargetTemplates = listOf("zephyr")
|
||||
|
||||
private val targetAliasResolutions = mapOf(
|
||||
"linux" to "linux_x64",
|
||||
"macbook" to "macos_x64",
|
||||
"macos" to "macos_x64",
|
||||
"imac" to "macos_x64",
|
||||
"raspberrypi" to "linux_arm32_hfp",
|
||||
"iphone32" to "ios_arm32",
|
||||
"iphone" to "ios_arm64",
|
||||
"ipad" to "ios_arm64",
|
||||
"ios" to "ios_arm64",
|
||||
"iphone_sim" to "ios_x64",
|
||||
"mingw" to "mingw_x64"
|
||||
)
|
||||
|
||||
private val targetAliases: Map<String, List<String>> by lazy {
|
||||
val result = mutableMapOf<String, MutableList<String>>()
|
||||
targetAliasResolutions.entries.forEach {
|
||||
result.getOrPut(it.value, { mutableListOf() } ).add(it.key)
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fun resolveAlias(request: String): String = targetAliasResolutions[request] ?: request
|
||||
|
||||
fun listAliases(target: String): List<String> = targetAliases[target] ?: emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
class TargetSupportException (message: String = "", cause: Throwable? = null) : Exception(message, cause)
|
||||
|
||||
@@ -1,426 +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.konan.target
|
||||
|
||||
import java.lang.ProcessBuilder
|
||||
import java.lang.ProcessBuilder.Redirect
|
||||
import org.jetbrains.kotlin.konan.exec.Command
|
||||
import org.jetbrains.kotlin.konan.file.*
|
||||
|
||||
typealias ObjectFile = String
|
||||
typealias ExecutableFile = String
|
||||
|
||||
enum class LinkerOutputKind {
|
||||
DYNAMIC_LIBRARY,
|
||||
STATIC_LIBRARY,
|
||||
EXECUTABLE
|
||||
}
|
||||
|
||||
// Here we take somewhat unexpected approach - we create the thin
|
||||
// library, and then repack it during post-link phase.
|
||||
// This way we ensure .a inputs are properly processed.
|
||||
private fun staticGnuArCommands(ar: String, executable: ExecutableFile,
|
||||
objectFiles: List<ObjectFile>, libraries: List<String>) = when {
|
||||
HostManager.hostIsMingw -> {
|
||||
val temp = executable.replace('/', '\\') + "__"
|
||||
val arWindows = ar.replace('/', '\\')
|
||||
listOf(
|
||||
Command(arWindows, "-rucT", temp).apply {
|
||||
+objectFiles
|
||||
+libraries
|
||||
},
|
||||
Command("cmd", "/c").apply {
|
||||
+"(echo create $executable & echo addlib ${temp} & echo save & echo end) | $arWindows -M"
|
||||
},
|
||||
Command("cmd", "/c", "del", "/q", temp))
|
||||
}
|
||||
HostManager.hostIsLinux || HostManager.hostIsMac -> listOf(
|
||||
Command(ar, "cqT", executable).apply {
|
||||
+objectFiles
|
||||
+libraries
|
||||
},
|
||||
Command("/bin/sh", "-c").apply {
|
||||
+"printf 'create $executable\\naddlib $executable\\nsave\\nend' | $ar -M"
|
||||
})
|
||||
else -> TODO("Unsupported host ${HostManager.host}")
|
||||
}
|
||||
|
||||
// Use "clang -v -save-temps" to write linkCommand() method
|
||||
// for another implementation of this class.
|
||||
abstract class LinkerFlags(val configurables: Configurables)
|
||||
/* : Configurables by configurables */ {
|
||||
|
||||
protected val llvmBin = "${configurables.absoluteLlvmHome}/bin"
|
||||
protected val llvmLib = "${configurables.absoluteLlvmHome}/lib"
|
||||
|
||||
private val libLTODir = when (HostManager.host) {
|
||||
KonanTarget.MACOS_X64, KonanTarget.LINUX_X64 -> llvmLib
|
||||
KonanTarget.MINGW_X64 -> llvmBin
|
||||
else -> error("Don't know libLTO location for this platform.")
|
||||
}
|
||||
|
||||
open val useCompilerDriverAsLinker: Boolean get() = false // TODO: refactor.
|
||||
|
||||
abstract fun linkCommands(objectFiles: List<ObjectFile>, executable: ExecutableFile,
|
||||
libraries: List<String>, linkerArgs: List<String>,
|
||||
optimize: Boolean, debug: Boolean,
|
||||
kind: LinkerOutputKind, outputDsymBundle: String): List<Command>
|
||||
|
||||
abstract fun filterStaticLibraries(binaries: List<String>): List<String>
|
||||
|
||||
open fun linkStaticLibraries(binaries: List<String>): List<String> {
|
||||
val libraries = filterStaticLibraries(binaries)
|
||||
// Let's just pass them as absolute paths.
|
||||
return libraries
|
||||
}
|
||||
}
|
||||
|
||||
open class AndroidLinker(targetProperties: AndroidConfigurables)
|
||||
: LinkerFlags(targetProperties), AndroidConfigurables by targetProperties {
|
||||
|
||||
private val prefix = "$absoluteTargetToolchain/bin/"
|
||||
private val clang = if (HostManager.hostIsMingw) "$prefix/clang.cmd" else "$prefix/clang"
|
||||
private val ar = "$absoluteTargetToolchain/${targetProperties.targetArg}/bin/ar"
|
||||
|
||||
override val useCompilerDriverAsLinker: Boolean get() = true
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>) = binaries.filter { it.isUnixStaticLib }
|
||||
|
||||
override fun linkCommands(objectFiles: List<ObjectFile>, executable: ExecutableFile,
|
||||
libraries: List<String>, linkerArgs: List<String>,
|
||||
optimize: Boolean, debug: Boolean,
|
||||
kind: LinkerOutputKind, outputDsymBundle: String): List<Command> {
|
||||
if (kind == LinkerOutputKind.STATIC_LIBRARY)
|
||||
return staticGnuArCommands(ar, executable, objectFiles, libraries)
|
||||
|
||||
val dynamic = kind == LinkerOutputKind.DYNAMIC_LIBRARY
|
||||
// liblog.so must be linked in, as we use its functionality in runtime.
|
||||
return listOf(Command(clang).apply {
|
||||
+"-o"
|
||||
+executable
|
||||
+"-fPIC"
|
||||
+"-shared"
|
||||
+"-llog"
|
||||
+objectFiles
|
||||
if (optimize) +linkerOptimizationFlags
|
||||
if (!debug) +linkerNoDebugFlags
|
||||
if (dynamic) +linkerDynamicFlags
|
||||
if (dynamic) +"-Wl,-soname,${File(executable).name}"
|
||||
+linkerKonanFlags
|
||||
+libraries
|
||||
+linkerArgs
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
open class MacOSBasedLinker(targetProperties: AppleConfigurables)
|
||||
: LinkerFlags(targetProperties), AppleConfigurables by targetProperties {
|
||||
|
||||
private val libtool = "$absoluteTargetToolchain/usr/bin/libtool"
|
||||
private val linker = "$absoluteTargetToolchain/usr/bin/ld"
|
||||
private val dsymutil = "$absoluteLlvmHome/bin/llvm-dsymutil"
|
||||
|
||||
private fun provideCompilerRtLibrary(libraryName: String): String? {
|
||||
val suffix = if (libraryName.isNotEmpty() && target == KonanTarget.IOS_X64) {
|
||||
"iossim"
|
||||
} else {
|
||||
when (val family = configurables.target.family) {
|
||||
Family.OSX -> "osx"
|
||||
Family.IOS -> "ios"
|
||||
else -> error("Family $family is unsupported")
|
||||
}
|
||||
}
|
||||
val dir = File("$absoluteTargetToolchain/usr/lib/clang/").listFiles.firstOrNull()?.absolutePath
|
||||
val mangledName = if (libraryName.isEmpty()) "" else "${libraryName}_"
|
||||
|
||||
return if (dir != null) "$dir/lib/darwin/libclang_rt.$mangledName$suffix.a" else null
|
||||
}
|
||||
|
||||
private val compilerRtLibrary: String? by lazy {
|
||||
provideCompilerRtLibrary("")
|
||||
}
|
||||
|
||||
// Code coverage requires this library.
|
||||
private val profileLibrary: String? by lazy {
|
||||
provideCompilerRtLibrary("profile")
|
||||
}
|
||||
|
||||
private val osVersionMinFlags: List<String> by lazy {
|
||||
listOf(osVersionMinFlagLd, osVersionMin + ".0")
|
||||
}
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>) = binaries.filter { it.isUnixStaticLib }
|
||||
|
||||
override fun linkCommands(objectFiles: List<ObjectFile>, executable: ExecutableFile,
|
||||
libraries: List<String>, linkerArgs: List<String>,
|
||||
optimize: Boolean, debug: Boolean, kind: LinkerOutputKind,
|
||||
outputDsymBundle: String): List<Command> {
|
||||
if (kind == LinkerOutputKind.STATIC_LIBRARY)
|
||||
return listOf(Command(libtool).apply {
|
||||
+"-static"
|
||||
+listOf("-o", executable)
|
||||
+objectFiles
|
||||
+libraries
|
||||
})
|
||||
val dynamic = kind == LinkerOutputKind.DYNAMIC_LIBRARY
|
||||
return listOf(Command(linker).apply {
|
||||
+"-demangle"
|
||||
+listOf("-dynamic", "-arch", arch)
|
||||
+osVersionMinFlags
|
||||
+listOf("-syslibroot", absoluteTargetSysRoot, "-o", executable)
|
||||
+objectFiles
|
||||
if (optimize) +linkerOptimizationFlags
|
||||
if (!debug) +linkerNoDebugFlags
|
||||
if (dynamic) +linkerDynamicFlags
|
||||
+linkerKonanFlags
|
||||
if (compilerRtLibrary != null) +compilerRtLibrary!!
|
||||
if (profileLibrary != null) +profileLibrary!!
|
||||
+libraries
|
||||
+linkerArgs
|
||||
+rpath(dynamic)
|
||||
}) + if (debug) listOf(dsymUtilCommand(executable, outputDsymBundle)) else emptyList()
|
||||
}
|
||||
|
||||
private fun rpath(dynamic: Boolean): List<String> = listOfNotNull(
|
||||
when (target.family) {
|
||||
Family.OSX -> "@executable_path/../Frameworks"
|
||||
Family.IOS -> "@executable_path/Frameworks"
|
||||
else -> error(target)
|
||||
},
|
||||
"@loader_path/Frameworks".takeIf { dynamic }
|
||||
).flatMap { listOf("-rpath", it) }
|
||||
|
||||
fun dsymUtilCommand(executable: ExecutableFile, outputDsymBundle: String) =
|
||||
object : Command(dsymutilCommand(executable, outputDsymBundle)) {
|
||||
override fun runProcess(): Int =
|
||||
executeCommandWithFilter(command)
|
||||
}
|
||||
|
||||
// TODO: consider introducing a better filtering directly in Command.
|
||||
private fun executeCommandWithFilter(command: List<String>): Int {
|
||||
val builder = ProcessBuilder(command)
|
||||
|
||||
// Inherit main process output streams.
|
||||
val isDsymUtil = (command[0] == dsymutil)
|
||||
|
||||
builder.redirectOutput(Redirect.INHERIT)
|
||||
builder.redirectInput(Redirect.INHERIT)
|
||||
if (!isDsymUtil)
|
||||
builder.redirectError(Redirect.INHERIT)
|
||||
|
||||
val process = builder.start()
|
||||
if (isDsymUtil) {
|
||||
/**
|
||||
* llvm-lto has option -alias that lets tool to know which symbol we use instead of _main,
|
||||
* llvm-dsym doesn't have such a option, so we ignore annoying warning manually.
|
||||
*/
|
||||
val errorStream = process.errorStream
|
||||
val outputStream = bufferedReader(errorStream)
|
||||
while (true) {
|
||||
val line = outputStream.readLine() ?: break
|
||||
if (!line.contains("warning: could not find object file symbol for symbol _main"))
|
||||
System.err.println(line)
|
||||
}
|
||||
outputStream.close()
|
||||
}
|
||||
val exitCode = process.waitFor()
|
||||
return exitCode
|
||||
}
|
||||
|
||||
open fun dsymutilCommand(executable: ExecutableFile, outputDsymBundle: String): List<String> =
|
||||
listOf(dsymutil, executable, "-o", outputDsymBundle)
|
||||
|
||||
open fun dsymutilDryRunVerboseCommand(executable: ExecutableFile): List<String> =
|
||||
listOf(dsymutil, "-dump-debug-map", executable)
|
||||
}
|
||||
|
||||
open class LinuxBasedLinker(targetProperties: LinuxBasedConfigurables)
|
||||
: LinkerFlags(targetProperties), LinuxBasedConfigurables by targetProperties {
|
||||
|
||||
private val ar = if (HostManager.hostIsMac) "$absoluteTargetToolchain/bin/llvm-ar"
|
||||
else "$absoluteTargetToolchain/bin/ar"
|
||||
override val libGcc: String = "$absoluteTargetSysRoot/${super.libGcc}"
|
||||
private val linker = "$absoluteLlvmHome/bin/ld.lld"
|
||||
private val specificLibs = abiSpecificLibraries.map { "-L${absoluteTargetSysRoot}/$it" }
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>) = binaries.filter { it.isUnixStaticLib }
|
||||
|
||||
override fun linkCommands(objectFiles: List<ObjectFile>, executable: ExecutableFile,
|
||||
libraries: List<String>, linkerArgs: List<String>,
|
||||
optimize: Boolean, debug: Boolean,
|
||||
kind: LinkerOutputKind, outputDsymBundle: String): List<Command> {
|
||||
if (kind == LinkerOutputKind.STATIC_LIBRARY)
|
||||
return staticGnuArCommands(ar, executable, objectFiles, libraries)
|
||||
|
||||
val isMips = (configurables is LinuxMIPSConfigurables)
|
||||
val dynamic = kind == LinkerOutputKind.DYNAMIC_LIBRARY
|
||||
// TODO: Can we extract more to the konan.configurables?
|
||||
return listOf(Command(linker).apply {
|
||||
+"--sysroot=${absoluteTargetSysRoot}"
|
||||
+"-export-dynamic"
|
||||
+"-z"
|
||||
+"relro"
|
||||
+"--build-id"
|
||||
+"--eh-frame-hdr"
|
||||
+"-dynamic-linker"
|
||||
+dynamicLinker
|
||||
+"-o"
|
||||
+executable
|
||||
if (!dynamic) +"$absoluteTargetSysRoot/usr/lib64/crt1.o"
|
||||
+"$absoluteTargetSysRoot/usr/lib64/crti.o"
|
||||
+if (dynamic) "$libGcc/crtbeginS.o" else "$libGcc/crtbegin.o"
|
||||
+"-L$llvmLib"
|
||||
+"-L$libGcc"
|
||||
if (!isMips) +"--hash-style=gnu" // MIPS doesn't support hash-style=gnu
|
||||
+specificLibs
|
||||
+listOf("-L$absoluteTargetSysRoot/../lib", "-L$absoluteTargetSysRoot/lib", "-L$absoluteTargetSysRoot/usr/lib")
|
||||
if (optimize) +linkerOptimizationFlags
|
||||
if (!debug) +linkerNoDebugFlags
|
||||
if (dynamic) +linkerDynamicFlags
|
||||
+objectFiles
|
||||
+linkerKonanFlags
|
||||
+listOf("-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed",
|
||||
"-lc", "-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed")
|
||||
+if (dynamic) "$libGcc/crtendS.o" else "$libGcc/crtend.o"
|
||||
+"$absoluteTargetSysRoot/usr/lib64/crtn.o"
|
||||
+libraries
|
||||
+linkerArgs
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
open class MingwLinker(targetProperties: MingwConfigurables)
|
||||
: LinkerFlags(targetProperties), MingwConfigurables by targetProperties {
|
||||
|
||||
private val ar = "$absoluteTargetToolchain/bin/ar"
|
||||
private val linker = "$absoluteTargetToolchain/bin/clang++"
|
||||
|
||||
override val useCompilerDriverAsLinker: Boolean get() = true
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>) = binaries.filter { it.isWindowsStaticLib || it.isUnixStaticLib }
|
||||
|
||||
override fun linkCommands(objectFiles: List<ObjectFile>, executable: ExecutableFile,
|
||||
libraries: List<String>, linkerArgs: List<String>,
|
||||
optimize: Boolean, debug: Boolean,
|
||||
kind: LinkerOutputKind, outputDsymBundle: String): List<Command> {
|
||||
if (kind == LinkerOutputKind.STATIC_LIBRARY)
|
||||
return staticGnuArCommands(ar, executable, objectFiles, libraries)
|
||||
|
||||
val dynamic = kind == LinkerOutputKind.DYNAMIC_LIBRARY
|
||||
return listOf(when {
|
||||
HostManager.hostIsMingw -> Command(linker)
|
||||
else -> Command("wine64", "$linker.exe")
|
||||
}.apply {
|
||||
+listOf("-o", executable)
|
||||
+objectFiles
|
||||
if (optimize) +linkerOptimizationFlags
|
||||
if (!debug) +linkerNoDebugFlags
|
||||
if (dynamic) +linkerDynamicFlags
|
||||
+libraries
|
||||
+linkerArgs
|
||||
+linkerKonanFlags
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
open class WasmLinker(targetProperties: WasmConfigurables)
|
||||
: LinkerFlags(targetProperties), WasmConfigurables by targetProperties {
|
||||
|
||||
override val useCompilerDriverAsLinker: Boolean get() = false
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>) = binaries.filter { it.isJavaScript }
|
||||
|
||||
override fun linkCommands(objectFiles: List<ObjectFile>, executable: ExecutableFile,
|
||||
libraries: List<String>, linkerArgs: List<String>,
|
||||
optimize: Boolean, debug: Boolean,
|
||||
kind: LinkerOutputKind, outputDsymBundle: String): List<Command> {
|
||||
if (kind != LinkerOutputKind.EXECUTABLE) throw Error("Unsupported linker output kind")
|
||||
|
||||
// TODO(horsh): maybe rethink it.
|
||||
return listOf(object : Command() {
|
||||
override fun execute() {
|
||||
val src = File(objectFiles.single())
|
||||
val dst = File(executable)
|
||||
src.recursiveCopyTo(dst)
|
||||
javaScriptLink(libraries, executable)
|
||||
}
|
||||
|
||||
private fun javaScriptLink(jsFiles: List<String>, executable: String): String {
|
||||
val linkedJavaScript = File("$executable.js")
|
||||
|
||||
val linkerHeader = "var konan = { libraries: [] };\n"
|
||||
val linkerFooter = """|if (isBrowser()) {
|
||||
| konan.moduleEntry([]);
|
||||
|} else {
|
||||
| konan.moduleEntry(arguments);
|
||||
|}""".trimMargin()
|
||||
|
||||
linkedJavaScript.writeText(linkerHeader)
|
||||
|
||||
jsFiles.forEach {
|
||||
linkedJavaScript.appendBytes(File(it).readBytes())
|
||||
}
|
||||
|
||||
linkedJavaScript.appendBytes(linkerFooter.toByteArray())
|
||||
return linkedJavaScript.name
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
open class ZephyrLinker(targetProperties: ZephyrConfigurables)
|
||||
: LinkerFlags(targetProperties), ZephyrConfigurables by targetProperties {
|
||||
|
||||
private val linker = "$absoluteTargetToolchain/bin/ld"
|
||||
|
||||
override val useCompilerDriverAsLinker: Boolean get() = false
|
||||
|
||||
override fun filterStaticLibraries(binaries: List<String>) = emptyList<String>()
|
||||
|
||||
override fun linkCommands(objectFiles: List<ObjectFile>, executable: ExecutableFile,
|
||||
libraries: List<String>, linkerArgs: List<String>,
|
||||
optimize: Boolean, debug: Boolean,
|
||||
kind: LinkerOutputKind, outputDsymBundle: String): List<Command> {
|
||||
if (kind != LinkerOutputKind.EXECUTABLE) throw Error("Unsupported linker output kind: $kind")
|
||||
return listOf(Command(linker).apply {
|
||||
+listOf("-r", "--gc-sections", "--entry", "main")
|
||||
+listOf("-o", executable)
|
||||
+objectFiles
|
||||
+libraries
|
||||
+linkerArgs
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun linker(configurables: Configurables): LinkerFlags =
|
||||
when (configurables.target) {
|
||||
KonanTarget.LINUX_X64, KonanTarget.LINUX_ARM32_HFP ->
|
||||
LinuxBasedLinker(configurables as LinuxConfigurables)
|
||||
KonanTarget.LINUX_MIPS32, KonanTarget.LINUX_MIPSEL32 ->
|
||||
LinuxBasedLinker(configurables as LinuxMIPSConfigurables)
|
||||
KonanTarget.MACOS_X64, KonanTarget.IOS_ARM32, KonanTarget.IOS_ARM64, KonanTarget.IOS_X64 ->
|
||||
MacOSBasedLinker(configurables as AppleConfigurables)
|
||||
KonanTarget.ANDROID_ARM32, KonanTarget.ANDROID_ARM64 ->
|
||||
AndroidLinker(configurables as AndroidConfigurables)
|
||||
KonanTarget.MINGW_X64, KonanTarget.MINGW_X86 ->
|
||||
MingwLinker(configurables as MingwConfigurables)
|
||||
KonanTarget.WASM32 ->
|
||||
WasmLinker(configurables as WasmConfigurables)
|
||||
is KonanTarget.ZEPHYR ->
|
||||
ZephyrLinker(configurables as ZephyrConfigurables)
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.konan.target
|
||||
|
||||
import org.jetbrains.kotlin.konan.util.DependencyProcessor
|
||||
|
||||
class Platform(val configurables: Configurables)
|
||||
: Configurables by configurables {
|
||||
|
||||
val clang by lazy {
|
||||
ClangArgs(configurables)
|
||||
}
|
||||
val linker by lazy {
|
||||
linker(configurables)
|
||||
}
|
||||
}
|
||||
|
||||
class PlatformManager(distribution: Distribution = Distribution(), experimental: Boolean = false) :
|
||||
HostManager(distribution, experimental) {
|
||||
|
||||
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.getValue(target)
|
||||
val hostPlatform = platforms.getValue(host)
|
||||
|
||||
fun loader(target: KonanTarget) = loaders.getValue(target)
|
||||
}
|
||||
|
||||
@@ -1,64 +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.konan.properties
|
||||
|
||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove the whole file!
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.*
|
||||
|
||||
typealias Properties = java.util.Properties
|
||||
|
||||
fun File.loadProperties(): Properties {
|
||||
val properties = java.util.Properties()
|
||||
this.bufferedReader().use { reader ->
|
||||
properties.load(reader)
|
||||
}
|
||||
return properties
|
||||
}
|
||||
|
||||
fun loadProperties(path: String): Properties = File(path).loadProperties()
|
||||
|
||||
fun File.saveProperties(properties: Properties) {
|
||||
this.outputStream().use {
|
||||
properties.store(it, null)
|
||||
}
|
||||
}
|
||||
|
||||
fun Properties.saveToFile(file: File) = file.saveProperties(this)
|
||||
|
||||
fun Properties.propertyString(key: String, suffix: String? = null): String? = getProperty(key.suffix(suffix)) ?: this.getProperty(key)
|
||||
|
||||
/**
|
||||
* TODO: this method working with suffixes should be replaced with
|
||||
* functionality borrowed from def file parser and unified for interop tool
|
||||
* and kotlin compiler.
|
||||
*/
|
||||
fun Properties.propertyList(key: String, suffix: String? = null): List<String> {
|
||||
val value = this.getProperty(key.suffix(suffix)) ?: this.getProperty(key)
|
||||
if (value?.isBlank() == true) return emptyList()
|
||||
|
||||
return value?.split(Regex("\\s+")) ?: emptyList()
|
||||
}
|
||||
|
||||
fun Properties.hasProperty(key: String, suffix: String? = null): Boolean
|
||||
= this.getProperty(key.suffix(suffix)) != null
|
||||
|
||||
fun String.suffix(suf: String?): String =
|
||||
if (suf == null) this
|
||||
else "${this}.$suf"
|
||||
|
||||
|
||||
@@ -1,37 +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.konan.properties
|
||||
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
|
||||
fun Properties.hostString(name: String): String?
|
||||
= this.propertyString(name, HostManager.hostName)
|
||||
|
||||
fun Properties.hostList(name: String): List<String>
|
||||
= this.propertyList(name, HostManager.hostName)
|
||||
|
||||
fun Properties.targetString(name: String, target: KonanTarget): String?
|
||||
= this.propertyString(name, target.name)
|
||||
|
||||
fun Properties.targetList(name: String, target: KonanTarget): List<String>
|
||||
= this.propertyList(name, target.name)
|
||||
|
||||
fun Properties.hostTargetString(name: String, target: KonanTarget): String?
|
||||
= this.propertyString(name, hostTargetSuffix(HostManager.host, target))
|
||||
|
||||
fun Properties.hostTargetList(name: String, target: KonanTarget): List<String>
|
||||
= this.propertyList(name, hostTargetSuffix(HostManager.host, target))
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.konan.target
|
||||
|
||||
import org.jetbrains.kotlin.konan.KonanExternalToolFailure
|
||||
import org.jetbrains.kotlin.konan.exec.Command
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
|
||||
interface Xcode {
|
||||
val toolchain: String
|
||||
val macosxSdk: String
|
||||
val iphoneosSdk: String
|
||||
val iphonesimulatorSdk: String
|
||||
val version: String
|
||||
|
||||
companion object {
|
||||
val current: Xcode by lazy {
|
||||
CurrentXcode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private object CurrentXcode : Xcode {
|
||||
|
||||
override val toolchain by lazy {
|
||||
val ldPath = xcrun("-f", "ld") // = $toolchain/usr/bin/ld
|
||||
File(ldPath).parentFile.parentFile.parentFile.absolutePath
|
||||
}
|
||||
|
||||
override val macosxSdk by lazy { getSdkPath("macosx") }
|
||||
override val iphoneosSdk by lazy { getSdkPath("iphoneos") }
|
||||
override val iphonesimulatorSdk by lazy { getSdkPath("iphonesimulator") }
|
||||
|
||||
override val version by lazy {
|
||||
xcrun("xcodebuild", "-version")
|
||||
.removePrefix("Xcode ")
|
||||
}
|
||||
|
||||
private fun xcrun(vararg args: String): String =
|
||||
Command("/usr/bin/xcrun", *args).getOutputLines().first() // TODO: handle execution error
|
||||
|
||||
private fun getSdkPath(sdk: String) = xcrun("--sdk", sdk, "--show-sdk-path")
|
||||
}
|
||||
@@ -1,156 +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.konan.util
|
||||
|
||||
import java.io.File
|
||||
import java.io.StringReader
|
||||
import java.util.*
|
||||
|
||||
class DefFile(val file:File?, val config:DefFileConfig, val manifestAddendProperties:Properties, val defHeaderLines:List<String>) {
|
||||
private constructor(file0:File?, triple: Triple<Properties, Properties, List<String>>): this(file0, DefFileConfig(triple.first), triple.second, triple.third)
|
||||
constructor(file:File?, substitutions: Map<String, String>) : this(file, parseDefFile(file, substitutions))
|
||||
|
||||
val name by lazy {
|
||||
file?.nameWithoutExtension ?: ""
|
||||
}
|
||||
class DefFileConfig(private val properties: Properties) {
|
||||
val headers by lazy {
|
||||
properties.getSpaceSeparated("headers")
|
||||
}
|
||||
|
||||
val modules by lazy {
|
||||
properties.getSpaceSeparated("modules")
|
||||
}
|
||||
|
||||
val language by lazy {
|
||||
properties.getProperty("language")
|
||||
}
|
||||
|
||||
val compilerOpts by lazy {
|
||||
properties.getSpaceSeparated("compilerOpts")
|
||||
}
|
||||
|
||||
val excludeSystemLibs by lazy {
|
||||
properties.getProperty("excludeSystemLibs")?.toBoolean() ?: false
|
||||
}
|
||||
|
||||
val excludeDependentModules by lazy {
|
||||
properties.getProperty("excludeDependentModules")?.toBoolean() ?: false
|
||||
}
|
||||
|
||||
val entryPoints by lazy {
|
||||
properties.getSpaceSeparated("entryPoint")
|
||||
}
|
||||
|
||||
val linkerOpts by lazy {
|
||||
properties.getSpaceSeparated("linkerOpts")
|
||||
}
|
||||
|
||||
val linker by lazy {
|
||||
properties.getProperty("linker", "clang")
|
||||
}
|
||||
|
||||
val excludedFunctions by lazy {
|
||||
properties.getSpaceSeparated("excludedFunctions")
|
||||
}
|
||||
|
||||
val excludedMacros by lazy {
|
||||
properties.getSpaceSeparated("excludedMacros")
|
||||
}
|
||||
|
||||
val staticLibraries by lazy {
|
||||
properties.getSpaceSeparated("staticLibraries")
|
||||
}
|
||||
|
||||
val libraryPaths by lazy {
|
||||
properties.getSpaceSeparated("libraryPaths")
|
||||
}
|
||||
|
||||
val packageName by lazy {
|
||||
properties.getProperty("package")
|
||||
}
|
||||
|
||||
val headerFilter by lazy {
|
||||
properties.getSpaceSeparated("headerFilter")
|
||||
}
|
||||
|
||||
val strictEnums by lazy {
|
||||
properties.getSpaceSeparated("strictEnums")
|
||||
}
|
||||
|
||||
val nonStrictEnums by lazy {
|
||||
properties.getSpaceSeparated("nonStrictEnums")
|
||||
}
|
||||
|
||||
val noStringConversion by lazy {
|
||||
properties.getSpaceSeparated("noStringConversion")
|
||||
}
|
||||
|
||||
val depends by lazy {
|
||||
properties.getSpaceSeparated("depends")
|
||||
}
|
||||
|
||||
val exportForwardDeclarations by lazy {
|
||||
properties.getSpaceSeparated("exportForwardDeclarations")
|
||||
}
|
||||
|
||||
val disableDesignatedInitializerChecks by lazy {
|
||||
properties.getProperty("disableDesignatedInitializerChecks")?.toBoolean() ?: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Properties.getSpaceSeparated(name: String): List<String> {
|
||||
return this.getProperty(name)?.split(' ')?.filter { it.isNotEmpty() } ?: emptyList()
|
||||
}
|
||||
|
||||
private fun parseDefFile(file: File?, substitutions: Map<String, String>): Triple<Properties, Properties, List<String>> {
|
||||
val properties = Properties()
|
||||
|
||||
if (file == null) {
|
||||
return Triple(properties, Properties(), emptyList())
|
||||
}
|
||||
|
||||
val lines = file.readLines()
|
||||
|
||||
val separator = "---"
|
||||
val separatorIndex = lines.indexOf(separator)
|
||||
|
||||
val propertyLines: List<String>
|
||||
val headerLines: List<String>
|
||||
|
||||
if (separatorIndex != -1) {
|
||||
propertyLines = lines.subList(0, separatorIndex)
|
||||
headerLines = lines.subList(separatorIndex + 1, lines.size)
|
||||
} else {
|
||||
propertyLines = lines
|
||||
headerLines = emptyList()
|
||||
}
|
||||
|
||||
val propertiesReader = StringReader(propertyLines.joinToString(System.lineSeparator()))
|
||||
properties.load(propertiesReader)
|
||||
|
||||
// Pass unsubstituted copy of properties we have obtained from `.def`
|
||||
// to compiler `-maniest`.
|
||||
val manifestAddendProperties = properties.duplicate()
|
||||
|
||||
substitute(properties, substitutions)
|
||||
|
||||
return Triple(properties, manifestAddendProperties, headerLines)
|
||||
}
|
||||
|
||||
private fun Properties.duplicate() = Properties().apply { putAll(this@duplicate) }
|
||||
@@ -1,221 +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.konan.util
|
||||
|
||||
import java.io.*
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.net.URLConnection
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
import java.util.concurrent.*
|
||||
|
||||
typealias ProgressCallback = (url: String, currentBytes: Long, totalBytes: Long) -> Unit
|
||||
|
||||
class DependencyDownloader(
|
||||
var maxAttempts: Int = DEFAULT_MAX_ATTEMPTS,
|
||||
var attemptIntervalMs: Long = DEFAULT_ATTEMPT_INTERVAL_MS,
|
||||
customProgressCallback: ProgressCallback? = null
|
||||
) {
|
||||
|
||||
private val progressCallback = customProgressCallback ?: { url, currentBytes, totalBytes ->
|
||||
print("\rDownloading dependency: $url (${currentBytes.humanReadable}/${totalBytes.humanReadable}). ")
|
||||
}
|
||||
|
||||
val executor = ExecutorCompletionService<Unit>(Executors.newSingleThreadExecutor(object : ThreadFactory {
|
||||
override fun newThread(r: Runnable?): Thread {
|
||||
val thread = Thread(r)
|
||||
thread.name = "konan-dependency-downloader"
|
||||
thread.isDaemon = true
|
||||
|
||||
return thread
|
||||
}
|
||||
}))
|
||||
|
||||
enum class ReplacingMode {
|
||||
/** Redownload the file and replace the existing one. */
|
||||
REPLACE,
|
||||
/** Throw FileAlreadyExistsException */
|
||||
THROW,
|
||||
/** Don't download the file and return the existing one*/
|
||||
RETURN_EXISTING
|
||||
}
|
||||
|
||||
class HTTPResponseException(val url: URL, val responseCode: Int)
|
||||
: IOException("Server returned HTTP response code: $responseCode for URL: $url")
|
||||
|
||||
class DownloadingProgress(@Volatile var currentBytes: Long) {
|
||||
fun update(readBytes: Int) { currentBytes += readBytes }
|
||||
}
|
||||
|
||||
private fun HttpURLConnection.checkHTTPResponse(expected: Int, originalUrl: URL = url) {
|
||||
if (responseCode != expected) {
|
||||
throw HTTPResponseException(originalUrl, responseCode)
|
||||
}
|
||||
}
|
||||
|
||||
private fun HttpURLConnection.checkHTTPResponse(originalUrl: URL, predicate: (Int) -> Boolean) {
|
||||
if (!predicate(responseCode)) {
|
||||
throw HTTPResponseException(originalUrl, responseCode)
|
||||
}
|
||||
}
|
||||
|
||||
private fun doDownload(originalUrl: URL,
|
||||
connection: URLConnection,
|
||||
tmpFile: File,
|
||||
currentBytes: Long,
|
||||
totalBytes: Long,
|
||||
append: Boolean) {
|
||||
val progress = DownloadingProgress(currentBytes)
|
||||
|
||||
// TODO: Implement multi-thread downloading.
|
||||
executor.submit {
|
||||
connection.getInputStream().use { from ->
|
||||
FileOutputStream(tmpFile, append).use { to ->
|
||||
val buffer = ByteArray(DEFAULT_BUFFER_SIZE)
|
||||
var read = from.read(buffer)
|
||||
while (read != -1) {
|
||||
if (Thread.interrupted()) {
|
||||
throw InterruptedException()
|
||||
}
|
||||
to.write(buffer, 0, read)
|
||||
progress.update(read)
|
||||
read = from.read(buffer)
|
||||
}
|
||||
if (progress.currentBytes != totalBytes) {
|
||||
throw EOFException("The stream closed before end of downloading.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var result: Future<Unit>?
|
||||
do {
|
||||
progressCallback(originalUrl.toString(), progress.currentBytes, totalBytes)
|
||||
result = executor.poll(1, TimeUnit.SECONDS)
|
||||
} while(result == null)
|
||||
progressCallback(originalUrl.toString(), progress.currentBytes, totalBytes)
|
||||
|
||||
try {
|
||||
result.get()
|
||||
} catch (e: ExecutionException) {
|
||||
throw e.cause ?: e
|
||||
}
|
||||
}
|
||||
|
||||
private fun resumeDownload(originalUrl: URL, originalConnection: HttpURLConnection, tmpFile: File) {
|
||||
originalConnection.connect()
|
||||
val totalBytes = originalConnection.contentLengthLong
|
||||
val currentBytes = tmpFile.length()
|
||||
if (currentBytes >= totalBytes || originalConnection.getHeaderField("Accept-Ranges") != "bytes") {
|
||||
// The temporary file is bigger then expected or the server doesn't support resuming downloading.
|
||||
// Download the file from scratch.
|
||||
doDownload(originalUrl, originalConnection, tmpFile, 0, totalBytes, false)
|
||||
} else {
|
||||
originalConnection.disconnect()
|
||||
val rangeConnection = originalUrl.openConnection() as HttpURLConnection
|
||||
rangeConnection.setRequestProperty("range", "bytes=$currentBytes-")
|
||||
rangeConnection.connect()
|
||||
rangeConnection.checkHTTPResponse(originalUrl) {
|
||||
it == HttpURLConnection.HTTP_PARTIAL || it == HttpURLConnection.HTTP_OK
|
||||
}
|
||||
doDownload(originalUrl, rangeConnection, tmpFile, currentBytes, totalBytes, true)
|
||||
}
|
||||
}
|
||||
|
||||
/** Performs an attempt to download a specified file into the specified location */
|
||||
private fun tryDownload(url: URL, tmpFile: File) {
|
||||
val connection = url.openConnection()
|
||||
|
||||
(connection as? HttpURLConnection)?.checkHTTPResponse(HttpURLConnection.HTTP_OK, url)
|
||||
|
||||
if (connection is HttpURLConnection && tmpFile.exists()) {
|
||||
resumeDownload(url, connection, tmpFile)
|
||||
} else {
|
||||
connection.connect()
|
||||
val totalBytes = connection.contentLengthLong
|
||||
doDownload(url, connection, tmpFile, 0, totalBytes, false)
|
||||
}
|
||||
}
|
||||
|
||||
/** Downloads a file from [source] url to [destination]. Returns [destination]. */
|
||||
fun download(source: URL,
|
||||
destination: File,
|
||||
replace: ReplacingMode = ReplacingMode.RETURN_EXISTING): File {
|
||||
|
||||
if (destination.exists()) {
|
||||
when (replace) {
|
||||
ReplacingMode.RETURN_EXISTING -> return destination
|
||||
ReplacingMode.THROW -> throw FileAlreadyExistsException(destination)
|
||||
ReplacingMode.REPLACE -> Unit // Just continue with downloading.
|
||||
}
|
||||
}
|
||||
val tmpFile = File("${destination.canonicalPath}.$TMP_SUFFIX")
|
||||
|
||||
check(!tmpFile.isDirectory) {
|
||||
"A temporary file is a directory: ${tmpFile.canonicalPath}. Remove it and try again."
|
||||
}
|
||||
check(!destination.isDirectory) {
|
||||
"The destination file is a directory: ${destination.canonicalPath}. Remove it and try again."
|
||||
}
|
||||
|
||||
var attempt = 1
|
||||
var waitTime = 0L
|
||||
while (true) {
|
||||
try {
|
||||
tryDownload(source, tmpFile)
|
||||
break
|
||||
} catch (e: HTTPResponseException) {
|
||||
throw e
|
||||
} catch (e: IOException) {
|
||||
if (attempt >= maxAttempts) {
|
||||
throw e
|
||||
}
|
||||
attempt++
|
||||
waitTime += attemptIntervalMs
|
||||
println("Cannot download a dependency: $e\n" +
|
||||
"Waiting ${waitTime.toDouble() / 1000} sec and trying again (attempt: $attempt/$maxAttempts).")
|
||||
// TODO: Wait better
|
||||
Thread.sleep(waitTime)
|
||||
}
|
||||
}
|
||||
|
||||
Files.move(tmpFile.toPath(), destination.toPath(), StandardCopyOption.REPLACE_EXISTING)
|
||||
println("Done.")
|
||||
return destination
|
||||
}
|
||||
|
||||
private val Long.humanReadable: String
|
||||
get() {
|
||||
if (this < 0) {
|
||||
return "-"
|
||||
}
|
||||
if (this < 1024) {
|
||||
return "$this bytes"
|
||||
}
|
||||
val exp = (Math.log(this.toDouble()) / Math.log(1024.0)).toInt()
|
||||
val prefix = "kMGTPE"[exp-1]
|
||||
return "%.1f %siB".format(this / Math.pow(1024.0, exp.toDouble()), prefix)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DEFAULT_MAX_ATTEMPTS = 10
|
||||
const val DEFAULT_ATTEMPT_INTERVAL_MS = 3000L
|
||||
|
||||
const val TMP_SUFFIX = "part"
|
||||
}
|
||||
}
|
||||
@@ -1,68 +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.konan.util
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.unzipTo
|
||||
import java.io.File
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
class DependencyExtractor {
|
||||
internal val useZip = System.getProperty("os.name").startsWith("Windows")
|
||||
|
||||
internal val archiveExtension = if (useZip) {
|
||||
"zip"
|
||||
} else {
|
||||
"tar.gz"
|
||||
}
|
||||
|
||||
private fun extractTarGz(tarGz: File, targetDirectory: File) {
|
||||
val tarProcess = ProcessBuilder().apply {
|
||||
command("tar", "-xzf", tarGz.canonicalPath)
|
||||
directory(targetDirectory)
|
||||
inheritIO()
|
||||
}.start()
|
||||
val finished = tarProcess.waitFor(extractionTimeout, extractionTimeoutUntis)
|
||||
when {
|
||||
finished && tarProcess.exitValue() != 0 ->
|
||||
throw RuntimeException(
|
||||
"Cannot extract archive with dependency: ${tarGz.canonicalPath}.\n" +
|
||||
"Tar exit code: ${tarProcess.exitValue()}."
|
||||
)
|
||||
!finished -> {
|
||||
tarProcess.destroy()
|
||||
throw RuntimeException(
|
||||
"Cannot extract archive with dependency: ${tarGz.canonicalPath}.\n" +
|
||||
"Tar process hasn't finished in ${extractionTimeoutUntis.toSeconds(extractionTimeout)} sec.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun extract(archive: File, targetDirectory: File) {
|
||||
if (useZip) {
|
||||
archive.toPath().unzipTo(targetDirectory.toPath())
|
||||
} else {
|
||||
extractTarGz(archive, targetDirectory)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val extractionTimeout = 3600L
|
||||
val extractionTimeoutUntis = TimeUnit.SECONDS
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,307 +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.konan.util
|
||||
|
||||
import org.jetbrains.kotlin.konan.file.use
|
||||
import org.jetbrains.kotlin.konan.properties.KonanPropertiesLoader
|
||||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
import org.jetbrains.kotlin.konan.properties.propertyList
|
||||
import java.io.File
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.RandomAccessFile
|
||||
import java.net.InetAddress
|
||||
import java.net.URL
|
||||
import java.net.UnknownHostException
|
||||
import java.nio.file.Paths
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.concurrent.withLock
|
||||
|
||||
private val Properties.dependenciesUrl : String
|
||||
get() = getProperty("dependenciesUrl")
|
||||
?: throw IllegalStateException("No such property in konan.properties: dependenciesUrl")
|
||||
|
||||
private val Properties.airplaneMode : Boolean
|
||||
get() = getProperty("airplaneMode")?.toBoolean() ?: false
|
||||
|
||||
private val Properties.downloadingAttempts : Int
|
||||
get() = getProperty("downloadingAttempts")?.toInt()
|
||||
?: DependencyDownloader.DEFAULT_MAX_ATTEMPTS
|
||||
|
||||
private val Properties.downloadingAttemptIntervalMs : Long
|
||||
get() = getProperty("downloadingAttemptPauseMs")?.toLong()
|
||||
?: DependencyDownloader.DEFAULT_ATTEMPT_INTERVAL_MS
|
||||
|
||||
private fun Properties.findCandidates(dependencies: List<String>): Map<String, List<DependencySource>> {
|
||||
val dependencyProfiles = this.propertyList("dependencyProfiles")
|
||||
return dependencies.map { dependency ->
|
||||
dependency to dependencyProfiles.flatMap { profile ->
|
||||
val candidateSpecs = propertyList("$dependency.$profile")
|
||||
if (profile == "default" && candidateSpecs.isEmpty()) {
|
||||
listOf(DependencySource.Remote.Public)
|
||||
} else {
|
||||
candidateSpecs.map { candidateSpec ->
|
||||
when (candidateSpec) {
|
||||
"remote:public" -> DependencySource.Remote.Public
|
||||
"remote:internal" -> DependencySource.Remote.Internal
|
||||
else -> DependencySource.Local(File(candidateSpec))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.toMap()
|
||||
}
|
||||
|
||||
|
||||
private val KonanPropertiesLoader.dependenciesUrl : String get() = properties.dependenciesUrl
|
||||
private val KonanPropertiesLoader.airplaneMode : Boolean get() = properties.airplaneMode
|
||||
private val KonanPropertiesLoader.downloadingAttempts : Int get() = properties.downloadingAttempts
|
||||
private val KonanPropertiesLoader.downloadingAttemptIntervalMs : Long get() = properties.downloadingAttemptIntervalMs
|
||||
|
||||
sealed class DependencySource {
|
||||
data class Local(val path: File) : DependencySource()
|
||||
|
||||
sealed class Remote : DependencySource() {
|
||||
object Public : Remote()
|
||||
object Internal : Remote()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspects [dependencies] and downloads all the missing ones into [dependenciesDirectory] from [dependenciesUrl].
|
||||
* If [airplaneMode] is true will throw a RuntimeException instead of downloading.
|
||||
*/
|
||||
class DependencyProcessor(dependenciesRoot: File,
|
||||
val dependenciesUrl: String,
|
||||
dependencyToCandidates: Map<String, List<DependencySource>>,
|
||||
homeDependencyCache: File = defaultDependencyCacheDir,
|
||||
val airplaneMode: Boolean = false,
|
||||
maxAttempts: Int = DependencyDownloader.DEFAULT_MAX_ATTEMPTS,
|
||||
attemptIntervalMs: Long = DependencyDownloader.DEFAULT_ATTEMPT_INTERVAL_MS,
|
||||
customProgressCallback: ProgressCallback? = null,
|
||||
val keepUnstable: Boolean = true,
|
||||
val deleteArchives: Boolean = true) {
|
||||
|
||||
val dependenciesDirectory = dependenciesRoot.apply { mkdirs() }
|
||||
val cacheDirectory = homeDependencyCache.apply { mkdirs() }
|
||||
|
||||
val lockFile = File(cacheDirectory, ".lock").apply { if (!exists()) createNewFile() }
|
||||
|
||||
var showInfo = true
|
||||
private var isInfoShown = false
|
||||
|
||||
private val downloader = DependencyDownloader(maxAttempts, attemptIntervalMs, customProgressCallback)
|
||||
private val extractor = DependencyExtractor()
|
||||
|
||||
private val archiveExtension get() = extractor.archiveExtension
|
||||
|
||||
constructor(dependenciesRoot: File,
|
||||
properties: KonanPropertiesLoader,
|
||||
dependenciesUrl: String = properties.dependenciesUrl,
|
||||
keepUnstable:Boolean = true) : this(
|
||||
dependenciesRoot,
|
||||
properties.properties,
|
||||
properties.dependencies,
|
||||
dependenciesUrl,
|
||||
keepUnstable = keepUnstable)
|
||||
|
||||
constructor(dependenciesRoot: File,
|
||||
properties: Properties,
|
||||
dependencies: List<String>,
|
||||
dependenciesUrl: String = properties.dependenciesUrl,
|
||||
keepUnstable:Boolean = true) : this(
|
||||
dependenciesRoot,
|
||||
dependenciesUrl,
|
||||
dependencyToCandidates = properties.findCandidates(dependencies),
|
||||
airplaneMode = properties.airplaneMode,
|
||||
maxAttempts = properties.downloadingAttempts,
|
||||
attemptIntervalMs = properties.downloadingAttemptIntervalMs,
|
||||
keepUnstable = keepUnstable)
|
||||
|
||||
|
||||
class DependencyFile(directory: File, fileName: String) {
|
||||
val file = File(directory, fileName).apply { createNewFile() }
|
||||
private val dependencies = file.readLines().toMutableSet()
|
||||
|
||||
fun contains(dependency: String) = dependencies.contains(dependency)
|
||||
fun add(dependency: String) = dependencies.add(dependency)
|
||||
fun remove(dependency: String) = dependencies.remove(dependency)
|
||||
|
||||
fun removeAndSave(dependency: String) {
|
||||
remove(dependency)
|
||||
save()
|
||||
}
|
||||
|
||||
fun addAndSave(dependency: String) {
|
||||
add(dependency)
|
||||
save()
|
||||
}
|
||||
|
||||
fun save() {
|
||||
val writer = file.writer()
|
||||
writer.use {
|
||||
dependencies.forEach {
|
||||
writer.write(it)
|
||||
writer.write("\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun downloadDependency(dependency: String, baseUrl: String) {
|
||||
val depDir = File(dependenciesDirectory, dependency)
|
||||
val depName = depDir.name
|
||||
|
||||
val fileName = "$depName.$archiveExtension"
|
||||
val archive = cacheDirectory.resolve(fileName)
|
||||
val url = URL("$baseUrl/$fileName")
|
||||
|
||||
val extractedDependencies = DependencyFile(dependenciesDirectory, ".extracted")
|
||||
if (extractedDependencies.contains(depName) &&
|
||||
depDir.exists() &&
|
||||
depDir.isDirectory &&
|
||||
depDir.list().isNotEmpty()) {
|
||||
|
||||
if (!keepUnstable && depDir.list().contains(".unstable")) {
|
||||
// The downloaded version of the dependency is unstable -> redownload it.
|
||||
depDir.deleteRecursively()
|
||||
archive.delete()
|
||||
extractedDependencies.removeAndSave(dependency)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (showInfo && !isInfoShown) {
|
||||
println("Downloading native dependencies (LLVM, sysroot etc). This is a one-time action performed only on the first run of the compiler.")
|
||||
isInfoShown = true
|
||||
}
|
||||
|
||||
if (!archive.exists()) {
|
||||
if (airplaneMode) {
|
||||
throw FileNotFoundException("""
|
||||
Cannot find a dependency locally: $dependency.
|
||||
Set `airplaneMode = false` in konan.properties to download it.
|
||||
""".trimIndent())
|
||||
}
|
||||
downloader.download(url, archive)
|
||||
}
|
||||
println("Extracting dependency: $archive into $dependenciesDirectory")
|
||||
extractor.extract(archive, dependenciesDirectory)
|
||||
if (deleteArchives) {
|
||||
archive.delete()
|
||||
}
|
||||
extractedDependencies.addAndSave(depName)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val lock = ReentrantLock()
|
||||
|
||||
val localKonanDir: File by lazy {
|
||||
File(System.getenv("KONAN_DATA_DIR") ?: (System.getProperty("user.home") + File.separator + ".konan"))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val defaultDependenciesRoot: File
|
||||
get() = localKonanDir.resolve("dependencies")
|
||||
|
||||
val defaultDependencyCacheDir: File
|
||||
get() = localKonanDir.resolve("cache")
|
||||
}
|
||||
|
||||
private val resolvedDependencies = dependencyToCandidates.map { (dependency, candidates) ->
|
||||
val candidate = candidates.asSequence().mapNotNull { candidate ->
|
||||
when (candidate) {
|
||||
is DependencySource.Local -> candidate.takeIf { it.path.exists() }
|
||||
DependencySource.Remote.Public -> candidate
|
||||
DependencySource.Remote.Internal -> candidate.takeIf { InternalServer.isAvailable }
|
||||
}
|
||||
}.firstOrNull()
|
||||
|
||||
candidate ?: error("$dependency is not available; candidates:\n${candidates.joinToString("\n")}")
|
||||
|
||||
dependency to candidate
|
||||
}.toMap()
|
||||
|
||||
private fun resolveDependency(dependency: String): File {
|
||||
val candidate = resolvedDependencies[dependency]
|
||||
return when (candidate) {
|
||||
is DependencySource.Local -> candidate.path
|
||||
is DependencySource.Remote -> File(dependenciesDirectory, dependency)
|
||||
null -> error("$dependency not declared as dependency")
|
||||
}
|
||||
}
|
||||
|
||||
fun resolveRelative(relative: String): File {
|
||||
val path = Paths.get(relative)
|
||||
if (path.isAbsolute) error("not a relative path: $relative")
|
||||
|
||||
val dependency = path.first().toString()
|
||||
return resolveDependency(dependency).let {
|
||||
if (path.nameCount > 1) {
|
||||
it.toPath().resolve(path.subpath(1, path.nameCount)).toFile()
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun run() = lock.withLock {
|
||||
RandomAccessFile(lockFile, "rw").channel.lock().use {
|
||||
resolvedDependencies.forEach { (dependency, candidate) ->
|
||||
val baseUrl = when (candidate) {
|
||||
is DependencySource.Local -> null
|
||||
DependencySource.Remote.Public -> dependenciesUrl
|
||||
DependencySource.Remote.Internal -> InternalServer.url
|
||||
}
|
||||
// TODO: consider using different caches for different remotes.
|
||||
if (baseUrl != null) {
|
||||
downloadDependency(dependency, baseUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal object InternalServer {
|
||||
private val host = "repo.labs.intellij.net"
|
||||
val url = "http://$host/kotlin-native"
|
||||
|
||||
private val internalDomain = "labs.intellij.net"
|
||||
|
||||
val isAvailable by lazy {
|
||||
val envKey = "KONAN_USE_INTERNAL_SERVER"
|
||||
val envValue = System.getenv(envKey)
|
||||
when (envValue) {
|
||||
"0" -> false
|
||||
"1" -> true
|
||||
null -> checkAccessible()
|
||||
else -> error("unexpected environment: $envKey=$envValue")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAccessible() = try {
|
||||
if (!InetAddress.getLocalHost().canonicalHostName.endsWith(".$internalDomain")) {
|
||||
// Fast path:
|
||||
false
|
||||
} else {
|
||||
InetAddress.getByName(host)
|
||||
true
|
||||
}
|
||||
} catch (e: UnknownHostException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
@@ -1,33 +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.konan.util
|
||||
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class Helper0(val dependenciesDir: String,
|
||||
val properties: Properties,
|
||||
val dependencies: List<String>): Runnable {
|
||||
|
||||
override fun run() {
|
||||
DependencyProcessor(File(dependenciesDir),
|
||||
properties,
|
||||
dependencies,
|
||||
properties.getProperty("dependenciesUrl", "https://download.jetbrains.com/kotlin/native")
|
||||
).run()
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package org.jetbrains.kotlin.konan.util
|
||||
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import java.util.*
|
||||
|
||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove the whole file!
|
||||
|
||||
fun defaultTargetSubstitutions(target: KonanTarget) =
|
||||
mapOf<String, String>(
|
||||
"target" to target.visibleName,
|
||||
"arch" to target.architecture.visibleName,
|
||||
"family" to target.family.visibleName)
|
||||
|
||||
// Performs substitution similar to:
|
||||
// foo = ${foo} ${foo.${arch}} ${foo.${os}}
|
||||
fun substitute(properties: Properties, substitutions: Map<String, String>) {
|
||||
for (key in properties.stringPropertyNames()) {
|
||||
for (substitution in substitutions.values) {
|
||||
val suffix = ".$substitution"
|
||||
if (key.endsWith(suffix)) {
|
||||
val baseKey = key.removeSuffix(suffix)
|
||||
val oldValue = properties.getProperty(baseKey, "")
|
||||
val appendedValue = properties.getProperty(key, "")
|
||||
val newValue = if (oldValue != "") "$oldValue $appendedValue" else appendedValue
|
||||
properties.setProperty(baseKey, newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package org.jetbrains.kotlin.konan.util
|
||||
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import java.io.File
|
||||
|
||||
fun DefFile(file: File?, target: KonanTarget) = DefFile(file, defaultTargetSubstitutions(target))
|
||||
@@ -1,61 +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.konan.util
|
||||
|
||||
import kotlin.system.measureTimeMillis
|
||||
import org.jetbrains.kotlin.konan.file.*
|
||||
|
||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove this function:
|
||||
fun <T> printMillisec(message: String, body: () -> T): T {
|
||||
var result: T? = null
|
||||
val msec = measureTimeMillis{
|
||||
result = body()
|
||||
}
|
||||
println("$message: $msec msec")
|
||||
return result!!
|
||||
}
|
||||
|
||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove this function:
|
||||
fun profile(message: String, body: () -> Unit) = profileIf(
|
||||
System.getProperty("konan.profile")?.equals("true") ?: false,
|
||||
message, body)
|
||||
|
||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: remove this function:
|
||||
fun profileIf(condition: Boolean, message: String, body: () -> Unit) =
|
||||
if (condition) printMillisec(message, body) else body()
|
||||
|
||||
fun nTabs(amount: Int): String {
|
||||
return String.format("%1$-${(amount+1)*4}s", "")
|
||||
}
|
||||
|
||||
fun String.prefixIfNot(prefix: String) =
|
||||
if (this.startsWith(prefix)) this else "$prefix$this"
|
||||
|
||||
fun String.prefixBaseNameIfNot(prefix: String): String {
|
||||
val file = File(this).absoluteFile
|
||||
val name = file.name
|
||||
val directory = file.parent
|
||||
return "$directory/${name.prefixIfNot(prefix)}"
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
fun <T> Lazy<T>.getValueOrNull(): T? = if (isInitialized()) value else null
|
||||
@@ -1,10 +0,0 @@
|
||||
package org.jetbrains.kotlin.konan.util
|
||||
|
||||
typealias Logger = (String) -> Unit
|
||||
|
||||
interface WithLogger {
|
||||
val logger: Logger
|
||||
}
|
||||
|
||||
fun dummyLogger(message: String) {}
|
||||
|
||||
@@ -82,6 +82,9 @@ repositories {
|
||||
maven {
|
||||
url kotlinCompilerRepo
|
||||
}
|
||||
maven {
|
||||
url sharedRepo
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
@@ -102,7 +105,8 @@ dependencies {
|
||||
bundleDependencies "org.jetbrains.kotlin:kotlin-serialization:$kotlinVersion"
|
||||
bundleDependencies "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
bundleDependencies "org.jetbrains.kotlin:kotlin-gradle-plugin-api:$kotlinVersion"
|
||||
bundleDependencies "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion"
|
||||
bundleDependencies "org.jetbrains.kotlin:kotlin-native-shared:$sharedVersion"
|
||||
bundleDependencies "org.jetbrains.kotlin:kotlin-native-version"
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation "org.jetbrains.kotlin:kotlin-test:$buildKotlinVersion"
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
rootProject.name = "kotlin-native-gradle-plugin"
|
||||
includeBuild '../../shared'
|
||||
includeBuild '../../version'
|
||||
+4
-1
@@ -24,6 +24,8 @@ import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.jetbrains.kotlin.gradle.plugin.tasks.KonanArtifactWithLibrariesTask
|
||||
import org.jetbrains.kotlin.gradle.plugin.tasks.KonanBuildingTask
|
||||
import org.jetbrains.kotlin.konan.CURRENT
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.library.SearchPathResolver
|
||||
import org.jetbrains.kotlin.konan.library.defaultResolver
|
||||
import org.jetbrains.kotlin.konan.target.Distribution
|
||||
@@ -146,7 +148,8 @@ open class KonanLibrariesSpec(val task: KonanArtifactWithLibrariesTask, val proj
|
||||
defaultResolver(
|
||||
repos.map { it.absolutePath },
|
||||
task.konanTarget,
|
||||
Distribution(konanHomeOverride = project.konanHome)
|
||||
Distribution(konanHomeOverride = project.konanHome),
|
||||
listOf(KonanVersion.CURRENT)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
+1
@@ -34,6 +34,7 @@ import org.gradle.util.GradleVersion
|
||||
import org.jetbrains.kotlin.gradle.plugin.konan.KonanPlugin.Companion.COMPILE_ALL_TASK_NAME
|
||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanToolingModelBuilder
|
||||
import org.jetbrains.kotlin.gradle.plugin.tasks.*
|
||||
import org.jetbrains.kotlin.konan.CURRENT
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.parseKonanVersion
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
|
||||
+4
-1
@@ -25,6 +25,8 @@ import org.gradle.process.CommandLineArgumentProvider
|
||||
import org.jetbrains.kotlin.gradle.plugin.konan.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifactImpl
|
||||
import org.jetbrains.kotlin.konan.CURRENT
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.library.defaultResolver
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.Distribution
|
||||
@@ -234,7 +236,8 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec {
|
||||
val resolver = defaultResolver(
|
||||
repos.map { it.absolutePath },
|
||||
konanTarget,
|
||||
Distribution(konanHomeOverride = project.konanHome)
|
||||
Distribution(konanHomeOverride = project.konanHome),
|
||||
listOf(KonanVersion.CURRENT)
|
||||
)
|
||||
|
||||
return KonanModelArtifactImpl(
|
||||
|
||||
+4
-1
@@ -27,6 +27,8 @@ import org.jetbrains.kotlin.gradle.plugin.konan.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.konan.KonanInteropSpec.IncludeDirectoriesSpec
|
||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact
|
||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifactImpl
|
||||
import org.jetbrains.kotlin.konan.CURRENT
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.library.defaultResolver
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.Distribution
|
||||
@@ -171,7 +173,8 @@ open class KonanInteropTask @Inject constructor(val workerExecutor: WorkerExecut
|
||||
val resolver = defaultResolver(
|
||||
repos.map { it.absolutePath },
|
||||
konanTarget,
|
||||
Distribution(konanHomeOverride = project.konanHome)
|
||||
Distribution(konanHomeOverride = project.konanHome),
|
||||
listOf(KonanVersion.CURRENT)
|
||||
)
|
||||
|
||||
return KonanModelArtifactImpl(
|
||||
|
||||
+1
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.gradle.plugin.konan.konanArtifactsContainer
|
||||
import org.jetbrains.kotlin.gradle.plugin.konan.konanExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.konan.konanHome
|
||||
import org.jetbrains.kotlin.gradle.plugin.konan.konanVersion
|
||||
import org.jetbrains.kotlin.konan.CURRENT
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import java.io.File
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.gradle.testfixtures.ProjectBuilder
|
||||
import org.jetbrains.kotlin.gradle.plugin.konan.KonanPlugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.konan.konanArtifactsContainer
|
||||
import org.jetbrains.kotlin.gradle.plugin.model.KonanToolingModelBuilder
|
||||
import org.jetbrains.kotlin.konan.CURRENT
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.junit.Rule
|
||||
import org.junit.rules.TemporaryFolder
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
package org.jetbrains.kotlin.cli.utilities
|
||||
|
||||
import org.jetbrains.kotlin.konan.CURRENT
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.konan.target.PlatformManager
|
||||
import org.jetbrains.kotlin.konan.library.*
|
||||
@@ -11,6 +12,7 @@ import org.jetbrains.kotlin.konan.target.Distribution
|
||||
import org.jetbrains.kotlin.native.interop.gen.jvm.interop
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kliopt.ArgParser
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.native.interop.tool.*
|
||||
|
||||
// TODO: this function should eventually be eliminated from 'utilities'.
|
||||
@@ -48,7 +50,8 @@ fun invokeInterop(flavor: String, args: Array<String>): Array<String>? {
|
||||
repos,
|
||||
libraries.filter { it.contains(File.separator) },
|
||||
target,
|
||||
Distribution()
|
||||
Distribution(),
|
||||
listOf(KonanVersion.CURRENT)
|
||||
).libraryResolver()
|
||||
val allLibraries = resolver.resolveWithDependencies(
|
||||
libraries.toUnresolvedLibraries, noStdLib = true, noDefaultLibs = noDefaultLibs
|
||||
|
||||
@@ -32,6 +32,9 @@ repositories {
|
||||
maven {
|
||||
url buildKotlinCompilerRepo
|
||||
}
|
||||
maven {
|
||||
url sharedRepo
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(ddol): KLIB-REFACTORING-CLEANUP: drop generation of KonanVersion!
|
||||
@@ -39,8 +42,6 @@ task generateCompilerVersion(type: VersionGenerator){}
|
||||
|
||||
sourceSets {
|
||||
main.kotlin {
|
||||
srcDir 'src/main/kotlin'
|
||||
srcDir 'src/library/kotlin'
|
||||
srcDir generateCompilerVersion.versionSourceDirectory
|
||||
}
|
||||
}
|
||||
@@ -57,9 +58,10 @@ clean {
|
||||
}
|
||||
|
||||
jar {
|
||||
archiveName = "shared.jar"
|
||||
archiveName = "version.jar"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$buildKotlinVersion"
|
||||
compile "org.jetbrains.kotlin:kotlin-native-shared:$sharedVersion"
|
||||
}
|
||||
@@ -20,7 +20,6 @@ buildscript {
|
||||
|
||||
}
|
||||
|
||||
|
||||
apply plugin: 'kotlin'
|
||||
|
||||
repositories {
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.jetbrains.kotlin
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.tasks.*
|
||||
import java.io.File
|
||||
|
||||
|
||||
open class VersionGenerator: DefaultTask() {
|
||||
@OutputDirectory
|
||||
val versionSourceDirectory = project.file("build/generated")
|
||||
@OutputFile
|
||||
val versionFile:File = project.file("${versionSourceDirectory.path}/org/jetbrains/kotlin/konan/KonanVersionGenerated.kt")
|
||||
|
||||
val konanVersion: String
|
||||
@Input get() = project.properties["konanVersion"].toString()
|
||||
|
||||
val buildNumber: String?
|
||||
// TeamCity passes all configuration parameters into a build script as project properties.
|
||||
// Thus we can use them here instead of environment variables.
|
||||
@Optional @Input get() = project.findProperty("build.number")?.toString()
|
||||
|
||||
val meta: String
|
||||
@Input get() = project.properties["konanMetaVersion"]?.let {
|
||||
"MetaVersion.${it.toString().toUpperCase()}"
|
||||
} ?: "MetaVersion.DEV"
|
||||
|
||||
|
||||
override fun configure(closure: Closure<*>): Task {
|
||||
val result = super.configure(closure)
|
||||
doFirst {
|
||||
val content = buildString {
|
||||
operator fun String.unaryPlus() = this@buildString.append(this)
|
||||
val version = konanVersion.split(".")
|
||||
val major = version[0].toInt()
|
||||
val minor = version[1].toInt()
|
||||
val maintenance = if (version.size > 2) version[2].toInt() else 0
|
||||
project.logger.info("BUILD_NUMBER: $buildNumber")
|
||||
val build = buildNumber?.let {
|
||||
it.split("-")[2].toInt() //7-dev-buildcount
|
||||
}?: -1
|
||||
|
||||
+ """
|
||||
|package org.jetbrains.kotlin.konan
|
||||
|
|
||||
|internal val currentKonanVersion: KonanVersion =
|
||||
| KonanVersionImpl($meta, $major, $minor, $maintenance, $build)
|
||||
|
|
||||
|val KonanVersion.Companion.CURRENT: KonanVersion
|
||||
| get() = currentKonanVersion
|
||||
""".trimMargin()
|
||||
}
|
||||
versionFile.printWriter().use {
|
||||
it.println(content)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
rootProject.name = "kotlin-native-version"
|
||||
Reference in New Issue
Block a user