Provide matching strategy for attributes + fix tests

This commit is contained in:
Ilya Matveev
2018-09-21 14:17:07 +03:00
committed by Ilya Matveev
parent c15407028e
commit 5e21253940
3 changed files with 92 additions and 9 deletions
@@ -0,0 +1,67 @@
/*
* 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.experimental.internal
import org.gradle.api.attributes.*
open class Compatible: AttributeCompatibilityRule<Boolean> {
override fun execute(details: CompatibilityCheckDetails<Boolean>) = details.compatible()
}
open class PreferValue(val defaultPreferred: Boolean): AttributeDisambiguationRule<Boolean> {
override fun execute(details: MultipleCandidatesDetails<Boolean>) = with(details) {
val preferredValue = consumerValue ?: defaultPreferred
if (candidateValues.contains(preferredValue)) {
closestMatch(preferredValue)
} else {
closestMatch(!preferredValue)
}
}
}
open class DebuggableDisambiguation: PreferValue(false)
open class OptimizedDisambiguation: PreferValue(false)
open class UsageCompatibility: AttributeCompatibilityRule<Usage> {
override fun execute(details: CompatibilityCheckDetails<Usage>) = with(details) {
val requested = consumerValue?.name
val provided = producerValue?.name
when {
requested == null -> compatible()
requested == Usage.JAVA_API && (provided == Usage.JAVA_API || provided == KotlinNativeUsage.KLIB) -> {
compatible()
}
requested == provided -> compatible()
}
}
}
open class UsageDisambiguation: AttributeDisambiguationRule<Usage> {
override fun execute(details: MultipleCandidatesDetails<Usage>): Unit = with(details) {
val usagePriority = listOf(Usage.JAVA_API, KotlinNativeUsage.KLIB)
usagePriority.forEach { usage ->
val found = candidateValues.find { it.name == usage }
if (found != null) {
closestMatch(found)
return
}
}
}
}
@@ -20,6 +20,8 @@ import org.gradle.api.DefaultTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.attributes.AttributeCompatibilityRule
import org.gradle.api.attributes.Usage
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.internal.FeaturePreviews
import org.gradle.api.internal.project.ProjectInternal
@@ -28,6 +30,7 @@ import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.HelpTasksPlugin
import org.gradle.api.tasks.TaskContainer
import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.gradle.language.cpp.CppBinary
import org.gradle.language.plugins.NativeBasePlugin
import org.gradle.nativeplatform.test.tasks.RunTestExecutable
import org.gradle.util.GradleVersion
@@ -279,6 +282,21 @@ class KotlinNativeBasePlugin: Plugin<ProjectInternal> {
return result
}
private fun Project.setUpMatchingStrategy(): Unit = with(dependencies.attributesSchema) {
attribute(CppBinary.DEBUGGABLE_ATTRIBUTE).apply {
compatibilityRules.add(Compatible::class.java)
disambiguationRules.add(DebuggableDisambiguation::class.java)
}
attribute(CppBinary.OPTIMIZED_ATTRIBUTE).apply {
compatibilityRules.add(Compatible::class.java)
disambiguationRules.add(OptimizedDisambiguation::class.java)
}
attribute(Usage.USAGE_ATTRIBUTE).apply {
compatibilityRules.add(UsageCompatibility::class.java)
disambiguationRules.add(UsageDisambiguation::class.java)
}
}
override fun apply(project: ProjectInternal): Unit = with(project) {
// TODO: Deal with compiler downloading.
// Apply base plugins
@@ -289,6 +307,7 @@ class KotlinNativeBasePlugin: Plugin<ProjectInternal> {
checkGradleVersion()
addCompilerDownloadingTask()
setUpMatchingStrategy()
addCompilationTasks()
addInteropTasks()
addTargetInfoTask()
@@ -106,9 +106,7 @@ class ExperimentalPluginTests {
val compileReleaseResult = project.createRunner().withArguments("compileReleaseKotlinNative").build()
assertEquals(TaskOutcome.SUCCESS, compileReleaseResult.task(":compileReleaseKotlinNative")?.outcome)
assertEquals(TaskOutcome.SUCCESS, compileReleaseResult.task(":library:compileReleaseKotlinNative")?.outcome)
assertTrue(projectDirectory.resolve("build/exe/main/release/test.$exeSuffix").exists())
assertTrue(libraryDir.resolve("build/lib/main/release/library.klib").exists())
assertEquals(TaskOutcome.UP_TO_DATE, compileReleaseResult.task(":library:compileDebugKotlinNative")?.outcome)
}
@Test
@@ -451,7 +449,7 @@ class ExperimentalPluginTests {
""".trimIndent())
}
val outputKinds = arrayOf(OutputKind.EXECUTABLE, OutputKind.KLIBRARY, OutputKind.FRAMEWORK)
val outputKinds = arrayOf(OutputKind.EXECUTABLE, OutputKind.FRAMEWORK)
val buildTypes = arrayOf("Debug", "Release")
val targets = arrayOf(HostManager.host, KonanTarget.WASM32)
@@ -460,7 +458,7 @@ class ExperimentalPluginTests {
buildTypes.map { type ->
":compile${type}${kind.name.toLowerCase().capitalize()}${target.name.capitalize()}KotlinNative"
}
}
} + ":compileDebug${OutputKind.KLIBRARY.name.toLowerCase().capitalize()}${target.name.capitalize()}KotlinNative"
}
val result1 = project.createRunner().withArguments("assemble").build()
@@ -695,7 +693,6 @@ class ExperimentalPluginTests {
rootProject.createRunner().withArguments(":libFoo:publish", ":libBar:publish").build()
assertFileExists("repo/test/libFoo_debug/1.0/libFoo_debug-1.0-interop-mystdio.klib")
assertFileExists("repo/test/libFoo_release/1.0/libFoo_release-1.0-interop-mystdio.klib")
// A dependency on a published library
rootProject.buildFile.writeText("""
@@ -809,13 +806,13 @@ class ExperimentalPluginTests {
val nameToArtifact = model.artifacts.map { it.name to it }.toMap()
val buildTypes = listOf("debug", "release")
val kinds = listOf(OutputKind.EXECUTABLE, OutputKind.KLIBRARY)
val targets = listOf(HostManager.host, KonanTarget.WASM32)
// Production binaries
buildTypes.forEach { buildType ->
kinds.forEach { kind ->
kinds.forEach { kind ->
val buildTypes = if (kind == OutputKind.KLIBRARY) listOf("debug") else listOf("debug", "release")
buildTypes.forEach { buildType ->
targets.forEach { target ->
val suffix = "${buildType.capitalize()}${kind.name.toLowerCase().capitalize()}${target.name.capitalize()}"
val artifact = nameToArtifact.getValue("main$suffix")