'gradle kotlindsl extract logic to outer scripts
What is the recommended way to extract gradle build code blocks to external scripts? Notice these scripts should support references to the gradle project, extra etc. So - compiling kt files in buildSrc isn't what I'm looking for.
I've tried to create files like logger.gradle.kts
and these seem to "know" the project ref / compile, but any fun
I write in them is not referenceable in the main build file although I apply like this:
`apply (from = "logger.gradle.kts")`
The error I get as part of the build is:
Unresolved reference: logInfo
- where logInfo
is a fun
in logger.gradle.kts
.
This is the logger file I am using:
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))
}
And usages in build.gradle.kts:
plugins {
base
idea
`java-library`
scala
apply(from = "gradle_scripts/logger.gradle.kts")
}
And invoking like this:
logInfo("Application Version: ${version}")
the method fails on:
Unresolved reference: logInfo
Note: If I add the functions to extra
(which is recommendation I saw somewhere on hos to expose methods between scripts files):
extra["logDebug"] = this::logDebug
extra["logInfo"] = this::logInfo
extra["logWarn"] = this::logWarn
extra["logError"] = this::logError
extra["logTitle"] = this::logTitle
extra["logStyles"] = this::logStyles
It then fails on:
Logger_gradle@a1f3cf9 is not being applied to a supported type.
Solution 1:[1]
Gradle Kotlin DSL does not support this operation if I'm not wrong.
If you try to add a "redundant" public
modifier to logInfo(...)
:
public fun logInfo(s: String) {
println(s)
}
You will get a compilation error:
Modifier 'public' is not applicable to 'local function'
The recommended way is leveraging Extension Functions?, for example:
val Project.isSnapshotBuild
get() = (version as String).contains("snapshot", true)
check a complete sample here.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | 2BAB |