Add missing DSL features to the MPP dependencies DSL
* Add DSL for project(...) with path and configuration
* Add DSL for e.g. api(someDependency) { /* ... */ }
* Add DSL for e.g. api(kotlin("stdlib"))
Issue #KT-26663 Fixed
This commit is contained in:
+35
-4
@@ -6,12 +6,43 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.artifacts.Dependency
|
||||
import org.gradle.api.artifacts.ExternalModuleDependency
|
||||
import org.gradle.api.artifacts.ProjectDependency
|
||||
import org.gradle.util.ConfigureUtil
|
||||
|
||||
interface KotlinDependencyHandler {
|
||||
fun api(dependencyNotation: Any)
|
||||
fun implementation(dependencyNotation: Any)
|
||||
fun compileOnly(dependencyNotation: Any)
|
||||
fun runtimeOnly(dependencyNotation: Any)
|
||||
fun api(dependencyNotation: Any): Dependency?
|
||||
fun api(dependencyNotation: String, configure: ExternalModuleDependency.() -> Unit): ExternalModuleDependency
|
||||
fun <T : Dependency> api(dependency: T, configure: T.() -> Unit): T
|
||||
fun api(dependencyNotation: String, configure: Closure<*>) = api(dependencyNotation) { ConfigureUtil.configure(configure, this) }
|
||||
fun <T : Dependency> api(dependency: T, configure: Closure<*>) = api(dependency) { ConfigureUtil.configure(configure, this) }
|
||||
|
||||
fun implementation(dependencyNotation: Any): Dependency?
|
||||
fun implementation(dependencyNotation: String, configure: ExternalModuleDependency.() -> Unit): ExternalModuleDependency
|
||||
fun <T : Dependency> implementation(dependency: T, configure: T.() -> Unit): T
|
||||
fun implementation(dependencyNotation: String, configure: Closure<*>) = implementation(dependencyNotation) { ConfigureUtil.configure(configure, this) }
|
||||
fun <T : Dependency> implementation(dependency: T, configure: Closure<*>) = implementation(dependency) { ConfigureUtil.configure(configure, this) }
|
||||
|
||||
fun compileOnly(dependencyNotation: Any): Dependency?
|
||||
fun compileOnly(dependencyNotation: String, configure: ExternalModuleDependency.() -> Unit): ExternalModuleDependency
|
||||
fun <T : Dependency> compileOnly(dependency: T, configure: T.() -> Unit): T
|
||||
fun compileOnly(dependencyNotation: String, configure: Closure<*>) = compileOnly(dependencyNotation) { ConfigureUtil.configure(configure, this) }
|
||||
fun <T : Dependency> compileOnly(dependency: T, configure: Closure<*>) = compileOnly(dependency) { ConfigureUtil.configure(configure, this) }
|
||||
|
||||
fun runtimeOnly(dependencyNotation: Any): Dependency?
|
||||
fun runtimeOnly(dependencyNotation: String, configure: ExternalModuleDependency.() -> Unit): ExternalModuleDependency
|
||||
fun <T : Dependency> runtimeOnly(dependency: T, configure: T.() -> Unit): T
|
||||
fun runtimeOnly(dependencyNotation: String, configure: Closure<*>) = runtimeOnly(dependencyNotation) { ConfigureUtil.configure(configure, this) }
|
||||
fun <T : Dependency> runtimeOnly(dependency: T, configure: Closure<*>) = runtimeOnly(dependency) { ConfigureUtil.configure(configure, this) }
|
||||
|
||||
fun kotlin(simpleModuleName: String): ExternalModuleDependency = kotlin(simpleModuleName, null)
|
||||
fun kotlin(simpleModuleName: String, version: String?): ExternalModuleDependency
|
||||
|
||||
fun project(path: String, configuration: String? = null): ProjectDependency =
|
||||
project(listOf("path", "configuration").zip(listOfNotNull(path, configuration)).toMap())
|
||||
|
||||
fun project(notation: Map<String, Any?>): ProjectDependency
|
||||
}
|
||||
|
||||
interface HasKotlinDependencies {
|
||||
|
||||
+31
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.gradle.plugin.sources.SourceSetConsistencyChecks
|
||||
import org.jetbrains.kotlin.gradle.util.checkBytecodeContains
|
||||
import org.jetbrains.kotlin.gradle.util.isWindows
|
||||
import org.jetbrains.kotlin.gradle.util.modify
|
||||
import org.jetbrains.kotlin.gradle.util.testResolveAllConfigurations
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.junit.Assert
|
||||
@@ -1171,6 +1172,36 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDependenciesDsl() = with(transformProjectWithPluginsDsl("newMppDependenciesDsl", GradleVersionRequired.AtLeast("4.10"))) {
|
||||
val originalBuildscriptContent = gradleBuildScript("app").readText()
|
||||
|
||||
fun testDependencies() = testResolveAllConfigurations("app") {
|
||||
assertContains(">> :app:testNonTransitiveStringNotationApi --> junit-4.12.jar")
|
||||
assertEquals(1, (Regex.escape(">> :app:testNonTransitiveStringNotationApi") + " .*").toRegex().findAll(output).count())
|
||||
|
||||
assertContains(">> :app:testNonTransitiveDependencyNotationApi --> kotlin-reflect-${defaultBuildOptions().kotlinVersion}.jar")
|
||||
assertEquals(1, (Regex.escape(">> :app:testNonTransitiveStringNotationApi") + " .*").toRegex().findAll(output).count())
|
||||
|
||||
assertContains(">> :app:testExplicitKotlinVersionApi --> kotlin-reflect-1.3.0.jar")
|
||||
assertContains(">> :app:testExplicitKotlinVersionImplementation --> kotlin-reflect-1.2.71.jar")
|
||||
assertContains(">> :app:testExplicitKotlinVersionCompileOnly --> kotlin-reflect-1.2.70.jar")
|
||||
assertContains(">> :app:testExplicitKotlinVersionRuntimeOnly --> kotlin-reflect-1.2.60.jar")
|
||||
|
||||
assertContains(">> :app:testProjectWithConfigurationApi --> output.txt")
|
||||
}
|
||||
|
||||
testDependencies()
|
||||
|
||||
// Then run with Gradle Kotlin DSL; the build script needs only one correction to be a valid GK DSL script:
|
||||
gradleBuildScript("app").run {
|
||||
modify { originalBuildscriptContent.replace(": ", " = ") }
|
||||
renameTo(projectDir.resolve("app/build.gradle.kts"))
|
||||
}
|
||||
|
||||
testDependencies()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUnusedSourceSetsReport() = with(Project("sample-lib", gradleVersion, "new-mpp-lib-and-app")) {
|
||||
setupWorkingDir()
|
||||
|
||||
+34
-1
@@ -19,7 +19,14 @@ fun BaseGradleIT.Project.testResolveAllConfigurations(
|
||||
) = with(testCase) {
|
||||
|
||||
setupWorkingDir()
|
||||
gradleBuildScript(subproject).appendText("\n" + generateResolveAllConfigurationsTask(excludePredicate))
|
||||
gradleBuildScript(subproject).run {
|
||||
val taskCode = when (extension) {
|
||||
"gradle" -> generateResolveAllConfigurationsTask(excludePredicate)
|
||||
"kts" -> generateResolveAllConfigurationsTaskKts(excludePredicate)
|
||||
else -> error("Unexpected build script extension $extension")
|
||||
}
|
||||
appendText("\n" + taskCode)
|
||||
}
|
||||
|
||||
build(RESOLVE_ALL_CONFIGURATIONS_TASK_NAME) {
|
||||
assertSuccessful()
|
||||
@@ -52,4 +59,30 @@ private fun generateResolveAllConfigurationsTask(exclude: String) =
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
private fun generateResolveAllConfigurationsTaskKts(exclude: String) =
|
||||
"""
|
||||
tasks.create("$RESOLVE_ALL_CONFIGURATIONS_TASK_NAME") {
|
||||
doFirst {
|
||||
project.configurations
|
||||
.filter { it.isCanBeResolved }
|
||||
.filterNot { $exclude }
|
||||
.forEach { configuration ->
|
||||
val path = (configuration as org.gradle.api.internal.artifacts.configurations.ConfigurationInternal).path
|
||||
try {
|
||||
println("Resolving ${'$'}path")
|
||||
configuration.files.forEach { println(">> ${'$'}path --> ${'$'}{it.name}") }
|
||||
println("OK, resolved ${'$'}path\n")
|
||||
} catch (e: Throwable) {
|
||||
var ex = e as Throwable?
|
||||
while (ex != null) {
|
||||
println(ex.message)
|
||||
ex = ex.cause
|
||||
}
|
||||
println("$UNRESOLVED_MARKER ${'$'}{configuration.name}\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
+3
-3
@@ -31,18 +31,18 @@ kotlin {
|
||||
sourceSets {
|
||||
val commonMain by getting {
|
||||
dependencies {
|
||||
api("org.jetbrains.kotlin:kotlin-stdlib-common")
|
||||
api(kotlin("stdlib-common"))
|
||||
}
|
||||
}
|
||||
jvm.compilations["main"].defaultSourceSet {
|
||||
dependencies {
|
||||
api("org.jetbrains.kotlin:kotlin-stdlib")
|
||||
api(kotlin("stdlib"))
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:0.23.4")
|
||||
}
|
||||
}
|
||||
js.compilations["main"].defaultSourceSet {
|
||||
dependencies {
|
||||
api("org.jetbrains.kotlin:kotlin-stdlib-js")
|
||||
api(kotlin("stdlib-js"))
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-html-js:0.6.11")
|
||||
}
|
||||
}
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
plugins {
|
||||
id("org.jetbrains.kotlin.multiplatform").version("<pluginMarkerVersion>")
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvm("jvm6")
|
||||
js { }
|
||||
|
||||
sourceSets {
|
||||
create("testNonTransitiveStringNotation") {
|
||||
dependencies {
|
||||
api("junit:junit:4.12") { setTransitive(false) }
|
||||
}
|
||||
}
|
||||
create("testNonTransitiveDependencyNotation") {
|
||||
dependencies {
|
||||
api(kotlin("reflect")) { setTransitive(false) }
|
||||
}
|
||||
}
|
||||
create("testExplicitKotlinVersion") {
|
||||
dependencies {
|
||||
api(kotlin("reflect", "1.3.0"))
|
||||
implementation(kotlin("reflect", "1.2.71"))
|
||||
compileOnly(kotlin("reflect", "1.2.70"))
|
||||
runtimeOnly(kotlin("reflect", "1.2.60"))
|
||||
}
|
||||
}
|
||||
create("testProjectWithConfiguration") {
|
||||
dependencies {
|
||||
api(project(path: ":lib", configuration: "outputConfiguration"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
configurations {
|
||||
outputConfiguration
|
||||
}
|
||||
|
||||
artifacts {
|
||||
outputConfiguration file('output.txt')
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
include ':lib', ':app'
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Dependency
|
||||
import org.gradle.api.artifacts.ExternalModuleDependency
|
||||
import org.gradle.api.artifacts.ProjectDependency
|
||||
import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
|
||||
|
||||
class DefaultKotlinDependencyHandler(
|
||||
val parent: HasKotlinDependencies,
|
||||
val project: Project
|
||||
) : KotlinDependencyHandler {
|
||||
override fun api(dependencyNotation: Any): Dependency? =
|
||||
addDependencyByAnyNotation(parent.apiConfigurationName, dependencyNotation)
|
||||
|
||||
override fun api(dependencyNotation: String, configure: ExternalModuleDependency.() -> Unit): ExternalModuleDependency =
|
||||
addDependencyByStringNotation(parent.apiConfigurationName, dependencyNotation, configure)
|
||||
|
||||
override fun <T : Dependency> api(dependency: T, configure: T.() -> Unit): T =
|
||||
addDependency(parent.apiConfigurationName, dependency, configure)
|
||||
|
||||
override fun implementation(dependencyNotation: Any): Dependency? =
|
||||
addDependencyByAnyNotation(parent.implementationConfigurationName, dependencyNotation)
|
||||
|
||||
override fun implementation(dependencyNotation: String, configure: ExternalModuleDependency.() -> Unit): ExternalModuleDependency =
|
||||
addDependencyByStringNotation(parent.implementationConfigurationName, dependencyNotation, configure)
|
||||
|
||||
override fun <T : Dependency> implementation(dependency: T, configure: T.() -> Unit): T =
|
||||
addDependency(parent.implementationConfigurationName, dependency, configure)
|
||||
|
||||
override fun compileOnly(dependencyNotation: Any): Dependency? =
|
||||
addDependencyByAnyNotation(parent.compileOnlyConfigurationName, dependencyNotation)
|
||||
|
||||
override fun compileOnly(dependencyNotation: String, configure: ExternalModuleDependency.() -> Unit): ExternalModuleDependency =
|
||||
addDependencyByStringNotation(parent.compileOnlyConfigurationName, dependencyNotation, configure)
|
||||
|
||||
override fun <T : Dependency> compileOnly(dependency: T, configure: T.() -> Unit): T =
|
||||
addDependency(parent.compileOnlyConfigurationName, dependency, configure)
|
||||
|
||||
override fun runtimeOnly(dependencyNotation: Any): Dependency? =
|
||||
addDependencyByAnyNotation(parent.runtimeOnlyConfigurationName, dependencyNotation)
|
||||
|
||||
override fun runtimeOnly(dependencyNotation: String, configure: ExternalModuleDependency.() -> Unit): ExternalModuleDependency =
|
||||
addDependencyByStringNotation(parent.runtimeOnlyConfigurationName, dependencyNotation, configure)
|
||||
|
||||
override fun <T : Dependency> runtimeOnly(dependency: T, configure: T.() -> Unit): T =
|
||||
addDependency(parent.runtimeOnlyConfigurationName, dependency, configure)
|
||||
|
||||
override fun kotlin(simpleModuleName: String, version: String?): ExternalModuleDependency =
|
||||
project.dependencies.create(
|
||||
"org.jetbrains.kotlin:kotlin-$simpleModuleName" + version?.let { ":$it" }.orEmpty()
|
||||
) as ExternalModuleDependency
|
||||
|
||||
override fun project(notation: Map<String, Any?>): ProjectDependency =
|
||||
project.dependencies.project(notation) as ProjectDependency
|
||||
|
||||
private fun addDependencyByAnyNotation(
|
||||
configurationName: String,
|
||||
dependencyNotation: Any
|
||||
): Dependency? =
|
||||
project.dependencies.add(configurationName, dependencyNotation)
|
||||
|
||||
private fun addDependencyByStringNotation(
|
||||
configurationName: String,
|
||||
dependencyNotation: Any,
|
||||
configure: ExternalModuleDependency.() -> Unit = { }
|
||||
): ExternalModuleDependency =
|
||||
addDependency(configurationName, project.dependencies.create(dependencyNotation) as ExternalModuleDependency, configure)
|
||||
|
||||
private fun <T : Dependency> addDependency(
|
||||
configurationName: String,
|
||||
dependency: T,
|
||||
configure: T.() -> Unit
|
||||
): T =
|
||||
dependency.also {
|
||||
configure(it)
|
||||
project.dependencies.add(configurationName, it)
|
||||
}
|
||||
}
|
||||
+1
-18
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
@@ -38,23 +38,6 @@ internal fun KotlinCompilation<*>.composeName(prefix: String? = null, suffix: St
|
||||
internal val KotlinCompilation<*>.defaultSourceSetName: String
|
||||
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName)
|
||||
|
||||
internal class DefaultKotlinDependencyHandler(
|
||||
val parent: HasKotlinDependencies,
|
||||
val project: Project
|
||||
) : KotlinDependencyHandler {
|
||||
override fun api(dependencyNotation: Any) = addDependency(parent.apiConfigurationName, dependencyNotation)
|
||||
|
||||
override fun implementation(dependencyNotation: Any) = addDependency(parent.implementationConfigurationName, dependencyNotation)
|
||||
|
||||
override fun compileOnly(dependencyNotation: Any) = addDependency(parent.compileOnlyConfigurationName, dependencyNotation)
|
||||
|
||||
override fun runtimeOnly(dependencyNotation: Any) = addDependency(parent.runtimeOnlyConfigurationName, dependencyNotation)
|
||||
|
||||
private fun addDependency(configurationName: String, dependencyNotation: Any) {
|
||||
project.dependencies.add(configurationName, dependencyNotation)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
|
||||
target: KotlinTarget,
|
||||
override val compilationName: String
|
||||
|
||||
Reference in New Issue
Block a user