Improve tooling model + add Gradle version checking (#1602)

* [gradle-plugin] Add tests for IDE model
* [gradle-plugin] Check Gradle version
* [gradle-plugin] Provide language, api and konan version in the model
* [gradle-plugin] Use String instead of KonanTarget in the IDE model
* [gradle-plugin] Rename Produce -> KonanOutput
* [version] Make KonanVersion an interface to allow passing it to IDE
* [gradle-plugin] Replace KonanOutput with CompilerOutputKind
* [gradle-plugin] Don't override usual jar with a fat one
* [gradle-plugin] Fix IDE model tests
* [gradle-plugin] Add library search paths in IDE model
* [gradle-plugin] Use 4.7 as a required version for the plugin
* [gradle-plugin] "Kotlinfy" the version check
This commit is contained in:
ilmat192
2018-05-23 11:58:47 +07:00
committed by GitHub
parent 74e1783e2b
commit bc65c7175d
15 changed files with 441 additions and 118 deletions
+7 -6
View File
@@ -40,7 +40,8 @@ ext {
kotlinReflectModule="org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}"
kotlinScriptRuntimeModule="org.jetbrains.kotlin:kotlin-script-runtime:${kotlinVersion}"
gradlePluginVersion = KonanVersion.CURRENT.gradlePluginVersion
konanVersionFull = KonanVersion.Companion.CURRENT
gradlePluginVersion = konanVersionFull.toString()
}
allprojects {
@@ -345,7 +346,7 @@ task bundle(type: (isWindows()) ? Zip : Tar) {
dependsOn('crossDistPlatformLibs')
dependsOn('crossDist')
def simpleOsName = HostManager.simpleOsName()
baseName = "kotlin-native-$simpleOsName-${KonanVersion.CURRENT}"
baseName = "kotlin-native-$simpleOsName-$konanVersionFull"
from("$project.rootDir/dist") {
include '**'
exclude 'dependencies'
@@ -403,7 +404,7 @@ task bundle(type: (isWindows()) ? Zip : Tar) {
task uploadBundle {
dependsOn ':bundle'
doLast {
def kind = (KonanVersion.CURRENT.meta == MetaVersion.DEV) ? "dev" : "releases"
def kind = (konanVersionFull.meta == MetaVersion.DEV) ? "dev" : "releases"
def ftpSettings = [
server: project.findProperty("cdnUrl") ?: System.getenv("CDN_URL"),
userid: project.findProperty("cdnUser") ?: System.getenv("CDN_USER"),
@@ -430,9 +431,9 @@ task performance {
task teamcityKonanVersion {
doLast {
println("##teamcity[setParameter name='kotlin.native.version.base' value='$konanVersion']")
println("##teamcity[setParameter name='kotlin.native.version.full' value='$KonanVersion.CURRENT']")
println("##teamcity[setParameter name='kotlin.native.version.meta' value='${KonanVersion.CURRENT.meta.toString().toLowerCase()}']")
println("##teamcity[buildNumber '${KonanVersion.CURRENT.toString(true, true)}']")
println("##teamcity[setParameter name='kotlin.native.version.full' value='$konanVersionFull']")
println("##teamcity[setParameter name='kotlin.native.version.meta' value='${konanVersionFull.meta.toString().toLowerCase()}']")
println("##teamcity[buildNumber '${konanVersionFull.toString(true, true)}']")
}
}
+1 -1
View File
@@ -43,7 +43,7 @@ sourceSets {
}
}
compileKotlin{
compileKotlin {
dependsOn('generateCompilerVersion')
}
@@ -42,42 +42,57 @@ open class VersionGenerator: DefaultTask() {
}?: -1
+ """
|package org.jetbrains.kotlin.konan
|data class KonanVersion(val meta: MetaVersion = MetaVersion.DEV,
| val major: Int,
| val minor: Int,
| val maintenance: Int,
| val build:Int) {
| companion object {
| val CURRENT = KonanVersion($meta, $major, $minor, $maintenance, $build)
| }
| 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
|
| val gradlePluginVersion by lazy { versionString }
|}
|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
|}
""".trimMargin()
}
versionFile.printWriter().use {
@@ -19,14 +19,14 @@ package org.jetbrains.kotlin.konan
/**
* 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")
}
enum class MetaVersion(val metaString: String) {
DEV("dev"),
EAP("eap"),
ALPHA("alpha"),
BETA("beta"),
RC1("rc1"),
RC2("rc2"),
RELEASE("release")
}
@@ -40,7 +40,7 @@ enum class Architecture(val bitness: Int) {
WASM32(32);
}
sealed class KonanTarget(override val name: String, val family: Family, val architecture: Architecture) : Named, Serializable {
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_ARM64 : KonanTarget( "ios_arm64", Family.IOS, Architecture.ARM64)
@@ -45,7 +45,7 @@ apply plugin: 'com.jfrog.bintray'
apply plugin: 'com.github.johnrengelman.shadow'
group = 'org.jetbrains.kotlin'
version = KonanVersion.CURRENT.gradlePluginVersion
version = KonanVersion.Companion.CURRENT.toString()
repositories {
mavenCentral()
@@ -76,11 +76,17 @@ dependencies {
}
}
jar {
appendix = "no-shared"
}
shadowJar {
configurations = [project.configurations.bundleDependencies]
classifier = null
}
assemble.dependsOn shadowJar
test {
systemProperty("kotlin.version", buildKotlinVersion)
if (project.hasProperty("konan.home")) {
@@ -24,6 +24,7 @@ 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.library.SearchPathResolver
import org.jetbrains.kotlin.konan.library.defaultResolver
import org.jetbrains.kotlin.konan.target.Distribution
import org.jetbrains.kotlin.konan.target.KonanTarget
@@ -132,14 +133,17 @@ open class KonanLibrariesSpec(val task: KonanArtifactWithLibrariesTask, val proj
if (this != another) { evaluationDependsOn(another.path) }
}
fun asFiles(): List<File> = mutableListOf<File>().apply {
fun asFiles(): List<File> = asFiles(
defaultResolver(
repos.map { it.absolutePath },
task.konanTarget,
Distribution(konanHomeOverride = project.konanHome)
)
)
fun asFiles(resolver: SearchPathResolver): List<File> = mutableListOf<File>().apply {
files.flatMapTo(this) { it.files }
addAll(artifactFiles)
val resolver = defaultResolver(
repos.map { it.absolutePath },
task.konanTarget,
Distribution(konanHomeOverride = project.konanHome)
)
namedKlibs.mapTo(this) { project.file(resolver.resolve(it).absolutePath) }
}
}
@@ -29,7 +29,9 @@ import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal
import org.gradle.language.cpp.internal.NativeVariantIdentity
import org.gradle.tooling.UnsupportedVersionException
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.plugin.KonanPlugin.Companion.COMPILE_ALL_TASK_NAME
import org.jetbrains.kotlin.gradle.plugin.model.KonanToolingModelBuilder
import org.jetbrains.kotlin.gradle.plugin.tasks.*
@@ -284,21 +286,30 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR
internal const val KONAN_DOWNLOAD_TASK_NAME = "checkKonanCompiler"
internal const val KONAN_GENERATE_CMAKE_TASK_NAME = "generateCMake"
internal const val COMPILE_ALL_TASK_NAME = "compileKonan"
internal const val KONAN_MAIN_VARIANT = "konan_main_variant"
internal const val KONAN_EXTENSION_NAME = "konan"
internal val REQUIRED_GRADLE_VERSION = GradleVersion.version("4.7")
}
private fun Project.cleanKonan() = project.tasks.withType(KonanBuildingTask::class.java).forEach {
project.delete(it.artifact)
}
private fun checkGradleVersion() = GradleVersion.current().let { current ->
check(current >= REQUIRED_GRADLE_VERSION) {
"Kotlin/Native Gradle plugin is incompatible with this version of Gradle.\n" +
"The minimal required version is ${REQUIRED_GRADLE_VERSION}\n" +
"Current version is ${current}"
}
}
override fun apply(project: ProjectInternal?) {
if (project == null) {
return
}
checkGradleVersion()
registry.register(KonanToolingModelBuilder)
project.plugins.apply("base")
// Create necessary tasks and extensions.
@@ -16,8 +16,8 @@
package org.jetbrains.kotlin.gradle.plugin.model
import org.jetbrains.kotlin.gradle.plugin.tasks.Produce
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.konan.KonanVersion
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import java.io.File
import java.io.Serializable
@@ -26,8 +26,10 @@ import java.io.Serializable
* This model is shared with the client processes such as an IDE.
*/
interface KonanModel : Serializable {
val konanHome: String
val konanVersion: String
val konanHome: File
val konanVersion: KonanVersion
val languageVersion: String?
val apiVersion: String?
val artifacts: List<KonanModelArtifact>
}
@@ -37,11 +39,12 @@ interface KonanModel : Serializable {
*/
interface KonanModelArtifact : Serializable {
val name: String
val type: Produce
val targetPlatform: KonanTarget
val type: CompilerOutputKind
val targetPlatform: String
val file: File
val buildTaskName: String
val srcDirs: List<File>
val srcFiles: List<File>
val libraries: List<File>
val searchPaths: List<File>
}
@@ -5,10 +5,8 @@ import org.gradle.tooling.provider.model.ToolingModelBuilder
import org.jetbrains.kotlin.gradle.plugin.konanArtifactsContainer
import org.jetbrains.kotlin.gradle.plugin.konanExtension
import org.jetbrains.kotlin.gradle.plugin.konanHome
import org.jetbrains.kotlin.gradle.plugin.tasks.KonanBuildingTask
import org.jetbrains.kotlin.gradle.plugin.tasks.KonanCompileTask
import org.jetbrains.kotlin.gradle.plugin.tasks.Produce
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.konan.KonanVersion
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import java.io.File
@@ -20,26 +18,31 @@ object KonanToolingModelBuilder : ToolingModelBuilder {
val artifacts = project.konanArtifactsContainer.flatten().toList().map { it.toModelArtifact() }
return KonanModelImpl(
artifacts,
project.konanHome,
// TODO: Provide a better support for the default version
project.konanExtension.languageVersion ?: "1.2"
project.file(project.konanHome),
KonanVersion.CURRENT,
// TODO: Provide defaults for these versions.
project.konanExtension.languageVersion,
project.konanExtension.apiVersion
)
}
}
internal data class KonanModelImpl(
override val artifacts: List<KonanModelArtifact>,
override val konanHome: String,
override val konanVersion: String
override val konanHome: File,
override val konanVersion: KonanVersion,
override val languageVersion: String?,
override val apiVersion: String?
) : KonanModel
internal data class KonanModelArtifactImpl(
override val name: String,
override val file: File,
override val type: Produce,
override val targetPlatform: KonanTarget,
override val type: CompilerOutputKind,
override val targetPlatform: String,
override val buildTaskName: String,
override val srcDirs: List<File>,
override val srcFiles: List<File>,
override val libraries: List<File>
override val libraries: List<File>,
override val searchPaths: List<File>
) : KonanModelArtifact
@@ -22,17 +22,11 @@ import org.gradle.api.tasks.*
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifactImpl
import org.jetbrains.kotlin.konan.library.defaultResolver
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.Distribution
import java.io.File
enum class Produce(val cliOption: String, val kind: CompilerOutputKind) {
PROGRAM("program", CompilerOutputKind.PROGRAM),
DYNAMIC("dynamic", CompilerOutputKind.DYNAMIC),
FRAMEWORK("framework", CompilerOutputKind.FRAMEWORK),
LIBRARY("library", CompilerOutputKind.LIBRARY),
BITCODE("bitcode", CompilerOutputKind.BITCODE)
}
/**
* A task compiling the target executable/library using Kotlin/Native compiler
*/
@@ -40,16 +34,16 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec {
@Internal override val toolRunner = KonanCompilerRunner(project)
abstract val produce: Produce
abstract val produce: CompilerOutputKind
@Internal get
// Output artifact --------------------------------------------------------
override val artifactSuffix: String
@Internal get() = produce.kind.suffix(konanTarget)
@Internal get() = produce.suffix(konanTarget)
override val artifactPrefix: String
@Internal get() = produce.kind.prefix(konanTarget)
@Internal get() = produce.prefix(konanTarget)
// Multiplatform support --------------------------------------------------
@@ -119,7 +113,7 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec {
addArgs("-library", libraries.artifacts.map { it.artifact.canonicalPath })
addFileArgs("-nativelibrary", nativeLibraries)
addArg("-produce", produce.cliOption)
addArg("-produce", produce.name.toLowerCase())
addListArg("-linkerOpts", linkerOpts)
@@ -222,41 +216,51 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec {
// endregion
// region IDE model
override fun toModelArtifact(): KonanModelArtifact = KonanModelArtifactImpl(
artifactName,
artifact,
produce,
konanTarget,
name,
allSources.filter { it is ConfigurableFileTree }.map { (it as ConfigurableFileTree).dir },
allSourceFiles,
libraries.asFiles()
)
override fun toModelArtifact(): KonanModelArtifact {
val repos = libraries.repos
val resolver = defaultResolver(
repos.map { it.absolutePath },
konanTarget,
Distribution(konanHomeOverride = project.konanHome)
)
return KonanModelArtifactImpl(
artifactName,
artifact,
produce,
konanTarget.name,
name,
allSources.filterIsInstance(ConfigurableFileTree::class.java).map { it.dir },
allSourceFiles,
libraries.asFiles(resolver),
repos.toList()
)
}
// endregion
}
open class KonanCompileProgramTask: KonanCompileTask() {
override val produce: Produce get() = Produce.PROGRAM
override val produce: CompilerOutputKind get() = CompilerOutputKind.PROGRAM
}
open class KonanCompileDynamicTask: KonanCompileTask() {
override val produce: Produce get() = Produce.DYNAMIC
override val produce: CompilerOutputKind get() = CompilerOutputKind.DYNAMIC
val headerFile: File
@OutputFile get() = destinationDir.resolve("$artifactPrefix${artifactName}_api.h")
}
open class KonanCompileFrameworkTask: KonanCompileTask() {
override val produce: Produce get() = Produce.FRAMEWORK
override val produce: CompilerOutputKind get() = CompilerOutputKind.FRAMEWORK
override val artifact
@OutputDirectory get() = super.artifact
}
open class KonanCompileLibraryTask: KonanCompileTask() {
override val produce: Produce get() = Produce.LIBRARY
override val produce: CompilerOutputKind get() = CompilerOutputKind.LIBRARY
}
open class KonanCompileBitcodeTask: KonanCompileTask() {
override val produce: Produce get() = Produce.BITCODE
override val produce: CompilerOutputKind get() = CompilerOutputKind.BITCODE
}
@@ -25,6 +25,9 @@ import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.KonanInteropSpec.IncludeDirectoriesSpec
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifactImpl
import org.jetbrains.kotlin.konan.library.defaultResolver
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.Distribution
import org.jetbrains.kotlin.konan.target.KonanTarget
import java.io.File
@@ -155,16 +158,26 @@ open class KonanInteropTask: KonanBuildingTask(), KonanInteropSpec {
// endregion
// region IDE model
override fun toModelArtifact(): KonanModelArtifact = KonanModelArtifactImpl(
artifactName,
artifact,
Produce.LIBRARY,
konanTarget,
name,
listOfNotNull(defFile.parentFile),
listOf(defFile),
libraries.asFiles()
)
override fun toModelArtifact(): KonanModelArtifact {
val repos = libraries.repos
val resolver = defaultResolver(
repos.map { it.absolutePath },
konanTarget,
Distribution(konanHomeOverride = project.konanHome)
)
return KonanModelArtifactImpl(
artifactName,
artifact,
CompilerOutputKind.LIBRARY,
konanTarget.name,
name,
listOfNotNull(defFile.parentFile),
listOf(defFile),
libraries.asFiles(resolver),
repos.toList()
)
}
// endregion
}
@@ -0,0 +1,44 @@
/*
* 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.gradle.plugin.test
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import java.io.File
import kotlin.test.*
open class CompatibilityTests {
val tmpFolder = TemporaryFolder()
@Rule get
val projectDirectory: File
get() = tmpFolder.root
@Test
fun `Plugin should fail if running with Gradle prior to the required one`() {
val project = KonanProject.createEmpty(projectDirectory)
val result = project
.createRunner()
.withGradleVersion("4.5")
.withArguments("tasks")
.buildAndFail()
println(result.output)
assertTrue("Build doesn't show the warning message") {
result.output.contains("Kotlin/Native Gradle plugin is incompatible with this version of Gradle.")
}
}
}
@@ -1,3 +1,19 @@
/*
* 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.gradle.plugin.test
import org.jetbrains.kotlin.gradle.plugin.test.KonanProject.escapeBackSlashes
@@ -11,7 +27,7 @@ import java.io.File
import kotlin.test.*
@RunWith(Spockito::class)
open class PropertiesAsEnvVariables {
open class PropertiesAsEnvVariablesTest {
val tmpFolder = TemporaryFolder()
@Rule get
@@ -0,0 +1,203 @@
/*
* 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.gradle.plugin.test
import org.jetbrains.kotlin.konan.KonanVersion
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import java.io.File
import java.nio.file.Paths
import kotlin.test.Test
open class ToolingModelTests {
val tmpFolder = TemporaryFolder()
@Rule get
val projectDirectory: File
get() = tmpFolder.root
@Test
fun `The model should be serialized without exceptions`() {
val project = KonanProject.createEmpty(projectDirectory).apply {
buildFile.appendText("""
konanArtifacts {
library('foo') {
srcDir 'src/foo/kotlin'
}
interop('bar')
program('main') {
libraries {
artifact konanArtifacts.foo
artifact konanArtifacts.bar
klib 'posix'
}
}
}
import org.jetbrains.kotlin.gradle.plugin.model.*
task testSerialization {
doLast {
def model = KonanToolingModelBuilder.INSTANCE.buildAll("KonanModel", project)
file("model.bin").withObjectOutputStream {
it.writeObject(model)
}
KonanModelImpl deserializedModel
file("model.bin").withObjectInputStream(model.getClass().getClassLoader()) { stream ->
deserializedModel = (KonanModelImpl) stream.readObject()
}
if (!deserializedModel.equals(model)) {
throw new AssertionError("The deserialized model doesn't equal to the initial one")
}
}
}
""".trimIndent())
generateSrcFile("main.kt")
generateSrcFile(Paths.get("src", "foo", "kotlin"), "foo.kt", "fun foo() = 1")
generateSrcFile(Paths.get("src", "bar", "kotlin"), "bar.kt", "fun bar() = 1")
generateDefFile("baz.def", "")
generateDefFile("qux.def", "")
}
project.createRunner().withArguments("testSerialization").build()
}
@Test
fun `The model should contain the same data as the Gradle tasks`() {
val project = KonanProject.createEmpty(projectDirectory, listOf("host", "wasm32")).apply {
val konanVersion = KonanVersion.CURRENT.toString()
generateSrcFile(listOf("src", "foo1"), "foo1.kt", "fun foo1() = 0")
generateSrcFile(listOf("src", "foo1"), "foo11.kt", "fun foo11() = 0")
generateSrcFile(listOf("src", "foo2"), "foo2.kt", "fun foo2() = 0")
generateSrcFile(listOf("defs_bar"), "bar.def", "")
generateSrcFile(listOf("src", "baz"), "baz.kt", "fun baz() = 0")
generateSrcFile("main.kt")
createSubDir("custom_repo")
buildFile.appendText("""
konanArtifacts {
library('foo') {
srcDir 'src/foo1'
srcDir 'src/foo2'
}
interop('bar') {
defFile 'defs_bar/bar.def'
}
library('baz') {
srcDir 'src/baz'
}
program('main') {
libraries {
artifact konanArtifacts.foo
artifact konanArtifacts.bar
klib 'baz'
useRepo 'custom_repo'
}
}
}
konan {
languageVersion = "1.2"
apiVersion = "1.2"
}
import org.jetbrains.kotlin.gradle.plugin.model.*
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
public <T> void assertEquals(
T actual,
T expected,
String message = "${'$'}expected expected but ${'$'}actual found") {
if (expected != actual) {
throw new AssertionError(message)
}
}
public <T> void assertContentEquals(
Collection<T> actual,
Collection<T> expected,
String message = "${'$'}expected\nexpected but\n${'$'}actual\nfound") {
if (actual.size() != expected.size() || !actual.containsAll(expected)) {
throw new AssertionError(message)
}
}
task testModelData {
dependsOn('compileKonanBaz')
doLast {
def model = KonanToolingModelBuilder.INSTANCE.buildAll("KonanModel", project)
assertEquals(model.konanHome, file(project.getProperty('konan.home')))
assertEquals(model.konanVersion.toString(), "$konanVersion")
assertEquals(model.languageVersion, "1.2")
assertEquals(model.apiVersion, "1.2")
model.artifacts.each {
def konanArtifact = konanArtifacts[it.name]
def target = it.targetPlatform
def task = konanArtifact.getByTarget(target)
assertEquals(it.file, task.artifact)
assertEquals(it.buildTaskName, task.name)
switch(it.name) {
case 'foo':
assertEquals(it.type, CompilerOutputKind.valueOf('LIBRARY'))
assertContentEquals(it.srcDirs, [file('src/foo1'), file('src/foo2')])
assertContentEquals(it.srcFiles, [
file('src/foo1/foo1.kt'),
file('src/foo1/foo11.kt'),
file('src/foo2/foo2.kt')])
assertContentEquals(it.libraries, [])
assertContentEquals(it.searchPaths, [task.artifact.parentFile])
break
case 'bar':
assertEquals(it.type, CompilerOutputKind.valueOf('LIBRARY'))
assertContentEquals(it.srcDirs, [file('defs_bar')])
assertContentEquals(it.srcFiles, [file('defs_bar/bar.def')])
assertContentEquals(it.libraries, [])
assertContentEquals(it.searchPaths, [task.artifact.parentFile])
break
case 'main':
assertEquals(it.type, CompilerOutputKind.valueOf('PROGRAM'))
assertContentEquals(it.srcDirs, [file('src/main/kotlin')])
assertContentEquals(it.srcFiles, [file('src/main/kotlin/main.kt')])
assertContentEquals(it.libraries, [
konanArtifacts['foo'].getByTarget(target).artifact,
konanArtifacts['bar'].getByTarget(target).artifact,
konanArtifacts['baz'].getByTarget(target).artifact
])
assertContentEquals(it.searchPaths, [
file('custom_repo'),
task.artifact.parentFile,
konanArtifacts.foo.getByTarget(target).artifact.parentFile
])
break
}
}
}
}
""".trimIndent())
}
project.createRunner().withArguments("testModelData").build()
}
}