【问题标题】:Modifying tasks in gradle plugin in buildSrc with kotlin dsl使用 kotlin dsl 在 buildSrc 中修改 gradle 插件中的任务
【发布时间】:2022-12-09 17:45:36
【问题描述】:

我在 buildSrc/src/main/kotlin/foo.bar.kts 中有一个 Gradle 插件,我正在尝试修改任务,但这些修改失败了。如果我删除任务修改部分,其余部分,即设置存储库,就可以正常工作。

我想我缺少语法 how to modify tasks in the module that imports this plugin。

buildSrc/src/main/kotlin/foo.bar.kts:

repositories {
    mavenCentral()
}

tasks.test {
    useJUnitPlatform()
}

tasks.withType<KotlinCompile>() {
    kotlinOptions.jvmTarget = "11"
}

在我的build.gradle.kts中使用插件

plugins {
  id("foo.bar")
}

./gradlew clean build 生成的错误

> Task :buildSrc:compileKotlin FAILED
e: /some/path/buildSrc/src/main/kotlin/foo.bar.gradle.kts: (8, 7): Unresolved reference: test
e: /some/path/buildSrc/src/main/kotlin/foo.bar.gradle.kts: (9, 5): Unresolved reference: useJUnitPlatform
e: /some/path/buildSrc/src/main/kotlin/foo.bar.gradle.kts: (12, 16): Unresolved reference: KotlinCompile
e: /some/path/buildSrc/src/main/kotlin/foo.bar.gradle.kts: (12, 33): Type mismatch: inferred type is () -> Unit but Class<TypeVariable(S)!> was expected
e: /some/path/buildSrc/src/main/kotlin/foo.bar.gradle.kts: (13, 5): Unresolved reference: kotlinOptions
e: /some/path/code/buildSrc/src/main/kotlin/foo.bar.gradle.kts: (13, 19): Variable expected

【问题讨论】:

    标签: kotlin gradle gradle-kotlin-dsl


    【解决方案1】:

    那是因为 foo.bar.kts 来自 buildSrc 必须先编译,所以它必须是自包含的。它无法预见它将应用于其他已经应用了 Kotlin 插件的构建脚本(这实际上很脆弱)。

    这意味着两件事:

    • 在编译时,您无法在不依赖插件的情况下从插件访问类型和函数(很可能在buildSrc/build.gradle.kts 中声明)
    • 在运行时,您不能假设存在仅在应用某些插件(此处为 Kotlin 插件)时才可用的任务和扩展 - 您需要确保它已被应用。

    要解决这个问题,您可以在 foo.bar.kts 本身中应用 Kotlin 插件,或者用 withPlugin()plugins.withId() 之类的东西对其做出反应:

    plugins {
        kotlin("jvm")
    }
    
    repositories {
        mavenCentral()
    }
    
    tasks.test {
        useJUnitPlatform()
    }
    
    tasks.withType<KotlinCompile>() {
        kotlinOptions.jvmTarget = "11"
    }
    

    为此,您可能需要依赖 buildSrc/build.gradle.kts 中的 Kotlin 插件:

    dependencies {
        implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.21")
    }
    

    有时您不想在应用您的插件时强行应用 Kotlin 插件(因为消费项目可能需要 Kotlin JVM 或 Kotlin Multiplatform,但不是两者都需要)。 对你来说可能不是这种情况,因为当使用像这样的约定插件时,你通常希望对插件有自己的看法,但它在定义一个既适用于 JVM 又适用于多平台的约定时仍然有用。因此,为了完整起见,让我详细说明一下这个案例。

    如果您需要这种惰性和/或条件配置,您可以注册配置,该配置仅在使用plugins.withId(...) 应用给定插件时应用。不需要 afterEvaluate 之类的。例如:

    plugins.withId("org.jetbrains.kotlin.jvm") {
        tasks.named<Test>("test") {
            useJUnitPlatform()
        }
        tasks.withType<KotlinCompile>() {
            kotlinOptions.jvmTarget = "11"
        }
    }
    
    plugins.withId("org.jetbrains.kotlin.multiplatform") {
        tasks.withType<Test>().configureEach {
            useJUnitPlatform()
        }
        tasks.withType<KotlinCompileCommon>() {
            // ..
        }
    }
    

    请注意,如果您需要使用插件中的类,您仍然需要 buildSrc/build.gradle.kts 来声明对插件的依赖。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-06
      • 2019-07-10
      • 1970-01-01
      • 2019-08-09
      • 2018-07-11
      • 1970-01-01
      • 2022-06-20
      • 2021-12-06
      相关资源
      最近更新 更多