In a previous post we learned how to create a class that extends RuleSource
with methods that define rules on how to create and change objects in the Gradle model space. With the model
configuration block in a build file we can also define creation rules for Rule based model configuration.
In the following build file we define a model
block and define a creation rule for creating the object versionInfo
of type VersionFile
. Also we add a new task to the tasks
object of type ModelMap<Task>
. To reference another object from the model space inside the Closure
for a creation rule we use the syntax $.<objectName>
:
// File: model.gradle import mrhaki.gradle.VersionFile import mrhaki.gradle.VersionFileTask model { // Creation rule to create object // with name versionInfo (name of the method) // and type VersionFile. versionInfo(VersionFile) { // Set default value for version to project.version. version = project.version // Set default outputFile to // file version.txt in build directory. outputFile = project.file("${buildDir}/version.txt") } // tasks is of type ModelMap<Task>. tasks { // Create task generationVersionFile // with custom task type VersionFileTask. create('generateVersionFile', VersionFileTask) { // Set properties with values // from managed object versionInfo, // that we created with the creation rule // versionInfo(VersionFile). // We use the special $.<name> notation // to reference object from the model space. version = $.versionInfo.version outputFile = $.versionInfo.outputFile } } }
The supporting VersionFile
class is a Gradle managed object:
// File: buildSrc/src/main/groovy/mrhaki/gradle/VersionFile.groovy package mrhaki.gradle import org.gradle.model.Managed @Managed interface VersionFile { String getVersion() void setVersion(final String version) File getOutputFile() void setOutputFile(final File outputFile) }
And the custom task is very straight forward for our example:
// File: buildSrc/src/main/groovy/mrhaki/gradle/VersionFileTask.groovy package mrhaki.gradle import org.gradle.api.DefaultTask import org.gradle.api.tasks.Input import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction /** * Simple task to save the value for the * {@link #version} property in a file. * The file is set with the {@link #outputFile} * property. */ class VersionFileTask extends DefaultTask { /** * Value for version to be saved. */ @Input String version /** * Output file to store version value in. */ @OutputFile File outputFile /** * Actual task actions to save the value * for {@link #version} in {@link #outputFile}. */ @TaskAction void generateVersionFile() { outputFile.parentFile.mkdirs() outputFile.text = version } }
We can use the model rules in our build script when we use apply from: 'model.gradle'
in our build script. In our example we also add a model
configuration block to configure the versionInfo
object:
// File: build.gradle apply from: 'model.gradle' model { // Configuration rule for the versionInfo // object, that is created with the // creation rule from 'model.gradle'. versionInfo { version = '3.0.0.RELEASE' } }
Let's invoke the model
task and check the output to see where are rules are applied:
$ gradle -q model ... tasks | Type: org.gradle.model.ModelMap<org.gradle.api.Task> | Creator: Project.<init>.tasks() | Rules: ⤷ tasks { ... } @ model.gradle line 18, column 5 ... + generateVersionFile | Type: mrhaki.gradle.VersionFileTask | Value: task ':generateVersionFile' | Creator: create(generateVersionFile, mrhaki.gradle.VersionFileTask) { ... } @ model.gradle line 21, column 9 | Rules: ⤷ copyToTaskContainer ... + versionInfo | Type: mrhaki.gradle.VersionFile | Creator: versionInfo(mrhaki.gradle.VersionFile) { ... } @ model.gradle line 8, column 5 | Rules: ⤷ versionInfo { ... } @ build.gradle line 47, column 5 + outputFile | Type: java.io.File | Value: /Users/mrhaki/Projects/mrhaki.com/blog/posts/samples/gradle/versionrule/build/version.txt | Creator: versionInfo(mrhaki.gradle.VersionFile) { ... } @ model.gradle line 8, column 5 + version | Type: java.lang.String | Value: 3.0.0.RELEASE | Creator: versionInfo(mrhaki.gradle.VersionFile) { ... } @ model.gradle line 8, column 5 ... $
Written with Gradle 3.2.