Extract common methods from Gradle build script

Gradlebuild.gradle

Gradle Problem Overview


I have a Gradle build script (build.gradle), in which I created some tasks. These tasks consist mostly of method calls. The called methods are also in the build script.

Now, here's the situation:

I am creating a fair amount of build scripts, which contain different tasks, but utilise the same methods from the original script. Thus, I would like to extract these "common methods" in some way, so I can easily re-use them instead of copying them for each new script I create.

If Gradle were PHP, something like the following would be ideal:

//script content
...
require("common-methods.gradle");
...
//more script content

But of course, that isn't possible. Or is it?

Anyway, how can I achieve this result? What is the best possible method to do this? I've read through the Gradle documentation already, but I can't seem to determine which method will be the easiest and best suited for this.

Thanks in advance!


UPDATE:

I've managed to extract the methods in another file

(using apply from: 'common-methods.gradle'),

so the structure is as follows:

parent/
      /build.gradle              // The original build script
      /common-methods.gradle     // The extracted methods
      /gradle.properties         // Properties used by the build script

After executing a task from build.gradle, I've bumped into a new problem: apparently, methods don't get recognized when they're in common-methods.gradle.

Any ideas on how to fix that?

Gradle Solutions


Solution 1 - Gradle

Building on Peter's answer, this is how I export my methods:

Content of helpers/common-methods.gradle:

// Define methods as usual
def commonMethod1(param) {
    return true
}
def commonMethod2(param) {
    return true
}

// Export methods by turning them into closures
ext {
    commonMethod1 = this.&commonMethod1
    otherNameForMethod2 = this.&commonMethod2
}

And this is how I use those methods in another script:

// Use double-quotes, otherwise $ won't work
apply from: "$rootDir/helpers/common-methods.gradle"

// You can also use URLs
//apply from: "https://bitbucket.org/mb/build_scripts/raw/master/common-methods.gradle"

task myBuildTask {
    def myVar = commonMethod1("parameter1")
    otherNameForMethod2(myVar)
}

Here's more on converting methods to closures in Groovy.

Solution 2 - Gradle

It isn't possible to share methods, but you can share extra properties containing a closure, which boils down to the same thing. For example, declare ext.foo = { ... } in common-methods.gradle, use apply from: to apply the script, and then call the closure with foo().

Solution 3 - Gradle

Using the Kotlin DSL it works like this:

build.gradle.kts:

apply {
  from("external.gradle.kts")
}

val foo = extra["foo"] as () -> Unit
foo()

external.gradle.kts:

extra["foo"] = fun() {
  println("Hello world!")
}

Solution 4 - Gradle

Another approach for Kotlin DSL could be:

my-plugin.gradle.kts

extra["sum"] = { x: Int, y: Int -> x + y }

settings.gradle.kts

@Suppress("unchecked_cast", "nothing_to_inline")
inline fun <T> uncheckedCast(target: Any?): T = target as T
    
apply("my-plugin.gradle.kts")
    
val sum = uncheckedCast<(Int, Int) -> Int>(extra["sum"])
    
println(sum(1, 2))

Solution 5 - Gradle

I would suggest a slight adjustment to Matthias Braun's answer, in that instead of writing the same method-name twice and still have it clear and consise, why not simply do the following:

ext.commonMethod1 = (param) -> {
    return true
} as Closure<boolean>

The usage of the as-operator simply tells one explicitly, that this function will return a value of boolean-type.

Because after all, this still is Groovy goodness. Neat huh?

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPieter VDEView Question on Stackoverflow
Solution 1 - GradleMatthias BraunView Answer on Stackoverflow
Solution 2 - GradlePeter NiederwieserView Answer on Stackoverflow
Solution 3 - GradleSimon LView Answer on Stackoverflow
Solution 4 - GradleGarouDanView Answer on Stackoverflow
Solution 5 - GradleChilly_VanillyView Answer on Stackoverflow