Support Native target platform in kotlin-stdlib-gen

- Allow to select target platform and target directory to generate source for
- Put copyright profile to resources to have it in the resulting jar
- Output error for missing bodies, but do not stop generation on the first error
This commit is contained in:
Ilya Gorbunov
2018-12-25 06:54:54 +03:00
parent 7b43d5c972
commit f05efd58de
4 changed files with 58 additions and 23 deletions
+14 -1
View File
@@ -1,7 +1,10 @@
apply plugin: 'kotlin'
sourceSets {
main.kotlin.srcDir 'src'
main {
kotlin.srcDir 'src'
resources.srcDir "$buildDir/copyright"
}
}
dependencies {
@@ -15,6 +18,16 @@ compileKotlin {
}
}
task copyCopyrightProfile(type: Copy) {
from "$rootDir/.idea/copyright"
into "$buildDir/copyright"
include 'apache.xml'
}
processResources {
dependsOn(copyCopyrightProfile)
}
task run(type: JavaExec) {
group 'application'
main 'generators.GenerateStandardLibKt'
@@ -7,6 +7,7 @@ package generators
import java.io.*
import templates.*
import kotlin.system.exitProcess
/**
* Generates methods in the standard library which are mostly identical
@@ -34,28 +35,46 @@ fun main(args: Array<String>) {
ComparableOps
)
require(args.size == 1) { "Expecting Kotlin project home path as an argument" }
val baseDir = File(args.first())
COPYRIGHT_NOTICE = readCopyrightNoticeFromProfile { Thread.currentThread().contextClassLoader.getResourceAsStream("apache.xml").reader() }
COPYRIGHT_NOTICE = readCopyrightNoticeFromProfile(baseDir.resolve(".idea/copyright/apache.xml"))
val targetBaseDirs = mutableMapOf<KotlinTarget, File>()
fun File.resolveExistingDir(subpath: String) = resolve(subpath).also {
require(it.isDirectory) { "Directory $it doesn't exist"}
when (args.size) {
1 -> {
val baseDir = File(args.first())
targetBaseDirs[KotlinTarget.Common] = baseDir.resolveExistingDir("libraries/stdlib/common/src/generated")
targetBaseDirs[KotlinTarget.JVM] = baseDir.resolveExistingDir("libraries/stdlib/jvm/src/generated")
targetBaseDirs[KotlinTarget.JS] = baseDir.resolveExistingDir("libraries/stdlib/js/src/generated")
targetBaseDirs[KotlinTarget.JS_IR] = baseDir.resolveExistingDir("libraries/stdlib/js/irRuntime/generated")
}
2 -> {
val (targetName, targetDir) = args
val target = KotlinTarget.values.singleOrNull { it.name.equals(targetName, ignoreCase = true) } ?: error("Invalid target: $targetName")
targetBaseDirs[target] = File(targetDir).also { it.requireExistingDir() }
}
else -> {
println("""Parameters:
<kotlin-base-dir> - generates sources for common, jvm, js, ir-js targets using paths derived from specified base path
<target> <target-dir> - generates source for the specified target in the specified target directory
""")
exitProcess(1)
}
}
val commonDir = baseDir.resolveExistingDir("libraries/stdlib/common/src/generated")
val jvmDir = baseDir.resolveExistingDir("libraries/stdlib/jvm/src/generated")
val jsDir = baseDir.resolveExistingDir("libraries/stdlib/js/src/generated")
val jsIrDir = baseDir.resolveExistingDir("libraries/stdlib/js/irRuntime/generated")
templateGroups.groupByFileAndWrite { (target, source) ->
// File("build/out/$platform/$source.kt")
templateGroups.groupByFileAndWrite(targetsToGenerate = targetBaseDirs.keys.toList()) { (target, source) ->
val targetDir = targetBaseDirs[target] ?: error("Target $target directory is not configured")
when (target) {
KotlinTarget.Common -> commonDir.resolve("_${source.name.capitalize()}.kt")
KotlinTarget.JVM -> jvmDir.resolve("_${source.name.capitalize()}Jvm.kt")
KotlinTarget.JS -> jsDir.resolve("_${source.name.capitalize()}Js.kt")
KotlinTarget.JS_IR -> jsIrDir.resolve("_${source.name.capitalize()}Js.kt")
KotlinTarget.Native -> error("Native is unsupported yet")
KotlinTarget.Common -> targetDir.resolve("_${source.name.capitalize()}.kt")
KotlinTarget.JVM -> targetDir.resolve("_${source.name.capitalize()}Jvm.kt")
KotlinTarget.JS -> targetDir.resolve("_${source.name.capitalize()}Js.kt")
KotlinTarget.JS_IR -> targetDir.resolve("_${source.name.capitalize()}Js.kt")
KotlinTarget.Native -> targetDir.resolve("_${source.name.capitalize()}Native.kt")
}
}
}
fun File.resolveExistingDir(subpath: String) = resolve(subpath).also { it.requireExistingDir() }
fun File.requireExistingDir() {
require(isDirectory) { "Directory $this doesn't exist"}
}
@@ -381,7 +381,7 @@ class MemberBuilder(
val body = (body ?:
deprecate?.replaceWith?.let { "return $it" } ?:
throw RuntimeException("$signature for ${target.fullName}: no body specified for ${family to primitive}")
"""TODO("Body is not provided")""".also { System.err.println("ERROR: $signature for ${target.fullName}: no body specified for ${family to primitive}") }
).trim('\n')
val indent: Int = body.takeWhile { it == ' ' }.length
@@ -8,6 +8,7 @@ package templates
import org.xml.sax.InputSource
import java.io.File
import java.io.FileWriter
import java.io.Reader
import javax.xml.xpath.XPathFactory
val COMMON_AUTOGENERATED_WARNING: String = """//
@@ -17,8 +18,10 @@ val COMMON_AUTOGENERATED_WARNING: String = """//
lateinit var COPYRIGHT_NOTICE: String
fun readCopyrightNoticeFromProfile(copyrightProfile: File): String {
val template = copyrightProfile.reader().use { reader ->
fun readCopyrightNoticeFromProfile(copyrightProfile: File): String = readCopyrightNoticeFromProfile { copyrightProfile.reader() }
fun readCopyrightNoticeFromProfile(getCopyrightReader: () -> Reader): String {
val template = getCopyrightReader().use { reader ->
XPathFactory.newInstance().newXPath().evaluate("/component/copyright/option[@name='notice']/@value", InputSource(reader))
}
val yearTemplate = "&#36;today.year"
@@ -34,10 +37,9 @@ data class TargetedSourceFile(
val sourceFile: SourceFile
)
private val targetsToGenerate = KotlinTarget.values - KotlinTarget.Native
@JvmName("groupByFileAndWriteGroups")
fun Sequence<TemplateGroup>.groupByFileAndWrite(
targetsToGenerate: List<KotlinTarget>,
fileNameBuilder: (TargetedSourceFile) -> File
) {
flatMap { group ->
@@ -49,6 +51,7 @@ fun Sequence<TemplateGroup>.groupByFileAndWrite(
@JvmName("groupByFileAndWriteTemplates")
fun Sequence<MemberTemplate>.groupByFileAndWrite(
targetsToGenerate: List<KotlinTarget>,
fileNameBuilder: (TargetedSourceFile) -> File
) {
flatMap { it.instantiate(targetsToGenerate) }