tools: Add dependecy download helpers
This patch adds 2 helpers to download dependencies for compiler and stub generator during their execution. They take list of external dependencies as a parameter and directory where they must be located. Helpers check if these dependencies exist in the given directory and download not existing ones.
This commit is contained in:
@@ -43,3 +43,9 @@ proto/compiler/google/src/google/protobuf/compiler/kotlin/protoc
|
|||||||
|
|
||||||
# translator auto generated artifacts
|
# translator auto generated artifacts
|
||||||
kotstd/ll
|
kotstd/ll
|
||||||
|
|
||||||
|
# directory for manual debug runs
|
||||||
|
run-debug/**
|
||||||
|
!run-debug/interop
|
||||||
|
!run-debug/konanc
|
||||||
|
|
||||||
|
|||||||
+22
-2
@@ -7,6 +7,7 @@ import org.jetbrains.kotlin.native.interop.indexer.buildNativeIndex
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.IllegalArgumentException
|
import java.lang.IllegalArgumentException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.reflect.KFunction
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val konanHome = System.getProperty("konan.home")!!
|
val konanHome = System.getProperty("konan.home")!!
|
||||||
@@ -116,7 +117,20 @@ private fun runCmd(command: Array<String>, workDir: File, verbose: Boolean = fal
|
|||||||
.runExpectingSuccess()
|
.runExpectingSuccess()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Properties.defaultCompilerOpts(target: String, dependencies: String): List<String> {
|
private fun maybeExecuteHelper(dependenciesRoot: String, propertiesFile: String, dependencies: List<String>) {
|
||||||
|
try {
|
||||||
|
val kClass = Class.forName("org.jetbrains.kotlin.konan.InteropHelper0").kotlin
|
||||||
|
val ctor = kClass.constructors.single() as KFunction<Runnable>
|
||||||
|
val result = ctor.call(dependenciesRoot, propertiesFile, dependencies)
|
||||||
|
result.run()
|
||||||
|
} catch (notFound: ClassNotFoundException) {
|
||||||
|
// Just ignore, no helper.
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
throw IllegalStateException("Cannot download dependencies.", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Properties.defaultCompilerOpts(target: String, dependencies: String, konanFileName: String): List<String> {
|
||||||
|
|
||||||
val hostSysRootDir = this.getOsSpecific("sysRoot", target)!!
|
val hostSysRootDir = this.getOsSpecific("sysRoot", target)!!
|
||||||
val hostSysRoot = "$dependencies/$hostSysRootDir"
|
val hostSysRoot = "$dependencies/$hostSysRootDir"
|
||||||
@@ -127,6 +141,12 @@ private fun Properties.defaultCompilerOpts(target: String, dependencies: String)
|
|||||||
val llvmHome = "$dependencies/$llvmHomeDir"
|
val llvmHome = "$dependencies/$llvmHomeDir"
|
||||||
val llvmVersion = this.getProperty("llvmVersion")!!
|
val llvmVersion = this.getProperty("llvmVersion")!!
|
||||||
|
|
||||||
|
val dependencyList = mutableListOf<String>(sysRoot, targetSysRoot, llvmHome)
|
||||||
|
if (target == "linux") {
|
||||||
|
dependencyList.add("$dependencies/${getOsSpecific("gccToolChain", target)!!}")
|
||||||
|
}
|
||||||
|
maybeExecuteHelper(dependencies, konanFileName, dependencyList)
|
||||||
|
|
||||||
// StubGenerator passes the arguments to libclang which
|
// StubGenerator passes the arguments to libclang which
|
||||||
// works not exactly the same way as the clang binary and
|
// works not exactly the same way as the clang binary and
|
||||||
// (in particular) uses different default header search path.
|
// (in particular) uses different default header search path.
|
||||||
@@ -242,7 +262,7 @@ private fun processLib(konanHome: String,
|
|||||||
val generateShims = args["-shims"].isTrue()
|
val generateShims = args["-shims"].isTrue()
|
||||||
val verbose = args["-verbose"].isTrue()
|
val verbose = args["-verbose"].isTrue()
|
||||||
|
|
||||||
val defaultOpts = konanProperties.defaultCompilerOpts(target, dependencies)
|
val defaultOpts = konanProperties.defaultCompilerOpts(target, dependencies, konanFileName)
|
||||||
val headerFiles = config.getSpaceSeparated("headers") + additionalHeaders
|
val headerFiles = config.getSpaceSeparated("headers") + additionalHeaders
|
||||||
val compilerOpts =
|
val compilerOpts =
|
||||||
config.getSpaceSeparated("compilerOpts") +
|
config.getSpaceSeparated("compilerOpts") +
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ between threads are allowed.
|
|||||||
|
|
||||||
./dist/bin/kotlinc <some_file>.kt <dir_with_kt_files> -o <executable>.kexe
|
./dist/bin/kotlinc <some_file>.kt <dir_with_kt_files> -o <executable>.kexe
|
||||||
|
|
||||||
|
During the first run it will download all external dependencies such as LLVM.
|
||||||
|
|
||||||
One may use `'-h'` flag to `kotlinc` to see available flags.
|
One may use `'-h'` flag to `kotlinc` to see available flags.
|
||||||
|
|
||||||
For documentation on C interoperability stubs see INTEROP.md.
|
For documentation on C interoperability stubs see INTEROP.md.
|
||||||
|
|||||||
@@ -16,17 +16,15 @@ import kotlin.reflect.KFunction
|
|||||||
|
|
||||||
private fun maybeExecuteHelper(configuration: CompilerConfiguration) {
|
private fun maybeExecuteHelper(configuration: CompilerConfiguration) {
|
||||||
try {
|
try {
|
||||||
val kClass = Class.forName("org.jetbrains.kotlin.konan.Helper0").kotlin
|
val kClass = Class.forName("org.jetbrains.kotlin.konan.CompilerHelper0").kotlin
|
||||||
val ctor = kClass.constructors.single() as KFunction<Runnable>
|
val ctor = kClass.constructors.single() as KFunction<Runnable>
|
||||||
val distribution = Distribution(configuration)
|
val distribution = Distribution(configuration)
|
||||||
val target = TargetManager(configuration)
|
val result = ctor.call(distribution)
|
||||||
val result = ctor.call(
|
|
||||||
distribution.konanHome, TargetManager.host, target.current)
|
|
||||||
result.run()
|
result.run()
|
||||||
} catch (notFound: ClassNotFoundException) {
|
} catch (notFound: ClassNotFoundException) {
|
||||||
// Just ignore, no helper.
|
// Just ignore, no helper.
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
println(e.toString())
|
throw IllegalStateException("Cannot download dependencies.", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-1
@@ -35,7 +35,13 @@ class Distribution(val config: CompilerConfiguration) {
|
|||||||
|
|
||||||
val llvmHome = "$dependencies/${properties.propertyString("llvmHome.$suffix")}"
|
val llvmHome = "$dependencies/${properties.propertyString("llvmHome.$suffix")}"
|
||||||
val sysRoot = "$dependencies/${properties.propertyString("sysRoot.$suffix")}"
|
val sysRoot = "$dependencies/${properties.propertyString("sysRoot.$suffix")}"
|
||||||
val libGcc = "$dependencies/${properties.propertyString("libGcc.$suffix")}"
|
val libGcc = "$dependencies/${properties.propertyString("libGcc.$suffix")}"
|
||||||
|
|
||||||
|
val targetSysRoot = if (properties.hasProperty("targetSysRoot.$suffix")) {
|
||||||
|
"$dependencies/${properties.propertyString("targetSysRoot.$suffix")}"
|
||||||
|
} else {
|
||||||
|
sysRoot
|
||||||
|
}
|
||||||
|
|
||||||
val llvmBin = "$llvmHome/bin"
|
val llvmBin = "$llvmHome/bin"
|
||||||
val llvmLib = "$llvmHome/lib"
|
val llvmLib = "$llvmHome/lib"
|
||||||
|
|||||||
+17
-5
@@ -4,12 +4,24 @@
|
|||||||
//
|
//
|
||||||
package org.jetbrains.kotlin.konan
|
package org.jetbrains.kotlin.konan
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanTarget
|
import org.jetbrains.kotlin.backend.konan.Distribution
|
||||||
|
import org.jetbrains.kotlin.backend.konan.TargetManager
|
||||||
|
|
||||||
// Name it Helper0 so that it get loaded.
|
// Name it CompilerHelper0 so that it get loaded.
|
||||||
class Helper0Disabled(
|
class CompilerHelper0Disabled(val distribution: Distribution) : Runnable {
|
||||||
val konanHome: String, val host: KonanTarget, val target: KonanTarget) : Runnable {
|
|
||||||
override fun run() {
|
override fun run() {
|
||||||
println("Running helper with $konanHome $host $target")
|
println("Running helper with ${distribution.konanHome} ${distribution.target} ${TargetManager.host}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Example startup helper for Kotlin N stub generator. Compile to JAR and add it to
|
||||||
|
// Kotlin N classpath - it will get loaded and executed automatically.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Name it InteropHelper0 so that it get loaded.
|
||||||
|
class InteropHelper0Disabled(val dependenciesRoot: String, val dependencies: List<String>) : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
println("Running helper with $dependenciesRoot $dependencies")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
@@ -15,10 +15,13 @@ public class KonanProperties(val propertyFile: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun propertyString(key: String): String? = properties.getProperty(key)
|
fun propertyString(key: String): String? = properties.getProperty(key)
|
||||||
|
fun propertyString(key: String, default: String) : String = properties.getProperty(key, default)
|
||||||
|
|
||||||
fun propertyList(key: String): List<String> {
|
fun propertyList(key: String): List<String> {
|
||||||
val value = properties.getProperty(key)
|
val value = properties.getProperty(key)
|
||||||
return value?.split(' ') ?: listOf<String>()
|
return value?.split(' ') ?: listOf<String>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun hasProperty(key: String): Boolean = properties.getProperty(key) != null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
// TODO: Do we need a $variable substitution mechanism here?
|
// TODO: Do we need a $variable substitution mechanism here?
|
||||||
llvmVersion = 3.9.0
|
llvmVersion = 3.9.0
|
||||||
|
dependenciesUrl = https://jetbrains.bintray.com/kotlin-native-dependencies
|
||||||
|
|
||||||
// macbook
|
// macbook
|
||||||
arch.osx = x86_64
|
arch.osx = x86_64
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ dependencies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def testOutputRoot = rootProject.file("test.output").absolutePath
|
ext.testOutputRoot = rootProject.file("test.output").absolutePath
|
||||||
def externalTestsDir = project.file("external")
|
ext.externalTestsDir = project.file("external")
|
||||||
externalTestsDir.mkdirs()
|
externalTestsDir.mkdirs()
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ class PlatformInfo {
|
|||||||
|
|
||||||
task dist_compiler(type: Copy) {
|
task dist_compiler(type: Copy) {
|
||||||
dependsOn ':backend.native:jars'
|
dependsOn ':backend.native:jars'
|
||||||
|
dependsOn ':tools:helpers:jar'
|
||||||
|
|
||||||
destinationDir file('dist')
|
destinationDir file('dist')
|
||||||
|
|
||||||
@@ -174,6 +175,11 @@ task dist_compiler(type: Copy) {
|
|||||||
includeEmptyDirs = false
|
includeEmptyDirs = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: check if we use native libraries copied to dist (see above) or not.
|
||||||
|
from(project(':tools:helpers').file('build/libs')) {
|
||||||
|
into('konan/lib')
|
||||||
|
}
|
||||||
|
|
||||||
doLast {
|
doLast {
|
||||||
// MacOS System Integrity Protection strips DYLD_LIBRARY_PATH from
|
// MacOS System Integrity Protection strips DYLD_LIBRARY_PATH from
|
||||||
// environment of all the binaries residing in /bin /usr/bin etc.
|
// environment of all the binaries residing in /bin /usr/bin etc.
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ abstract class KonanTest extends JavaExec {
|
|||||||
def backendNative = project.project(":backend.native")
|
def backendNative = project.project(":backend.native")
|
||||||
def runtimeProject = project.project(":runtime")
|
def runtimeProject = project.project(":runtime")
|
||||||
def dist = project.rootProject.file("dist")
|
def dist = project.rootProject.file("dist")
|
||||||
def dependencies = project.findProject(":dependencies").file("all")
|
def dependenciesDir = project.findProject(":dependencies").file("all")
|
||||||
def runtimeBc = new File("${dist.canonicalPath}/lib/runtime.bc").absolutePath
|
def runtimeBc = new File("${dist.canonicalPath}/lib/runtime.bc").absolutePath
|
||||||
def launcherBc = new File("${dist.canonicalPath}/lib/launcher.bc").absolutePath
|
def launcherBc = new File("${dist.canonicalPath}/lib/launcher.bc").absolutePath
|
||||||
def startKtBc = new File("${dist.canonicalPath}/lib/start.kt.bc").absolutePath
|
def startKtBc = new File("${dist.canonicalPath}/lib/start.kt.bc").absolutePath
|
||||||
@@ -59,7 +59,7 @@ abstract class KonanTest extends JavaExec {
|
|||||||
void setJvmArgs(Iterable<?> arguments) {
|
void setJvmArgs(Iterable<?> arguments) {
|
||||||
super.setJvmArgs(arguments +
|
super.setJvmArgs(arguments +
|
||||||
"-Dkonan.home=${dist.canonicalPath}" +
|
"-Dkonan.home=${dist.canonicalPath}" +
|
||||||
"-Dkonan.dependencies=${dependencies.canonicalPat}",
|
"-Dkonan.dependencies=${dependenciesDir.canonicalPath}" +
|
||||||
"-Djava.library.path=${dist.canonicalPath}/konan/nativelib")
|
"-Djava.library.path=${dist.canonicalPath}/konan/nativelib")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -40,7 +40,6 @@ findHome() {
|
|||||||
KONAN_HOME="$(findHome)"
|
KONAN_HOME="$(findHome)"
|
||||||
|
|
||||||
NATIVE_LIB="${KONAN_HOME}/konan/nativelib"
|
NATIVE_LIB="${KONAN_HOME}/konan/nativelib"
|
||||||
DEPENDENCIES="${KONAN_HOME}/../dependencies/all"
|
|
||||||
JAVA_OPTS="-ea \
|
JAVA_OPTS="-ea \
|
||||||
-Djava.library.path=${NATIVE_LIB} \
|
-Djava.library.path=${NATIVE_LIB} \
|
||||||
-Dkonan.home=${KONAN_HOME}"
|
-Dkonan.home=${KONAN_HOME}"
|
||||||
@@ -49,7 +48,8 @@ STUB_GENERATOR_JAR="${KONAN_HOME}/konan/lib/StubGenerator.jar"
|
|||||||
KOTLIN_JAR="${KONAN_HOME}/konan/lib/kotlin-compiler.jar"
|
KOTLIN_JAR="${KONAN_HOME}/konan/lib/kotlin-compiler.jar"
|
||||||
INTEROP_INDEXER_JAR="${KONAN_HOME}/konan/lib/Indexer.jar"
|
INTEROP_INDEXER_JAR="${KONAN_HOME}/konan/lib/Indexer.jar"
|
||||||
INTEROP_RUNTIME_JAR="${KONAN_HOME}/konan/lib/Runtime.jar"
|
INTEROP_RUNTIME_JAR="${KONAN_HOME}/konan/lib/Runtime.jar"
|
||||||
INTEROP_CLASSPATH="$STUB_GENERATOR_JAR:$KOTLIN_JAR:$INTEROP_INDEXER_JAR:$INTEROP_RUNTIME_JAR"
|
HELPERS_JAR="${KONAN_HOME}/konan/lib/helpers.jar"
|
||||||
|
INTEROP_CLASSPATH="$STUB_GENERATOR_JAR:$KOTLIN_JAR:$INTEROP_INDEXER_JAR:$INTEROP_RUNTIME_JAR:$HELPERS_JAR"
|
||||||
INTEROP_TOOL=org.jetbrains.kotlin.native.interop.gen.jvm.MainKt
|
INTEROP_TOOL=org.jetbrains.kotlin.native.interop.gen.jvm.MainKt
|
||||||
|
|
||||||
FLAVOR_ARG=-flavor:native
|
FLAVOR_ARG=-flavor:native
|
||||||
|
|||||||
+3
-2
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
if [ -z "$JAVACMD" -a -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then
|
if [ -z "$JAVACMD" -a -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then
|
||||||
JAVACMD="$JAVA_HOME/bin/java"
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
@@ -52,8 +52,9 @@ KONAN_HOME="$(findHome)"
|
|||||||
KONAN_JAR="${KONAN_HOME}/konan/lib/backend.native.jar"
|
KONAN_JAR="${KONAN_HOME}/konan/lib/backend.native.jar"
|
||||||
KOTLIN_JAR="${KONAN_HOME}/konan/lib/kotlin-compiler.jar"
|
KOTLIN_JAR="${KONAN_HOME}/konan/lib/kotlin-compiler.jar"
|
||||||
INTEROP_JAR="${KONAN_HOME}/konan/lib/Runtime.jar"
|
INTEROP_JAR="${KONAN_HOME}/konan/lib/Runtime.jar"
|
||||||
|
HELPERS_JAR="${KONAN_HOME}/konan/lib/helpers.jar"
|
||||||
NATIVE_LIB="${KONAN_HOME}/konan/nativelib"
|
NATIVE_LIB="${KONAN_HOME}/konan/nativelib"
|
||||||
KONAN_CLASSPATH="$KOTLIN_JAR:$INTEROP_JAR:$KONAN_JAR"
|
KONAN_CLASSPATH="$KOTLIN_JAR:$INTEROP_JAR:$KONAN_JAR:$HELPERS_JAR"
|
||||||
KONAN_COMPILER=org.jetbrains.kotlin.cli.bc.K2NativeKt
|
KONAN_COMPILER=org.jetbrains.kotlin.cli.bc.K2NativeKt
|
||||||
JAVA_OPTS=-ea
|
JAVA_OPTS=-ea
|
||||||
|
|
||||||
|
|||||||
@@ -7,3 +7,4 @@ include ':backend.native'
|
|||||||
include ':runtime'
|
include ':runtime'
|
||||||
include ':common'
|
include ':common'
|
||||||
include ':backend.native:tests'
|
include ':backend.native:tests'
|
||||||
|
include ':tools:helpers'
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
import org.jetbrains.kotlin.NativeInteropPlugin
|
||||||
|
import org.jetbrains.kotlin.RunInteropKonanTest
|
||||||
|
import org.jetbrains.kotlin.RunKonanTest
|
||||||
|
import org.jetbrains.kotlin.TestFailedException
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url 'http://oss.sonatype.org/content/repositories/snapshots'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'kotlin'
|
||||||
|
apply plugin: NativeInteropPlugin
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
cli_bc.extendsFrom compile
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile project(path: ':backend.native', configuration: 'cli_bc')
|
||||||
|
cli_bc jar.outputs.files
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
testOutputLocal {
|
||||||
|
output.dir(rootProject.file("${findProject(":backend.native:tests").testOutputRoot}/tools/helpers"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def testDependencies = project.file("${sourceSets.testOutputLocal.output.dirs.singleFile.absolutePath}/dependencies")
|
||||||
|
|
||||||
|
void prepareDependenciesDir(File testDependencies) {
|
||||||
|
project.delete testDependencies
|
||||||
|
testDependencies.mkdirs()
|
||||||
|
// We don't download big clang dependency in this test - only sysroots.
|
||||||
|
project.copy {
|
||||||
|
from project.findProject(":dependencies").file("all")
|
||||||
|
into testDependencies
|
||||||
|
include "clang*.tar.gz/**"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinNativeInterop {
|
||||||
|
sysstat {
|
||||||
|
pkg 'sysstat'
|
||||||
|
headers 'sys/stat.h'
|
||||||
|
flavor 'native'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task testInteropHelper(type: RunInteropKonanTest) {
|
||||||
|
dependsOn jar
|
||||||
|
dependsOn ':dist'
|
||||||
|
|
||||||
|
dependenciesDir = testDependencies
|
||||||
|
goldValue = "0\n0\n"
|
||||||
|
source = "testData/interop.kt"
|
||||||
|
interop = 'sysstat'
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
prepareDependenciesDir(testDependencies)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task testCompilerHelper(type: RunKonanTest) {
|
||||||
|
dependenciesDir = testDependencies
|
||||||
|
source = "testData/main.kt"
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
prepareDependenciesDir(testDependencies)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple test for parallel compiler execution
|
||||||
|
task testParallel(type: DefaultTask) {
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
task("runParallel$i", type: RunKonanTest) {
|
||||||
|
dependenciesDir = testDependencies
|
||||||
|
source = "testData/main.kt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
prepareDependenciesDir(testDependencies)
|
||||||
|
}
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
List<Thread> threads = new ArrayList<>()
|
||||||
|
def downloadCnt = new AtomicInteger(0)
|
||||||
|
tasks.withType(RunKonanTest).matching { it.name.startsWith("runParallel") }.each { task ->
|
||||||
|
threads.add(Thread.start {
|
||||||
|
task.executeTest()
|
||||||
|
// The helper prints messages when it is downloading.
|
||||||
|
// We check that there is only one downloading using compilation logs.
|
||||||
|
if (file("${task.buildExePath()}.compilation.log").text.contains("Download dependency")) {
|
||||||
|
downloadCnt.incrementAndGet()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
threads.each { it.join() }
|
||||||
|
if (downloadCnt.intValue() != 1) {
|
||||||
|
throw new TestFailedException("Actual downloads: ${downloadCnt.intValue()}, expected: 1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task testHelpers {
|
||||||
|
dependsOn testInteropHelper
|
||||||
|
dependsOn testCompilerHelper
|
||||||
|
dependsOn testParallel
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
delete testDependencies
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package org.jetbrains.kotlin.konan
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Distribution
|
||||||
|
import org.jetbrains.kotlin.backend.konan.KonanTarget
|
||||||
|
import org.jetbrains.kotlin.backend.konan.TargetManager
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class CompilerHelper0(val dist: Distribution): Runnable {
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
val dependencies = mutableListOf<String>()
|
||||||
|
dependencies.add(dist.sysRoot)
|
||||||
|
dependencies.add(dist.llvmHome)
|
||||||
|
if (dist.sysRoot != dist.targetSysRoot) {
|
||||||
|
dependencies.add(dist.targetSysRoot)
|
||||||
|
}
|
||||||
|
if (TargetManager.host == KonanTarget.LINUX) {
|
||||||
|
dependencies.add(dist.libGcc)
|
||||||
|
}
|
||||||
|
DependencyDownloader(File(dist.dependencies), dist.properties.properties, dependencies).run()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package org.jetbrains.kotlin.konan
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.io.RandomAccessFile
|
||||||
|
import java.net.URL
|
||||||
|
import java.nio.file.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
// TODO: Try to use some dependency management system (Ivy?)
|
||||||
|
// TODO: Show % and size during downloading
|
||||||
|
class DependencyDownloader(dependenciesRoot: File, val properties: Properties, val dependencies: List<String>) {
|
||||||
|
|
||||||
|
val dependenciesRoot = dependenciesRoot.apply { mkdirs() }
|
||||||
|
|
||||||
|
val lockFile = File(dependenciesRoot, ".lock").apply { createNewFile() }
|
||||||
|
val listFile = File(dependenciesRoot, ".downloaded")
|
||||||
|
|
||||||
|
val dependenciesUrl: String =
|
||||||
|
properties.getProperty("dependenciesUrl", "https://jetbrains.bintray.com/kotlin-native-dependencies")
|
||||||
|
|
||||||
|
var isInfoShown = false
|
||||||
|
|
||||||
|
private fun File.containsLine(line: String): Boolean {
|
||||||
|
if (!exists()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
var result = false
|
||||||
|
listFile.forEachLine {
|
||||||
|
if (!result && it == line) {
|
||||||
|
result = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processDependency(path: String) {
|
||||||
|
val depDir = File(path)
|
||||||
|
val depName = depDir.name
|
||||||
|
val inListFile = listFile.containsLine(depName)
|
||||||
|
if (inListFile && depDir.exists()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!isInfoShown) {
|
||||||
|
println("Downloading native dependencies (LLVM, sysroot etc). This is one-time action performing only for the first run of the compiler.")
|
||||||
|
isInfoShown = true
|
||||||
|
}
|
||||||
|
val downloaded = download(depName)
|
||||||
|
println("Extract dependency: $downloaded -> $depDir")
|
||||||
|
extract(downloaded)
|
||||||
|
if (!inListFile) {
|
||||||
|
listFile.appendText("$depName\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun extract(tarGz: File) {
|
||||||
|
val tarProcess = ProcessBuilder().apply {
|
||||||
|
command("tar", "-x", "-f", "${tarGz.canonicalPath}")
|
||||||
|
directory(tarGz.parentFile)
|
||||||
|
}.start()
|
||||||
|
tarProcess.waitFor()
|
||||||
|
if (tarProcess.exitValue() != 0) {
|
||||||
|
throw RuntimeException("Cannot extract archive with dependency: ${tarGz.canonicalPath}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun download(dependencyName: String): File {
|
||||||
|
val to = File(dependenciesRoot.canonicalPath, "$dependencyName.tar.gz")
|
||||||
|
if (!to.exists()) {
|
||||||
|
val from = URL("$dependenciesUrl/$dependencyName.tar.gz")
|
||||||
|
println("Download dependency: $dependencyName from $from")
|
||||||
|
from.openStream().use {
|
||||||
|
Files.copy(it, Paths.get(to.toURI()), StandardCopyOption.REPLACE_EXISTING)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return to
|
||||||
|
}
|
||||||
|
|
||||||
|
fun run() {
|
||||||
|
val systemLock = RandomAccessFile(lockFile, "rw").channel.lock()
|
||||||
|
dependencies.forEach {
|
||||||
|
processDependency(it)
|
||||||
|
}
|
||||||
|
systemLock.release()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.jetbrains.kotlin.konan
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.konan.KonanProperties
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class InteropHelper0(
|
||||||
|
val dependenciesRoot: String,
|
||||||
|
val propertiesFile: String,
|
||||||
|
val dependencies: List<String>): Runnable {
|
||||||
|
|
||||||
|
override fun run() =
|
||||||
|
DependencyDownloader(
|
||||||
|
File(dependenciesRoot),
|
||||||
|
Properties().apply { load(File(propertiesFile).inputStream()) },
|
||||||
|
dependencies
|
||||||
|
).run()
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import sysstat.*
|
||||||
|
import kotlinx.cinterop.*
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
val statBuf = nativeHeap.alloc<statStruct>()
|
||||||
|
val res = stat("/", statBuf.ptr)
|
||||||
|
println(res)
|
||||||
|
println(statBuf.st_uid.value)
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fun main(args: Array<String>) {
|
||||||
|
println(42)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user