【问题标题】:gradle kotlindsl extract logic to outer scriptsgradle kotlindsl 将逻辑提取到外部脚本
【发布时间】:2021-12-29 13:44:48
【问题描述】:

将 gradle 构建代码块提取到外部脚本的推荐方法是什么? 请注意,这些脚本应该支持对 gradle 项目、extra 等的引用。所以 - 在 buildSrc 中编译 kt 文件不是我想要的。

我尝试创建像logger.gradle.kts 这样的文件,这些文件似乎“知道”项目引用/编译,但是我在其中写入的任何fun 在主构建文件中都不可引用,尽管我这样应用:

apply (from = "logger.gradle.kts")

作为构建的一部分,我得到的错误是:

Unresolved reference: logInfo - 其中logInfofun 中的logger.gradle.kts

这是我正在使用的记录器文件:

import org.apache.tools.ant.taskdefs.condition.Os
import org.gradle.internal.logging.text.StyledTextOutput
import org.gradle.internal.logging.text.StyledTextOutputFactory
import org.gradle.internal.logging.services.DefaultStyledTextOutputFactory
import org.gradle.internal.logging.text.StyledTextOutput.Style



fun <R> callBasedOnContext(
    ifBuildScript: KotlinBuildScript.() -> R,
    ifSettingsScript: KotlinSettingsScript.() -> R
): R {
    /*
     * A bit of a hack to get around a compiler error when trying to do
     * `is KotlinBuildScript` and `is KotlinSettingsScript`.
     */
    val kotlinProjectClass = KotlinBuildScript::class
    val kotlinSettingsClass = KotlinSettingsScript::class

    return when {
        kotlinProjectClass.isInstance(this) -> (this as KotlinBuildScript).ifBuildScript()
        kotlinSettingsClass.isInstance(this) -> (this as KotlinSettingsScript).ifSettingsScript()
        else -> throw AssertionError("$this is not being applied to a supported type.")
    }
}

val extra: ExtraPropertiesExtension by lazy {
    callBasedOnContext(
        ifBuildScript = { extra },
        ifSettingsScript = { (settings as ExtensionAware).extra }
    )
}

fun hasPropertyHelper(propertyName: String): Boolean {
    return callBasedOnContext(
        ifBuildScript = { hasProperty(propertyName) },
        ifSettingsScript = { (settings as ExtensionAware).extra.properties.containsKey(propertyName) }
    )
}

fun propertyHelper(propertyName: String): Any? {
    return callBasedOnContext(
        ifBuildScript = { property(propertyName) },
        ifSettingsScript = { (settings as ExtensionAware).extra.properties[propertyName] }
    )
}

extra["logDebug"] = this::logDebug
extra["logInfo"] = this::logInfo
extra["logWarn"] = this::logWarn
extra["logError"] = this::logError
extra["logTitle"] = this::logTitle
extra["logStyles"] = this::logStyles

val loggerOut = DefaultStyledTextOutputFactory(null, null).create("styled_output")
val loggerOutError = loggerOut.withStyle(Style.Failure)
val loggerOutWarn = loggerOut.withStyle(Style.Description)
val loggerOutInfo = loggerOut.withStyle(Style.Success)
val loggerOutDebug = loggerOut.withStyle(Style.Normal)
val loggerOutTitle = loggerOut.withStyle(Style.Header)

fun log(message: String, out: StyledTextOutput) {
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        project.logger.quiet(message)
    } else {
        out.println(message)
    }
}

fun logTitle(message: String) {
    log("\n---------------------------------------------", loggerOutTitle)
    log("  ${message.toUpperCase()}", loggerOutTitle)
    log("---------------------------------------------", loggerOutTitle)
}

fun logDebug(message: String) {
    log("[DEBUG] " + message, loggerOutDebug)
}

fun logInfo(message: String) {
    log("[INFO] " + message, loggerOutInfo)
}

fun logWarn(message: String) {
    log("[WARN] " + message, loggerOutWarn)
}

fun logError(message: String) {
    log("[ERROR] " + message, loggerOutError)
}

fun logStyles() {
    val out = DefaultStyledTextOutputFactory(null, null).create("styled_test")

    log("Style: Normal", out.withStyle(Style.Normal))
    log("Style: Header", out.withStyle(Style.Header))
    log("Style: UserInput", out.withStyle(Style.UserInput))
    log("Style: Identifier", out.withStyle(Style.Identifier))
    log("Style: Description", out.withStyle(Style.Description))
    log("Style: ProgressStatus", out.withStyle(Style.ProgressStatus))
    log("Style: Success", out.withStyle(Style.Success))
    log("Style: SuccessHeader", out.withStyle(Style.SuccessHeader))
    log("Style: Failure", out.withStyle(Style.Failure))
    log("Style: FailureHeader", out.withStyle(Style.FailureHeader))
    log("Style: Info", out.withStyle(Style.Info))
    log("Style: Error", out.withStyle(Style.Error))
}

以及 build.gradle.kts 中的用法:

 plugins {
    base
    idea
    `java-library`
    scala
    apply(from = "gradle_scripts/logger.gradle.kts")
}

并像这样调用:

logInfo("Application Version: ${version}")

方法失败:

Unresolved reference: logInfo

注意:如果我将函数添加到 extra(这是我在 hos 某处看到的用于公开脚本文件之间的方法的建议):

extra["logDebug"] = this::logDebug
extra["logInfo"] = this::logInfo
extra["logWarn"] = this::logWarn
extra["logError"] = this::logError
extra["logTitle"] = this::logTitle
extra["logStyles"] = this::logStyles

然后失败:

Logger_gradle@a1f3cf9 is not being applied to a supported type.

【问题讨论】:

  • 请发布一个不工作的示例 Gradle 脚本以及它是如何使用的。
  • @FranciscoMateo 编辑帖子并提供更多信息
  • 关注了这个回复,它似乎有效:stackoverflow.com/a/52139585/200937

标签: gradle gradle-kotlin-dsl kotlin-dsl


【解决方案1】:

如果我没记错的话,Gradle Kotlin DSL 不支持这个操作。

如果您尝试将“冗余”public 修饰符添加到 logInfo(...)

public fun logInfo(s: String) {
    println(s)
}

你会得到一个编译错误:

修饰符“public”不适用于“local function”

推荐的方法是利用扩展功能,例如:

val Project.isSnapshotBuild
    get() = (version as String).contains("snapshot", true)

查看完整示例here

【讨论】:

  • 谢谢,您确定扩展功能也适用于根项目吗?我没有在这里使用模块。我想从根项目中提取构建逻辑。
  • fun Project.logInfo(message: String) { log("[INFO] " + message, loggerOutInfo) } 仍然导致:未解决的参考:logInfo
  • @YaOg 你需要把扩展函数放到*.kt,而不是.gradle.kts。我已经从我的本地项目中仔细检查过,它适用于模块/根build.gradle.kts
  • 我也试过了。由于某种原因 buildSrc 任务跳过了 compileKotlin。我只看到编译 java 和 groovy。但是,我最初的问题是使用 kts 文件——即不需要预编译。不支持吗?它在 gradle groovy 中运行良好(使用 apply from ...)。
  • @YaOg 是的,Gradle Kotlin DSL 编写的独立脚本插件有很多限制,据我测试,它不支持扩展函数技巧。预编译脚本插件在*.gradle.kts世界中更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-26
  • 2022-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
相关资源
最近更新 更多