karfai
karfai

Reputation: 906

How to implement this 'dynamic block' in Gradle?

I am new to gradle. So let straight to the point. I want to implement the block as below. Note that the libraries is dynamic, and available for other developers to add on for the needed libraries.

libraries {
    slf4j 'org.slf4j:slf4j-api:1.7.21'
    junit 'junit:junit:4.12'
}

So that I can call them out like this.

dependencies {
    compile libraries.slf4j
    testCompile libraries.junit
}

I am not sure how to make it. But I found some related solution from here. As shown below:

apply plugin: GreetingPlugin

greeting {
    message 'Hi'
    greeter 'Gradle'
}

class GreetingPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.extensions.create("greeting", GreetingPluginExtension)
        project.task('hello') {
            doLast {
                println "${project.greeting.message} from ${project.greeting.greeter}"
            }
        }
    }
}

class GreetingPluginExtension {
    String message
    String greeter
}

The problem is as I add on to the greeting block, I need to declare them in GreetingPluginExtension as well. Any idea how to make it such that only update on greeting block?

Upvotes: 1

Views: 110

Answers (1)

Opal
Opal

Reputation: 84854

What you need to do is to utilize groovy meta programming. Below you can find just a sample, however fully functional.

apply plugin: LibrariesPlugin

libraries {
    slf4j 'org.slf4j:slf4j-api:1.7.21'
    junit 'junit:junit:4.12'
}

class LibrariesPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.extensions.create("libraries", LibrariesPluginExtension)
        project.task('printLib') {
            doLast {
                println "$project.libraries.slf4j"
                println "$project.libraries.junit"

                project.libraries.each {
                    println "$it.key -> $it.value"
                }
            }
        }
    }
}

class LibrariesPluginExtension {

    Map libraries = [:]

    def methodMissing(String name, args) {
        // TODO you need to do some arg checking here
        libraries[name] = args[0]
    }

    def propertyMissing(String name) {
        // TODO same here
        libraries[name]
    }

    Iterator iterator() {
        libraries.iterator()
    }
}

Upvotes: 5

Related Questions