Initial checkin of klib support.
The libraries exist in two incarnations:
packed foo.klib and unpacked foo/ .
The compiler when given '-library foo' expects to find either
a foo.klib file and unpack it, or an already unpacked foo/ directory.
The stdlib is always unpacked in dist/klib .
The semantics of -o has changed slightly.
It now accepts '-o foo' and the compiler
either produces foo.kexe or foo.klib .
This commit is contained in:
committed by
alexander-gorshenev
parent
77e093354f
commit
3b5ce031f8
@@ -38,6 +38,9 @@ model {
|
||||
include '**/*.c'
|
||||
}
|
||||
binaries.all {
|
||||
def host = rootProject.ext.host
|
||||
def hostLibffiDir = rootProject.ext.get("${host}LibffiDir")
|
||||
|
||||
cCompiler.args compilerArgsForJniIncludes
|
||||
cCompiler.args "-I$hostLibffiDir/include"
|
||||
|
||||
|
||||
+10
-10
@@ -153,7 +153,7 @@ kotlinNativeInterop {
|
||||
compilerOpts '-fPIC'
|
||||
linkerOpts '-fPIC'
|
||||
linker 'clang++'
|
||||
linkOutputs ':common:hostHash'
|
||||
linkOutputs ":common:${host}Hash"
|
||||
|
||||
headers fileTree('../common/src/hash/headers') {
|
||||
include '**/*.h'
|
||||
@@ -194,8 +194,8 @@ build.dependsOn 'compilerClasses','cli_bcClasses','bc_frontendClasses'
|
||||
|
||||
|
||||
// These are just a couple of aliases
|
||||
task stdlib(dependsOn: 'hostStdlib')
|
||||
task start(dependsOn: 'hostStart')
|
||||
task stdlib(dependsOn: "${host}Stdlib")
|
||||
task start(dependsOn: "${host}Start")
|
||||
|
||||
// These files are built before the 'dist' is complete,
|
||||
// so we provide custom values for
|
||||
@@ -208,8 +208,8 @@ targetList.each { target ->
|
||||
jvmArgs "-ea",
|
||||
"-Dkonan.home=${project.parent.file('dist')}",
|
||||
"-Djava.library.path=${project.buildDir}/nativelibs"
|
||||
args('-output', project(':runtime').file("build/${target}/stdlib.kt.bc"),
|
||||
'-nolink', '-nostdlib', '-ea',
|
||||
args('-output', project(':runtime').file("build/${target}Stdlib"),
|
||||
'-nolink', '-nopack', '-nostdlib','-ea',
|
||||
'-target', target,
|
||||
'-runtime', project(':runtime').file("build/${target}/runtime.bc"),
|
||||
'-properties', project(':backend.native').file('konan.properties'),
|
||||
@@ -221,7 +221,7 @@ targetList.each { target ->
|
||||
inputs.dir(project(':runtime').file('src/main/kotlin'))
|
||||
inputs.dir(project(':Interop:Runtime').file('src/main/kotlin'))
|
||||
inputs.dir(project(':Interop:Runtime').file('src/native/kotlin'))
|
||||
outputs.file(project(':runtime').file("build/${target}/stdlib.kt.bc"))
|
||||
outputs.file(project(':runtime').file("build/${target}Stdlib"))
|
||||
|
||||
dependsOn ":runtime:${target}Runtime"
|
||||
}
|
||||
@@ -234,17 +234,17 @@ targetList.each { target ->
|
||||
jvmArgs "-ea",
|
||||
"-Dkonan.home=${project.parent.file('dist')}",
|
||||
"-Djava.library.path=${project.buildDir}/nativelibs"
|
||||
args('-output', project(':runtime').file("build/${target}/start.kt.bc"),
|
||||
'-nolink', '-nostdlib', '-ea',
|
||||
args('-output', project(':runtime').file("build/${target}Start"),
|
||||
'-nolink', '-nopack', '-nostdlib', '-ea',
|
||||
'-target', target,
|
||||
'-library', project(':runtime').file("build/${target}/stdlib.kt.bc"),
|
||||
'-library', project(':runtime').file("build/${target}Stdlib"),
|
||||
'-runtime', project(':runtime').file("build/${target}/runtime.bc"),
|
||||
'-properties', project(':backend.native').file('konan.properties'),
|
||||
project(':runtime').file('src/launcher/kotlin'),
|
||||
*project.globalBuildArgs)
|
||||
|
||||
inputs.dir(project(':runtime').file('src/launcher/kotlin'))
|
||||
outputs.file(project(':runtime').file("build/${target}/start.kt.bc"))
|
||||
outputs.file(project(':runtime').file("build/${target}Start"))
|
||||
|
||||
dependsOn ":runtime:${target}Runtime", "${target}Stdlib"
|
||||
}
|
||||
|
||||
@@ -90,36 +90,38 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||
|
||||
put(NOSTDLIB, arguments.nostdlib)
|
||||
put(NOLINK, arguments.nolink)
|
||||
put(NOPACK, arguments.nopack)
|
||||
put(NOMAIN, arguments.nomain)
|
||||
put(LIBRARY_FILES,
|
||||
arguments.libraries.toNonNullList())
|
||||
|
||||
put(LINKER_ARGS, arguments.linkerArguments.toNonNullList())
|
||||
if (arguments.target != null)
|
||||
put(TARGET, arguments.target)
|
||||
|
||||
put(NATIVE_LIBRARY_FILES,
|
||||
arguments.nativeLibraries.toNonNullList())
|
||||
|
||||
// TODO: Collect all the explicit file names into an object
|
||||
// and teach the compiler to work with temporaries and -save-temps.
|
||||
val bitcodeFile = if (arguments.nolink) {
|
||||
arguments.outputFile ?: "program.kt.bc"
|
||||
} else {
|
||||
"${arguments.outputFile ?: "program"}.kt.bc"
|
||||
val library = arguments.outputFile ?: "library"
|
||||
if (arguments.nolink)
|
||||
put(LIBRARY_NAME, library)
|
||||
put(LIBRARY_FILE, "${library}.klib")
|
||||
val program = arguments.outputFile ?: "program"
|
||||
if (!arguments.nolink) {
|
||||
put(PROGRAM_NAME,program)
|
||||
put(EXECUTABLE_FILE,"${program}.kexe")
|
||||
}
|
||||
put(BITCODE_FILE, bitcodeFile)
|
||||
|
||||
// This is a decision we could change
|
||||
put(CommonConfigurationKeys.MODULE_NAME, bitcodeFile)
|
||||
val module = if (arguments.nolink) library else program
|
||||
put(CommonConfigurationKeys.MODULE_NAME, module)
|
||||
put(ABI_VERSION, 1)
|
||||
|
||||
put(EXECUTABLE_FILE,
|
||||
arguments.outputFile ?: "program.kexe")
|
||||
if (arguments.runtimeFile != null)
|
||||
put(RUNTIME_FILE, arguments.runtimeFile)
|
||||
if (arguments.propertyFile != null)
|
||||
put(PROPERTY_FILE, arguments.propertyFile)
|
||||
if (arguments.target != null)
|
||||
put(TARGET, arguments.target)
|
||||
put(LIST_TARGETS, arguments.listTargets)
|
||||
put(OPTIMIZATION, arguments.optimization)
|
||||
put(DEBUG, arguments.debug)
|
||||
|
||||
@@ -38,6 +38,9 @@ public class K2NativeCompilerArguments extends CommonCompilerArguments {
|
||||
@Argument(value = "-nolink", description = "Don't link, just produce a bitcode file")
|
||||
public boolean nolink;
|
||||
|
||||
@Argument(value = "-nopack", description = "Don't pack the library into a klib file")
|
||||
public boolean nopack;
|
||||
|
||||
@Argument(value = "-nomain", description = "Assume 'main' entry point to be provided by external libraries")
|
||||
public boolean nomain;
|
||||
|
||||
|
||||
+2
-5
@@ -55,11 +55,6 @@ import java.util.*
|
||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
internal class LinkData(
|
||||
val module: String,
|
||||
val fragments: List<String>,
|
||||
val fragmentNames: List<String> )
|
||||
|
||||
internal class SpecialDescriptorsFactory(val context: Context) {
|
||||
private val enumSpecialDescriptorsFactory by lazy { EnumSpecialDescriptorsFactory(context) }
|
||||
private val outerThisDescriptors = mutableMapOf<ClassDescriptor, PropertyDescriptor>()
|
||||
@@ -270,6 +265,8 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
|
||||
lateinit var llvm: Llvm
|
||||
lateinit var llvmDeclarations: LlvmDeclarations
|
||||
lateinit var bitcodeFileName: String
|
||||
lateinit var library: KonanLibraryWriter
|
||||
|
||||
var phase: KonanPhase? = null
|
||||
var depth: Int = 0
|
||||
|
||||
+4
-8
@@ -22,9 +22,7 @@ import java.io.File
|
||||
class Distribution(val config: CompilerConfiguration) {
|
||||
|
||||
val targetManager = TargetManager(config)
|
||||
val target =
|
||||
if (!targetManager.crossCompile) "host"
|
||||
else targetManager.current.name.toLowerCase()
|
||||
val target = targetManager.currentName
|
||||
val suffix = targetManager.currentSuffix()
|
||||
val hostSuffix = TargetManager.host.suffix
|
||||
init { if (!targetManager.crossCompile) assert(suffix == hostSuffix) }
|
||||
@@ -40,16 +38,14 @@ class Distribution(val config: CompilerConfiguration) {
|
||||
?: "$konanHome/konan/konan.properties"
|
||||
val properties = KonanProperties(propertyFile)
|
||||
|
||||
val lib = "$konanHome/lib/$target"
|
||||
val klib = "$konanHome/klib"
|
||||
|
||||
val dependenciesDir = "$konanHome/dependencies"
|
||||
val dependencies = properties.propertyList("dependencies.$suffix")
|
||||
|
||||
val stdlib = "$lib/stdlib.kt.bc"
|
||||
val start = "$lib/start.kt.bc"
|
||||
val launcher = "$lib/launcher.bc"
|
||||
val stdlib = "$klib/stdlib"
|
||||
val runtime = config.get(KonanConfigKeys.RUNTIME_FILE)
|
||||
?: "$lib/runtime.bc"
|
||||
?: "$stdlib/$target/native/runtime.bc"
|
||||
|
||||
val llvmHome = "$dependenciesDir/${properties.propertyString("llvmHome.$hostSuffix")}"
|
||||
val sysRoot = "$dependenciesDir/${properties.propertyString("sysRoot.$hostSuffix")}"
|
||||
|
||||
+4
-4
@@ -28,6 +28,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
val moduleId: String
|
||||
get() = configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)
|
||||
|
||||
internal val targetManager = TargetManager(configuration)
|
||||
internal val distribution = Distribution(configuration)
|
||||
|
||||
private val libraryNames: List<String>
|
||||
@@ -39,16 +40,15 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
return fromCommandLine + distribution.stdlib
|
||||
}
|
||||
|
||||
internal val libraries: List<KonanLibrary> by lazy {
|
||||
// Here we have chosen a particular .kt.bc KonanLibrary implementation
|
||||
libraryNames.map{it -> KtBcLibrary(it, configuration)}
|
||||
internal val libraries: List<KonanLibraryReader> by lazy {
|
||||
// Here we have chosen a particular KonanLibraryReader implementation
|
||||
libraryNames.map{it -> SplitLibraryReader(it, configuration)}
|
||||
}
|
||||
|
||||
private val loadedDescriptors = loadLibMetadata()
|
||||
|
||||
internal val nativeLibraries: List<String> = configuration.getList(KonanConfigKeys.NATIVE_LIBRARY_FILES)
|
||||
|
||||
|
||||
fun loadLibMetadata(): List<ModuleDescriptorImpl> {
|
||||
|
||||
val allMetadata = mutableListOf<ModuleDescriptorImpl>()
|
||||
|
||||
+8
-2
@@ -25,8 +25,12 @@ class KonanConfigKeys {
|
||||
= CompilerConfigurationKey.create("library file paths")
|
||||
val NATIVE_LIBRARY_FILES: CompilerConfigurationKey<List<String>>
|
||||
= CompilerConfigurationKey.create("native library file paths")
|
||||
val BITCODE_FILE: CompilerConfigurationKey<String>
|
||||
= CompilerConfigurationKey.create("emitted bitcode file path")
|
||||
val LIBRARY_NAME: CompilerConfigurationKey<String>
|
||||
= CompilerConfigurationKey.create("library name")
|
||||
val LIBRARY_FILE: CompilerConfigurationKey<String>
|
||||
= CompilerConfigurationKey.create("library file path")
|
||||
val PROGRAM_NAME: CompilerConfigurationKey<String>
|
||||
= CompilerConfigurationKey.create("program name")
|
||||
val EXECUTABLE_FILE: CompilerConfigurationKey<String>
|
||||
= CompilerConfigurationKey.create("final executable file path")
|
||||
val RUNTIME_FILE: CompilerConfigurationKey<String?>
|
||||
@@ -43,6 +47,8 @@ class KonanConfigKeys {
|
||||
= CompilerConfigurationKey.create("don't link with stdlib")
|
||||
val NOLINK: CompilerConfigurationKey<Boolean>
|
||||
= CompilerConfigurationKey.create("don't link, only produce a bitcode file ")
|
||||
val NOPACK: CompilerConfigurationKey<Boolean>
|
||||
= CompilerConfigurationKey.create("don't the library into a klib file")
|
||||
val NOMAIN: CompilerConfigurationKey<Boolean>
|
||||
= CompilerConfigurationKey.create("assume 'main' entry point to be provided by external libraries")
|
||||
val LINKER_ARGS: CompilerConfigurationKey<List<String>>
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ public fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEn
|
||||
|
||||
val config = konanConfig.configuration
|
||||
|
||||
val targets = TargetManager(config)
|
||||
val targets = konanConfig.targetManager
|
||||
if (config.get(KonanConfigKeys.LIST_TARGETS) ?: false) {
|
||||
targets.list()
|
||||
}
|
||||
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.MetadataReader
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.loadSerializedModule
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.loadSerializedPackageFragment
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.Base64
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.deserializeModule
|
||||
import java.io.File
|
||||
|
||||
interface KonanLibrary {
|
||||
val libraryName: String
|
||||
val moduleName: String
|
||||
val moduleDescriptor: ModuleDescriptorImpl
|
||||
val bitcodePaths: List<String>
|
||||
}
|
||||
|
||||
class KtBcLibrary(val file: File, val configuration: CompilerConfiguration): KonanLibrary {
|
||||
constructor(path: String, configuration: CompilerConfiguration) : this(File(path), configuration)
|
||||
init {
|
||||
if (!file.exists())
|
||||
error("Path '" + file.path + "' does not exist")
|
||||
}
|
||||
|
||||
override val libraryName: String
|
||||
get() = file.path
|
||||
|
||||
override val bitcodePaths: List<String>
|
||||
get() = listOf(libraryName)
|
||||
|
||||
private val reader = MetadataReader(file)
|
||||
|
||||
private val namedModuleData by lazy {
|
||||
val currentAbiVersion = configuration.get(KonanConfigKeys.ABI_VERSION)!!
|
||||
reader.loadSerializedModule(currentAbiVersion)
|
||||
}
|
||||
override val moduleName = namedModuleData.name
|
||||
|
||||
private val tableOfContentsAsString = namedModuleData.base64
|
||||
|
||||
private fun packageMetadata(fqName: String): Base64 =
|
||||
reader.loadSerializedPackageFragment(fqName)
|
||||
|
||||
override val moduleDescriptor: ModuleDescriptorImpl by lazy {
|
||||
deserializeModule(configuration,
|
||||
{it -> packageMetadata(it)},
|
||||
tableOfContentsAsString, moduleName)
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -77,6 +77,7 @@ object KonanPhases {
|
||||
|
||||
// Don't serialize anything to a final executable.
|
||||
KonanPhase.SERIALIZER.enabled = getBoolean(NOLINK)
|
||||
KonanPhase.METADATOR.enabled = getBoolean(NOLINK)
|
||||
|
||||
val disabled = get(DISABLED_PHASES)
|
||||
disabled?.forEach { phases[known(it)]!!.enabled = false }
|
||||
|
||||
+2
@@ -30,6 +30,8 @@ enum class KonanTarget(val suffix: String, var enabled: Boolean = false) {
|
||||
class TargetManager(val config: CompilerConfiguration) {
|
||||
val targets = KonanTarget.values().associate{ it.name.toLowerCase() to it }
|
||||
val current = determineCurrent()
|
||||
val currentName
|
||||
get() = current.name.toLowerCase()
|
||||
|
||||
init {
|
||||
when (host) {
|
||||
|
||||
+4
-5
@@ -147,9 +147,9 @@ internal class LinkStage(val context: Context) {
|
||||
|
||||
val config = context.config.configuration
|
||||
|
||||
val targetManager = TargetManager(config)
|
||||
val targetManager = context.config.targetManager
|
||||
private val distribution =
|
||||
Distribution(context.config.configuration)
|
||||
context.config.distribution
|
||||
private val properties = distribution.properties
|
||||
|
||||
val platform = when (TargetManager.host) {
|
||||
@@ -164,8 +164,8 @@ internal class LinkStage(val context: Context) {
|
||||
val suffix = targetManager.currentSuffix()
|
||||
|
||||
val optimize = config.get(KonanConfigKeys.OPTIMIZATION) ?: false
|
||||
val emitted = config.get(KonanConfigKeys.BITCODE_FILE)!!
|
||||
val nomain = config.get(KonanConfigKeys.NOMAIN) ?: false
|
||||
val emitted = context.bitcodeFileName
|
||||
val libraries = context.config.libraries
|
||||
|
||||
fun llvmLto(files: List<BitcodeFile>): ObjectFile {
|
||||
@@ -265,8 +265,7 @@ internal class LinkStage(val context: Context) {
|
||||
fun linkStage() {
|
||||
context.log{"# Compiler root: ${distribution.konanHome}"}
|
||||
|
||||
val bitcodeFiles = listOf<BitcodeFile>(emitted, distribution.start,
|
||||
distribution.runtime, distribution.launcher) +
|
||||
val bitcodeFiles = listOf<BitcodeFile>(emitted) +
|
||||
libraries.map{it -> it.bitcodePaths}.flatten()
|
||||
|
||||
var objectFiles: List<String> = listOf()
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import java.io.File
|
||||
import java.net.URI
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.StandardCopyOption
|
||||
|
||||
val File.zipUri: URI
|
||||
get() = URI.create("jar:file:${this.absolutePath}")
|
||||
|
||||
val File.zipRootPath: Path
|
||||
get() {
|
||||
val zipUri = this.zipUri
|
||||
val allowCreation = hashMapOf("create" to "true")
|
||||
val zipfs = FileSystems.newFileSystem(zipUri, allowCreation, null)
|
||||
return zipfs.getPath("/")
|
||||
}
|
||||
|
||||
fun File.zipDirAs(zipFile: File) {
|
||||
val zipPath = zipFile.zipRootPath
|
||||
this.toPath().recursiveCopyTo(zipPath)
|
||||
zipPath.fileSystem.close()
|
||||
}
|
||||
|
||||
fun File.unzipAs(directory: File) {
|
||||
val zipPath = this.zipRootPath
|
||||
zipPath.recursiveCopyTo(directory.toPath())
|
||||
zipPath.fileSystem.close()
|
||||
}
|
||||
|
||||
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 Sting.
|
||||
val newPath = destFs.getPath(destPath.toString(), relative.toString())
|
||||
|
||||
// File systems don't allow replacing an existing root.
|
||||
if (newPath == newPath.getRoot()) return@next
|
||||
Files.copy(oldPath, newPath,
|
||||
StandardCopyOption.REPLACE_EXISTING)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun File.copyTo(destination: File) {
|
||||
Files.copy(this.toPath(), destination.toPath())
|
||||
}
|
||||
|
||||
+225
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import llvm.LLVMLinkModules2
|
||||
import llvm.LLVMModuleRef
|
||||
import llvm.LLVMWriteBitcodeToFile
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.Base64
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.deserializeModule
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import java.io.File
|
||||
|
||||
interface KonanLibraryReader {
|
||||
val libraryName: String
|
||||
val moduleName: String
|
||||
val moduleDescriptor: ModuleDescriptorImpl
|
||||
val bitcodePaths: List<String>
|
||||
}
|
||||
|
||||
abstract class FileBasedLibraryReader(
|
||||
val file: File,
|
||||
val configuration: CompilerConfiguration,
|
||||
val reader: MetadataReader): KonanLibraryReader {
|
||||
|
||||
override val libraryName: String
|
||||
get() = file.path
|
||||
|
||||
protected val namedModuleData by lazy {
|
||||
val currentAbiVersion = configuration.get(KonanConfigKeys.ABI_VERSION)!!
|
||||
reader.loadSerializedModule(currentAbiVersion)
|
||||
}
|
||||
|
||||
override val moduleName: String
|
||||
get() = namedModuleData.name
|
||||
|
||||
protected val tableOfContentsAsString : String
|
||||
get() = namedModuleData.base64
|
||||
|
||||
protected fun packageMetadata(fqName: String): Base64 =
|
||||
reader.loadSerializedPackageFragment(fqName)
|
||||
|
||||
override val moduleDescriptor: ModuleDescriptorImpl by lazy {
|
||||
deserializeModule(configuration,
|
||||
{it -> packageMetadata(it)},
|
||||
tableOfContentsAsString, moduleName)
|
||||
}
|
||||
}
|
||||
|
||||
class KtBcLibraryReader(file: File, configuration: CompilerConfiguration)
|
||||
: FileBasedLibraryReader(file, configuration, KtBcMetadataReader(file)) {
|
||||
|
||||
public constructor(path: String, configuration: CompilerConfiguration) : this(File(path), configuration)
|
||||
|
||||
override val bitcodePaths: List<String>
|
||||
get() = listOf(libraryName)
|
||||
|
||||
}
|
||||
|
||||
// TODO: Get rid of the configuration here.
|
||||
class SplitLibraryReader(val libDir: File, configuration: CompilerConfiguration)
|
||||
: FileBasedLibraryReader(libDir, configuration, SplitMetadataReader(libDir)) {
|
||||
|
||||
public constructor(path: String, configuration: CompilerConfiguration) : this(File(path), configuration)
|
||||
|
||||
val klibFile = File("${libDir.path}.klib")
|
||||
|
||||
init {
|
||||
unpackIfNeeded()
|
||||
}
|
||||
|
||||
// TODO: Search path processing is also goes somewhere around here.
|
||||
fun unpackIfNeeded() {
|
||||
// TODO: Clarify the policy here.
|
||||
if (libDir.exists()) {
|
||||
if (libDir.isDirectory()) return
|
||||
}
|
||||
if (!klibFile.exists()) {
|
||||
error("Could not find neither $libDir nor $klibFile.")
|
||||
}
|
||||
if (klibFile.isFile()) {
|
||||
klibFile.unzipAs(libDir)
|
||||
|
||||
if (!libDir.exists()) error("Could not unpack $klibFile as $libDir.")
|
||||
} else {
|
||||
error("Expected $klibFile to be a regular libDir.")
|
||||
}
|
||||
}
|
||||
|
||||
private val File.dirAbsolutePaths: List<String>
|
||||
get() = this.listFiles()!!.toList()!!.map{it->it.absolutePath}
|
||||
|
||||
private val targetDir: File
|
||||
get() {
|
||||
val target = TargetManager(configuration).currentName
|
||||
val dir = File(libDir, target)
|
||||
return dir
|
||||
}
|
||||
|
||||
override val bitcodePaths: List<String>
|
||||
get() = File(targetDir, "kotlin").dirAbsolutePaths +
|
||||
File(targetDir, "native").dirAbsolutePaths
|
||||
|
||||
}
|
||||
/* ------------ writer part ----------------*/
|
||||
|
||||
interface KonanLibraryWriter {
|
||||
|
||||
fun addLinkData(linkData: LinkData)
|
||||
fun addNativeBitcode(library: String)
|
||||
fun addKotlinBitcode(llvmModule: LLVMModuleRef)
|
||||
fun commit()
|
||||
|
||||
val mainBitcodeFileName: String
|
||||
}
|
||||
|
||||
class LinkData(
|
||||
val abiVersion: Int,
|
||||
val module: String,
|
||||
val moduleName: String,
|
||||
val fragments: List<String>,
|
||||
val fragmentNames: List<String> )
|
||||
|
||||
abstract class FileBasedLibraryWriter (
|
||||
val file: File): KonanLibraryWriter {
|
||||
}
|
||||
|
||||
class KtBcLibraryWriter(file: File, val llvmModule: LLVMModuleRef)
|
||||
: FileBasedLibraryWriter(file) {
|
||||
|
||||
override val mainBitcodeFileName = file.path
|
||||
|
||||
public constructor(path: String, llvmModule: LLVMModuleRef)
|
||||
: this(File(path), llvmModule)
|
||||
|
||||
override fun addKotlinBitcode(llvmModule: LLVMModuleRef) {
|
||||
// This is a noop for .kt.bc based libraries,
|
||||
// because the bitcode itself is the container.
|
||||
}
|
||||
|
||||
override fun addLinkData(linkData: LinkData) {
|
||||
MetadataGenerator(llvmModule).addLinkData(linkData)
|
||||
}
|
||||
|
||||
override fun addNativeBitcode(library: String) {
|
||||
|
||||
val libraryModule = parseBitcodeFile(library)
|
||||
val failed = LLVMLinkModules2(llvmModule, libraryModule)
|
||||
if (failed != 0) {
|
||||
throw Error("failed to link $library") // TODO: retrieve error message from LLVM.
|
||||
}
|
||||
}
|
||||
|
||||
override fun commit() {
|
||||
LLVMWriteBitcodeToFile(llvmModule, file.path)
|
||||
}
|
||||
}
|
||||
|
||||
class SplitLibraryWriter(val libDir: File, target: String, val nopack: Boolean = false): FileBasedLibraryWriter(libDir) {
|
||||
public constructor(path: String, target: String, nopack: Boolean): this(File(path), target, nopack)
|
||||
|
||||
val klibFile = File("${libDir.path}.klib")
|
||||
val linkdataDir = File(libDir, "linkdata")
|
||||
val resourcesDir = File(libDir, "resources")
|
||||
val targetDir = File(libDir, target)
|
||||
val kotlinDir = File(targetDir, "kotlin")
|
||||
val nativeDir = File(targetDir, "native")
|
||||
// TODO: Experiment with separate bitcode files.
|
||||
// Per package or per class.
|
||||
val mainBitcodeFile = File(kotlinDir, "program.kt.bc")
|
||||
override val mainBitcodeFileName = mainBitcodeFile.path
|
||||
|
||||
init {
|
||||
// TODO: figure out the proper policy here.
|
||||
libDir.deleteRecursively()
|
||||
klibFile.delete()
|
||||
libDir.mkdirs()
|
||||
linkdataDir.mkdirs()
|
||||
targetDir.mkdirs()
|
||||
kotlinDir.mkdirs()
|
||||
nativeDir.mkdirs()
|
||||
resourcesDir.mkdirs()
|
||||
}
|
||||
|
||||
var llvmModule: LLVMModuleRef? = null
|
||||
|
||||
override fun addKotlinBitcode(llvmModule: LLVMModuleRef) {
|
||||
this.llvmModule = llvmModule
|
||||
LLVMWriteBitcodeToFile(llvmModule, mainBitcodeFileName)
|
||||
}
|
||||
|
||||
override fun addLinkData(linkData: LinkData) {
|
||||
SplitMetadataGenerator(linkdataDir).addLinkData(linkData)
|
||||
}
|
||||
|
||||
override fun addNativeBitcode(library: String) {
|
||||
val basename = File(library).getName()
|
||||
File(library).copyTo(File(nativeDir, basename))
|
||||
}
|
||||
|
||||
override fun commit() {
|
||||
if (!nopack) {
|
||||
// This is no-op for the Split library.
|
||||
// Or should we zip the directory?
|
||||
libDir.zipDirAs(klibFile)
|
||||
libDir.deleteRecursively()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-1
@@ -22,6 +22,7 @@ import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||
import org.jetbrains.kotlin.backend.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.backend.konan.TargetManager
|
||||
import org.jetbrains.kotlin.backend.konan.util.File
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
@@ -94,7 +95,15 @@ internal fun String?.toFileAndFolder():FileAndFolder {
|
||||
|
||||
internal fun generateDebugInfoHeader(context: Context) {
|
||||
if (context.shouldContainDebugInfo()) {
|
||||
val path = context.config.configuration.get(KonanConfigKeys.BITCODE_FILE).toFileAndFolder()
|
||||
|
||||
val path = with(context.config.configuration) {
|
||||
if (!getBoolean(KonanConfigKeys.NOLINK)) {
|
||||
get(KonanConfigKeys.EXECUTABLE_FILE)!!
|
||||
} else {
|
||||
get(KonanConfigKeys.LIBRARY_NAME)!!
|
||||
}
|
||||
}.toFileAndFolder()
|
||||
|
||||
context.debugInfo.module = DICreateModule(
|
||||
builder = context.debugInfo.builder,
|
||||
scope = context.llvmModule as DIScopeOpaqueRef,
|
||||
|
||||
+64
-30
@@ -23,9 +23,14 @@ import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||
import org.jetbrains.kotlin.backend.konan.KonanPhase
|
||||
import org.jetbrains.kotlin.backend.konan.LinkData
|
||||
import org.jetbrains.kotlin.backend.konan.PhaseManager
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||
import org.jetbrains.kotlin.backend.konan.TargetManager
|
||||
import org.jetbrains.kotlin.backend.konan.KonanLibraryWriter
|
||||
import org.jetbrains.kotlin.backend.konan.KtBcLibraryWriter
|
||||
import org.jetbrains.kotlin.backend.konan.SplitLibraryWriter
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
@@ -52,7 +57,9 @@ import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
internal fun emitLLVM(context: Context) {
|
||||
|
||||
val config = context.config.configuration
|
||||
val irModule = context.irModule!!
|
||||
|
||||
// Note that we don't set module target explicitly.
|
||||
// It is determined by the target of runtime.bc
|
||||
// (see Llvm class in ContextUtils)
|
||||
@@ -61,7 +68,6 @@ internal fun emitLLVM(context: Context) {
|
||||
val llvmModule = LLVMModuleCreateWithName("out")!! // TODO: dispose
|
||||
context.llvmModule = llvmModule
|
||||
context.debugInfo.builder = DICreateBuilder(llvmModule)
|
||||
|
||||
context.llvmDeclarations = createLlvmDeclarations(context)
|
||||
|
||||
val phaser = PhaseManager(context)
|
||||
@@ -70,33 +76,74 @@ internal fun emitLLVM(context: Context) {
|
||||
irModule.acceptVoid(RTTIGeneratorVisitor(context))
|
||||
}
|
||||
|
||||
|
||||
generateDebugInfoHeader(context)
|
||||
|
||||
phaser.phase(KonanPhase.CODEGEN) {
|
||||
irModule.acceptVoid(CodeGeneratorVisitor(context))
|
||||
}
|
||||
|
||||
phaser.phase(KonanPhase.METADATOR) {
|
||||
irModule.acceptVoid(MetadatorVisitor(context))
|
||||
}
|
||||
|
||||
phaser.phase(KonanPhase.BITCODE_LINKER) {
|
||||
for (library in context.config.nativeLibraries) {
|
||||
val libraryModule = parseBitcodeFile(library)
|
||||
val failed = LLVMLinkModules2(llvmModule, libraryModule)
|
||||
if (failed != 0) {
|
||||
throw Error("failed to link $library") // TODO: retrieve error message from LLVM.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (context.shouldContainDebugInfo()) {
|
||||
DIFinalize(context.debugInfo.builder)
|
||||
}
|
||||
LLVMWriteBitcodeToFile(llvmModule, context.config.configuration.get(KonanConfigKeys.BITCODE_FILE)!!)
|
||||
|
||||
if (!config.getBoolean(KonanConfigKeys.NOLINK)) {
|
||||
val program = config.get(KonanConfigKeys.PROGRAM_NAME)!!
|
||||
val output = "$program}.kt.bc"
|
||||
context.bitcodeFileName = output
|
||||
|
||||
phaser.phase(KonanPhase.BITCODE_LINKER) {
|
||||
for (library in context.config.nativeLibraries) {
|
||||
val libraryModule = parseBitcodeFile(library)
|
||||
val failed = LLVMLinkModules2(llvmModule, libraryModule)
|
||||
if (failed != 0) {
|
||||
throw Error("failed to link $library") // TODO: retrieve error message from LLVM.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLVMWriteBitcodeToFile(llvmModule, output)
|
||||
} else {
|
||||
|
||||
val libraryName = config.get(KonanConfigKeys.LIBRARY_NAME)!!
|
||||
val nopack = config.getBoolean(KonanConfigKeys.NOPACK)
|
||||
val targetName = context.config.targetManager.currentName
|
||||
|
||||
val library = buildLibrary(
|
||||
phaser,
|
||||
context.config.nativeLibraries,
|
||||
context.serializedLinkData!!,
|
||||
targetName,
|
||||
libraryName,
|
||||
llvmModule,
|
||||
nopack)
|
||||
|
||||
context.library = library
|
||||
|
||||
context.bitcodeFileName =
|
||||
library.mainBitcodeFileName
|
||||
}
|
||||
}
|
||||
|
||||
internal fun buildLibrary(phaser: PhaseManager, natives: List<String>, linkData: LinkData, target: String, output: String, llvmModule: LLVMModuleRef, nopack: Boolean): KonanLibraryWriter {
|
||||
// TODO: May be we need a factory?
|
||||
//val library = KtBcLibraryWriter(output, llvmModule)
|
||||
val library = SplitLibraryWriter(output, target, nopack)
|
||||
|
||||
library.addKotlinBitcode(llvmModule)
|
||||
|
||||
phaser.phase(KonanPhase.METADATOR) {
|
||||
library.addLinkData(linkData)
|
||||
}
|
||||
|
||||
phaser.phase(KonanPhase.BITCODE_LINKER) {
|
||||
natives.forEach {
|
||||
library.addNativeBitcode(it)
|
||||
}
|
||||
}
|
||||
|
||||
library.commit()
|
||||
return library
|
||||
}
|
||||
|
||||
internal fun verifyModule(llvmModule: LLVMModuleRef, current: String = "") {
|
||||
memScoped {
|
||||
@@ -134,19 +181,6 @@ internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid {
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
internal class MetadatorVisitor(val context: Context) : IrElementVisitorVoid {
|
||||
|
||||
val metadator = MetadataGenerator(context)
|
||||
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitModuleFragment(module: IrModuleFragment) {
|
||||
module.acceptChildrenVoid(this)
|
||||
metadator.endModule(module)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines how to generate context-dependent operations.
|
||||
|
||||
+65
-15
@@ -20,13 +20,51 @@ import kotlinx.cinterop.*
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||
import org.jetbrains.kotlin.backend.konan.LinkData
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import java.io.Closeable
|
||||
import java.io.File
|
||||
import kotlin.io.readText
|
||||
import java.util.Properties
|
||||
|
||||
class NamedModuleData(val name:String, val base64: String)
|
||||
|
||||
fun MetadataReader.loadSerializedModule(currentAbiVersion: Int): NamedModuleData {
|
||||
interface MetadataReader {
|
||||
fun loadSerializedModule(currentAbiVersion: Int): NamedModuleData
|
||||
fun loadSerializedPackageFragment(fqName: String): String
|
||||
}
|
||||
|
||||
class SplitMetadataReader(file: File) : MetadataReader {
|
||||
|
||||
val linkDataDir = File(file, "linkdata")
|
||||
|
||||
override fun loadSerializedModule(currentAbiVersion: Int): NamedModuleData {
|
||||
val header = Properties()
|
||||
val file = File(linkDataDir, "module")
|
||||
file.bufferedReader().use { reader ->
|
||||
header.load(reader)
|
||||
}
|
||||
val headerAbiVersion = header.getProperty("abi_version")!!
|
||||
val moduleName = header.getProperty("module_name")!!
|
||||
val moduleData = header.getProperty("module_data")!!
|
||||
|
||||
if ("$currentAbiVersion" != headerAbiVersion)
|
||||
error("ABI version mismatch. Compiler expects: $currentAbiVersion, the library is $headerAbiVersion")
|
||||
|
||||
return NamedModuleData(moduleName, moduleData)
|
||||
}
|
||||
|
||||
override fun loadSerializedPackageFragment(fqName: String): String {
|
||||
val realName = if (fqName == "") "<root>" else fqName
|
||||
|
||||
return File(linkDataDir, realName).readText()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class KtBcMetadataReader(file: File) : Closeable, MetadataReader {
|
||||
|
||||
override fun loadSerializedModule(currentAbiVersion: Int): NamedModuleData {
|
||||
val (nodeCount, kmetadataNodeArg) = namedMetadataNode("kmetadata")
|
||||
|
||||
if (nodeCount != 1) {
|
||||
@@ -48,7 +86,7 @@ fun MetadataReader.loadSerializedModule(currentAbiVersion: Int): NamedModuleData
|
||||
return NamedModuleData(moduleName, tableOfContentsAsString)
|
||||
}
|
||||
|
||||
fun MetadataReader.loadSerializedPackageFragment(fqName: String): String {
|
||||
override fun loadSerializedPackageFragment(fqName: String): String {
|
||||
val (nodeCount, kpackageNodeArg) = namedMetadataNode("kpackage:$fqName")
|
||||
|
||||
if (nodeCount != 1) {
|
||||
@@ -61,8 +99,6 @@ fun MetadataReader.loadSerializedPackageFragment(fqName: String): String {
|
||||
return base64
|
||||
}
|
||||
|
||||
class MetadataReader(file: File) : Closeable {
|
||||
|
||||
lateinit var llvmModule: LLVMModuleRef
|
||||
lateinit var llvmContext: LLVMContextRef
|
||||
|
||||
@@ -141,7 +177,7 @@ class MetadataReader(file: File) : Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
internal class MetadataGenerator(override val context: Context): ContextUtils {
|
||||
internal class MetadataGenerator(val llvmModule: LLVMModuleRef) {
|
||||
|
||||
private fun metadataNode(args: List<LLVMValueRef?>): LLVMValueRef {
|
||||
return LLVMMDNode(args.toCValues(), args.size)!!
|
||||
@@ -154,38 +190,52 @@ internal class MetadataGenerator(override val context: Context): ContextUtils {
|
||||
}
|
||||
|
||||
private fun emitModuleMetadata(name: String, md: LLVMValueRef?) {
|
||||
LLVMAddNamedMetadataOperand(context.llvmModule, name, md)
|
||||
LLVMAddNamedMetadataOperand(llvmModule, name, md)
|
||||
}
|
||||
|
||||
private fun metadataString(str: String): LLVMValueRef {
|
||||
return LLVMMDString(str, str.length)!!
|
||||
}
|
||||
|
||||
private fun addLinkData(module: IrModuleFragment) {
|
||||
val linkData = context.serializedLinkData
|
||||
fun addLinkData(linkData: LinkData) {
|
||||
if (linkData == null) return
|
||||
|
||||
val abiVersion = context.config.configuration.get(KonanConfigKeys.ABI_VERSION)
|
||||
val abiNode = metadataString("$abiVersion")
|
||||
val moduleName = metadataString(module.descriptor.name.asString())
|
||||
val abiNode = metadataString("${linkData.abiVersion}")
|
||||
val moduleNameNode = metadataString(linkData.moduleName)
|
||||
val module = linkData.module
|
||||
val fragments = linkData.fragments
|
||||
val fragmentNames = linkData.fragmentNames
|
||||
val dataNode = metadataString(module)
|
||||
|
||||
val kmetadataArg = metadataNode(listOf(abiNode, moduleName, dataNode))
|
||||
val kmetadataArg = metadataNode(listOf(abiNode, moduleNameNode, dataNode))
|
||||
emitModuleMetadata("kmetadata", kmetadataArg)
|
||||
|
||||
fragments.forEachIndexed { index, it ->
|
||||
val name = fragmentNames.get(index)
|
||||
val name = fragmentNames[index]
|
||||
val dataNode = metadataString(it)
|
||||
val kpackageArg = metadataNode(listOf(dataNode))
|
||||
emitModuleMetadata("kpackage:$name", kpackageArg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun endModule(module: IrModuleFragment) {
|
||||
addLinkData(module)
|
||||
internal class SplitMetadataGenerator(val file: File) {
|
||||
|
||||
fun addLinkData(linkData: LinkData) {
|
||||
|
||||
val header = Properties()
|
||||
header.putAll(hashMapOf(
|
||||
"abi_version" to "${linkData.abiVersion}",
|
||||
"module_name" to "${linkData.moduleName}",
|
||||
"module_data" to "${linkData.module}"
|
||||
))
|
||||
header.store(File(file, "module").outputStream(), null)
|
||||
|
||||
linkData.fragments.forEachIndexed { index, it ->
|
||||
val name = linkData.fragmentNames[index]
|
||||
val realName = if (name == "") "<root>" else name
|
||||
File(file, realName).writeText(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.konan.serialization
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.LinkData
|
||||
import org.jetbrains.kotlin.backend.konan.KonanBuiltIns
|
||||
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.base64Decode
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.base64Encode
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.isExported
|
||||
@@ -274,7 +275,9 @@ internal class KonanSerializationUtil(val context: Context) {
|
||||
}
|
||||
val libraryAsByteArray = libraryProto.build().toByteArray()
|
||||
val library = byteArrayToBase64(libraryAsByteArray)
|
||||
return LinkData(library, fragments, fragmentNames)
|
||||
val abiVersion = context.config.configuration.get(KonanConfigKeys.ABI_VERSION)!!
|
||||
val moduleName = moduleDescriptor.name.asString()
|
||||
return LinkData(abiVersion, library, moduleName, fragments, fragmentNames)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+52
-26
@@ -67,8 +67,9 @@ void setupCompilationFlags() {
|
||||
final String binDir
|
||||
|
||||
if (isLinux()) {
|
||||
ext.host = "linux"
|
||||
ext.targetArgs <<
|
||||
["host":
|
||||
[(ext.host):
|
||||
["--sysroot=${gccToolchainDir}/${gnuTriplet}/sysroot"],
|
||||
"raspberrypi":
|
||||
["-target", "armv7-unknown-linux-gnueabihf",
|
||||
@@ -79,9 +80,10 @@ void setupCompilationFlags() {
|
||||
"-I$raspberryPiSysrootDir/usr/include/c++/4.8.3/arm-linux-gnueabihf"]
|
||||
]
|
||||
} else {
|
||||
ext.host = "macbook"
|
||||
ext.targetArgs <<
|
||||
["host":
|
||||
["--sysroot=$hostSysrootDir", "-mmacosx-version-min=$minMacOsVersion"],
|
||||
[(ext.host):
|
||||
["--sysroot=$macbookSysrootDir", "-mmacosx-version-min=$minMacOsVersion"],
|
||||
"iphone":
|
||||
["-stdlib=libc++", "-arch", "arm64", "-isysroot", "$iphoneSysrootDir",
|
||||
"-miphoneos-version-min=8.0.0"]
|
||||
@@ -99,11 +101,11 @@ void setupCompilationFlags() {
|
||||
"-L$llvmDir/lib"
|
||||
])
|
||||
} else {
|
||||
binDir = "$hostSysrootDir/usr/bin"
|
||||
binDir = "$macbookSysrootDir/usr/bin"
|
||||
}
|
||||
ext.clangArgs << "-B$binDir"
|
||||
ext.hostClangArgs = ext.clangArgs.clone()
|
||||
ext.hostClangArgs.addAll(ext.targetArgs['host'])
|
||||
ext.hostClangArgs.addAll(ext.targetArgs[host])
|
||||
|
||||
ext.clangPath << binDir
|
||||
ext.jvmArgs = ["-ea"]
|
||||
@@ -164,7 +166,12 @@ class PlatformInfo {
|
||||
}
|
||||
}
|
||||
|
||||
task dist_compiler(type: Copy) {
|
||||
task dist_compiler(dependsOn: "distCompiler")
|
||||
task dist_runtime(dependsOn: "distRuntime")
|
||||
task cross_dist(dependsOn: "crossDist")
|
||||
task list_dist(dependsOn: "listDist")
|
||||
|
||||
task distCompiler(type: Copy) {
|
||||
dependsOn ':backend.native:jars'
|
||||
dependsOn ':tools:helpers:jar'
|
||||
|
||||
@@ -221,46 +228,65 @@ task dist_compiler(type: Copy) {
|
||||
}
|
||||
}
|
||||
|
||||
task list_dist(type: Exec) {
|
||||
task listDist(type: Exec) {
|
||||
commandLine 'find', 'dist'
|
||||
}
|
||||
|
||||
task dist_runtime(type: Copy) {
|
||||
dependsOn ':runtime:hostRuntime'
|
||||
dependsOn ':backend.native:hostStdlib'
|
||||
dependsOn ':backend.native:hostStart'
|
||||
task distRuntime(type: Copy) {
|
||||
dependsOn "${host}CrossDistRuntime"
|
||||
dependsOn('commonDistRuntime')
|
||||
}
|
||||
|
||||
task commonDistRuntime(type: Copy) {
|
||||
destinationDir file('dist')
|
||||
|
||||
from(project(':runtime').file('build')) {
|
||||
include('*/*.bc')
|
||||
into('lib')
|
||||
// Target independant common part.
|
||||
from(project(':runtime').file("build/${host}Stdlib")) {
|
||||
include('**')
|
||||
into('klib/stdlib')
|
||||
}
|
||||
}
|
||||
|
||||
task cross_dist_runtime(type: Copy) {
|
||||
dependsOn.addAll(targetList.collect { ":runtime:${it}Runtime" })
|
||||
dependsOn.addAll(targetList.collect { ":backend.native:${it}Stdlib" })
|
||||
dependsOn.addAll(targetList.collect { ":backend.native:${it}Start" })
|
||||
task crossDistRuntime(type: Copy) {
|
||||
dependsOn.addAll(targetList.collect { "${it}CrossDistRuntime" })
|
||||
dependsOn('commonDistRuntime')
|
||||
}
|
||||
|
||||
destinationDir file('dist')
|
||||
targetList.each { target ->
|
||||
task("${target}CrossDistRuntime", type: Copy) {
|
||||
dependsOn ":runtime:${target}Runtime"
|
||||
dependsOn ":backend.native:${target}Stdlib"
|
||||
dependsOn ":backend.native:${target}Start"
|
||||
|
||||
from(project(':runtime').file('build')) {
|
||||
include('*/*.bc')
|
||||
into('lib')
|
||||
destinationDir file('dist')
|
||||
|
||||
from(project(':runtime').file("build/$target")) {
|
||||
include("*.bc")
|
||||
eachFile {println("eachfile= $it")}
|
||||
into("klib/stdlib/$target/native")
|
||||
}
|
||||
from(project(':runtime').file("build/${target}Stdlib")) {
|
||||
include('**')
|
||||
into('klib/stdlib')
|
||||
}
|
||||
from(project(':runtime').file("build/${target}Start/$target/kotlin")) {
|
||||
include("program.kt.bc")
|
||||
rename('program.kt.bc', 'start.kt.bc')
|
||||
into("klib/stdlib/$target/native")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task dist {
|
||||
dependsOn 'dist_compiler', 'dist_runtime', ':tools:gradle-plugin:dist'
|
||||
dependsOn 'distCompiler', 'distRuntime', ':tools:gradle-plugin:dist'
|
||||
}
|
||||
|
||||
task cross_dist {
|
||||
dependsOn 'cross_dist_runtime', 'dist'
|
||||
task crossDist {
|
||||
dependsOn 'crossDistRuntime', 'distCompiler'
|
||||
}
|
||||
|
||||
task bundle(type: Tar) {
|
||||
dependsOn('cross_dist')
|
||||
dependsOn('crossDist')
|
||||
baseName = "kotlin-native-${simpleOsName()}-${project.konanVersion}"
|
||||
from("$project.rootDir/dist") {
|
||||
include '**'
|
||||
|
||||
@@ -117,7 +117,7 @@ abstract class KonanTest extends JavaExec {
|
||||
}
|
||||
|
||||
String buildExePath() {
|
||||
def exeName = project.file(source).name.replace(".kt", ".kt.exe")
|
||||
def exeName = project.file(source).name.replace(".kt", "")
|
||||
return "$outputDirectory/$exeName"
|
||||
}
|
||||
|
||||
@@ -206,9 +206,10 @@ fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation<Any?> = ob
|
||||
@TaskAction
|
||||
void executeTest() {
|
||||
createOutputDirectory()
|
||||
def exe = buildExePath()
|
||||
def program = buildExePath()
|
||||
def exe = "${program}.kexe"
|
||||
|
||||
compileTest(buildCompileList(), exe)
|
||||
compileTest(buildCompileList(), program)
|
||||
|
||||
if (!run) {
|
||||
println "to be executed manually: $exe"
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ targetList.each { targetName ->
|
||||
}
|
||||
|
||||
task build {
|
||||
dependsOn hostHash
|
||||
dependsOn "${host}Hash"
|
||||
}
|
||||
|
||||
task clean << {
|
||||
|
||||
Vendored
+12
-11
@@ -178,16 +178,14 @@ class HelperNativeDep extends TgzNativeDep {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
task hostLibffi(type: HelperNativeDep) {
|
||||
baseName = "libffi-3.2.1-2-$host"
|
||||
}
|
||||
|
||||
task llvm(type: HelperNativeDep) {
|
||||
baseName = "clang-llvm-$llvmVersion-$host"
|
||||
}
|
||||
|
||||
if (isLinux()) {
|
||||
task linuxLibffi(type: HelperNativeDep) {
|
||||
baseName = "libffi-3.2.1-2-$host"
|
||||
}
|
||||
task gccToolchain(type: HelperNativeDep) {
|
||||
baseName = "target-gcc-toolchain-3-$host"
|
||||
}
|
||||
@@ -198,7 +196,10 @@ if (isLinux()) {
|
||||
baseName = "libffi-3.2.1-2-raspberrypi"
|
||||
}
|
||||
} else {
|
||||
task hostSysroot(type: HelperNativeDep) {
|
||||
task macbookLibffi(type: HelperNativeDep) {
|
||||
baseName = "libffi-3.2.1-2-$host"
|
||||
}
|
||||
task macbookSysroot(type: HelperNativeDep) {
|
||||
baseName = "target-sysroot-1-$host"
|
||||
}
|
||||
task iphoneSysroot(type: HelperNativeDep) {
|
||||
@@ -207,11 +208,11 @@ if (isLinux()) {
|
||||
task iphoneLibffi(type: HelperNativeDep) {
|
||||
baseName = "libffi-3.2.1-2-darwin-ios"
|
||||
}
|
||||
// TODO: re-enable when we known how to bring the simulator
|
||||
// sysroot to dependencies.
|
||||
// task iphoneSimSysroot(type: TgzNativeDep) {
|
||||
// baseName = "target-sysroot-1-darwin-ios-sim"
|
||||
// }
|
||||
// TODO: re-enable when we known how to bring the simulator
|
||||
// sysroot to dependencies.
|
||||
// task iphoneSimSysroot(type: TgzNativeDep) {
|
||||
// baseName = "target-sysroot-1-darwin-ios-sim"
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ targetList.each { targetName ->
|
||||
}
|
||||
}
|
||||
|
||||
task hostRuntime(dependsOn: "${rootProject.ext.host}Runtime")
|
||||
|
||||
task clean << {
|
||||
delete buildDir
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user