How to find `type` of Gradle task? - gradle

I have the following code which works fine:
allprojects {
tasks.whenTaskAdded { task ->
if (task.name =~ /generate.*Proto/) { // ①
task.dependsOn(protolockStatus)
task.finalizedBy(protolockCommit)
}
}
}
Rather than assuming some task naming convention on the line commented with ①, I'd like to make the condition based on the type of the task. I had thought type instanceof would work, but it did not. I also don't see any methods that would provide the type of the task. Is there a way to do this?

You could use the class of the task for that. So for example, you could try this:
allprojects {
tasks.whenTaskAdded { task ->
println "Type is " + task.class.simpleName
}
}

Related

Executing registered task in kotlin build file

I need to convert a gradle build script, which is written in Groovy, into Kotlin. The problem is, that in the Groovy build file in one task another task, which was defined before, is executed. However, it appears that in Kotlin there is no support for that, at least I could not find any in the API.
I have studied the API and searched for similar problems, but I could not find anything useful.
The Groovy code looks like this:
task doSomething () {
...
}
task anotherTask () {
...
doSomething.execute()
...
}
How would this call be translated into Kotlin?
doSomething.execute()
You should never call execute() on a task. Instead set the inputs, outputs and dependencies correctly, and Gradle will call the task for you if it needs to.
something like:
tasks {
val doSomething by registering {
doLast {
println("running doSomething")
}
}
val anotherTask by registering {
dependsOn(doSomething)
doLast {
println("Running anotherTask")
}
}
}
Then:
$ gradle anotherTask
> Task :doSomething
running doSomething
> Task :anotherTask
Running anotherTask
BUILD SUCCESSFUL in 746ms
Kotlin is statically typed. So you must know the type of the task of doSomething and anotherTask if Kotlin not able to infer it for you. execute leads me to believe it some sort of execute task. So for your example:
val doSomething = tasks.register("doSomething", JavaExec::class.java) {
main = "com.example.Example"
}
val anotherTask = tasks.register("anotherTask") {
doSomething.get().exec()
}
However, it looks you just want to execute doSomething before anotherTask, so you'd want:
val doSomething = tasks.register("doSomething", JavaExec::class.java) {
main = "com.example.Example"
}
val anotherTask = tasks.register("anotherTask") {
dependsOn(doSomething)
}
Without knowing the types of your task it's difficult to give you the right answer.

Refactor duplicated code in gradle task "type: Copy"

A gradle project contains several similar task type:Copy and some of them require additional checks.
task copyPackage1(type: Copy) {
from buildPackage1
into "/pkgs/"
eachFile {
if (it.relativePath.getFile(destinationDir).exists()) {
throw new GradleException("Probably version was no updated. File exists: " + it)
}
}
}
...
task copyPackage2(type: Copy) {
from buildPackage2
into "/pkgs/"
eachFile {
if (it.relativePath.getFile(destinationDir).exists()) {
throw new GradleException("Probably version was no updated. File exists: " + it)
}
}
}
How it is possible to refactor duplicated checks and specify same target directory for all similar tasks (but not all Copy tasks)?
You could either implement this with a custom Gradle plugin (as suggested in this similar question on Gradle forum), or use simple Groovy method to create and configure your tasks, as follows:
// define a "task creator" method
ext.createCopyToPkgTask = { String taskName , String fromDir ->
return project.tasks.create(taskName, Copy.class){
from fromDir
into "/pkgs"
eachFile {
if (it.relativePath.getFile(destinationDir).exists()) {
throw new GradleException("Probably version was no updated. File exists: " + it)
}
}
}
}
/* declare your similar tasks using the creator method above */
createCopyToPkgTask("copyPackage1","buildPackage1")
createCopyToPkgTask("copyPackage2","buildPackage2")
// ...

refer to Gradle task which is defined later in build

