Gradle Goodness: Creation Rules For Rule Based Model Configuration Using Model DSL
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>
:
// 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.
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 $. 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 | Creator: Project..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/sample/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.