Our build has some generic logic to create tasks from configuration data. There are also several Gradle files on whose execution order I do not want to depend.
Now I need to add a task dependency to a task without knowing if that task will be defined before my part of the build script runs (at configuration time) or after my part.
[Edit: as #canillas writes I can say myTask.dependsOn "otherTask" and "lazily" depend on yet undefined "otherTask", but I need it the other way around.]
Since I can't write tasks["otherTask"].dependsOn myNewTask before "otherTask" is defined, I made the following helper function:
void safelyDoWithTask(String taskName, Closure func) {
def task = tasks.findByName(taskName)
if (task != null) {
func(task)
} else {
project.tasks.whenTaskAdded { task_ ->
if (taskName.equals(task_.getName())) {
func(task_)
}
}
}
}
safelyDoWithTask('otherTask', { it.dependsOn myNewTask })
Now I wonder if there is more canonical way to achieve this?
Consider the following:
// section 1
def dynamicDependencies = [:]
dynamicDependencies['otherTask'] = 'myNewTask'
// section 2
afterEvaluate { project ->
// taskA dependsOn taskB
dynamicDependencies.each { taskA, taskB ->
def task = project.tasks.findByName(taskA)
if (task) { task.dependsOn "${taskB}" }
}
}
// section 3
task myNewTask() {
doLast {
println 'myNewTask !'
}
}
task otherTask() {
doLast {
println 'otherTask !'
}
}
The gist is:
section 1 defines our dependency info in a custom map
section 2 uses the afterEvaluate hook to process the map
because the above is decoupled from the task definitions, we can simply put them in section 3 (or wherever)

How do I alias gradle task as if it were called with -x parameter?

I want instead of gradle cleanIdea idea -x compileJava -x compileTestJava
call something like gradle ideaNoRecompile
You can use TaskExecutionGraph to do it. First of all, you need to provide a custom task, named ideaNoRecompile, when during the configuration phase, you need to check, whether this graph contains ideaNoRecompile task (that means, that this task will be executed. And if this task should be executed, then you can use a closгre to skip all the tasks, you don't want to be executed. Something like this:
task ideaNoRecompile(dependsOn:idea) {
gradle.taskGraph.whenReady { graph ->
if (graph.hasTask(ideaNoRecompile)) {
compileJava.enabled = false
compileTestJava.enabled = false
}
}
}
I've found another similar answer:
task ideaNoRecompile {
finalizedBy allprojects*.tasks*.idea
doFirst {
def skipTasks = ['compileJava', 'compileMirah', 'processResources', 'classes', 'compileTestJava', 'compileTestMirah', 'processTestResources', 'testClasses', 'jar', 'mergeProperties', 'generateModuleManifest' ] as Set
allprojects*.tasks*.each {
if (skipTasks.contains(it.name))
it.enabled = false
}
}
}

Null dependency in gradle? (workaround for lazy downloads?)

I would like to be able to write something like this:
dependencies {
myConfig computeMyDependency()
}
and I want to be able to say "there is no dependency". Returning null or an empty map doesn't work. I suppose I can return files('/dev/null'), but that is weird, hacky and not portable. Is there some sort of null dependency constructor I can use?
Some background:
What I'm really trying to do is to defer dependency download to actual execution time. It appears that if a write a task, for example a copy task like so:
task copyMyDependencyFile(type: Copy) {
from { configurations.myConfig
.grep { it.name.endsWith("zip") }
.collect() { zipTree it }
}
into targetDir
}
Then running ./gradlew tasks will actually execute the from closure, which makes me very sad. (Using Gradle 2.4)
A quick workaround might be also:
task copyMyDependencyFile << {
copy {
from {
configurations.
compile.
grep { it.name.endsWith("jar") }.
collect { zipTree it }
}
into targetDir
}
}
It should be portable.
Not sure but maybe from and into maybe configured in doLast closure of task with type Copy:
task copyMyDependencyFile(type: Copy) {
doLast {
from {
configurations.
compile.
grep { it.name.endsWith("jar") }.
collect { zipTree it }
}
into targetDir
}
}
Please try the latter yourself.

Resources