Q: Can one task be dependent on another task with specific argument? If the answer is yes then how to accomplish that?
I opened Gradle for myself recently, and just got curious about next:
Let's say I'd like to have one of the build's subfolders to be copied each time I execute the copy task.
task copy (type: Copy) {
dependsOn build
from '[fromName]'
into '[intoName]'
}
In my case, I'd like to copy folder build/reports/profile, but the thing is that this folder is created by execution of the build --profile task.
So, is there any chance to accomplish the following:
task copy (...) {
dependsOn build --profile
from ...
into ...
}
Btw, plugin project-report doesn't create this folder, to be dependent on its task.
Note: It's not as important to have it done, I'm just interested if it is possible at all.
You can't pass arguments with dependsOn to a task directly but you can create a custom Exec task and pass arguments via the command line interpreter (cmd) using the gradle wrapper like this:
task buildWithArgument(type: Exec) {
commandLine 'cmd', '/c', 'gradlew.bat build --profile'
}
task copy (type: Copy) {
dependsOn buildWithArgument
from '[fromName]'
into '[intoName]'
}
Related
I have a project utilities with a build.gradle. utilities has some modules named util, util2, util3, ...
In a task I want to execute first :util2:build and :util5:build. But I do not know how to write such a task. This fails:
task executePreBuild() {
:util2:build
:util5:build
}
In commandline
gradlew clean :util2:build :util5:build
can be executed. But this is not my purporse.
I want to execute
gradlew clean executePreBuild someOtherTask build
This can be done by using dependsOn:
task executePreBuild {
dependsOn ":util2:build"
dependsOn ":util5:build"
}
Does anybody know what the simplest way to register several run tasks that represent exact copy of original one with changed app’s arguments ? Or may be how to supply run task with an optional argument that would represent app’s arguments.
Basically, I want my build to contain some pre-defined options how to run an application and don’t want to declare new JavaExec that requires its manual configuring while I have already had ready-to-go run task supplied by default.
gradle run --args='--mode=middle' ---> gradle run || gradle runDefault || gradle run default
gradle run --args='--mode=greed' ---> gradle runGreed || gradle run greed
gradle run --args='--mode=lavish' ---> gradle runLavish || gradle run lavish
As for now I came up only with the option that suggests implementing my own JavaExec_Custom task class with supplied arguments property. And it seems to be too complex and boilerplating as for my goal.
You can create tasks that modify the configuration of the actual run task in a doFirst or doLast closure:
// Groovy-DSL
task runGreed {
doFirst {
run.args '--mode=greed'
}
finalizedBy run
}
// Kotlin-DSL
register("runGreed") {
doFirst {
run.get().args = listOf("--mode=greed")
}
finalizedBy(run)
}
You can use a property for the args
task run(type: JavaExec) {
args property('run.args').split(' ')
...
}
Usage
gradle run -Prun.args='foo bar baz'
I am new to gradle, I want copy the jar file generated by gradlew build to another dir.
task myCopyTask(type: Copy) {
from "build/libs/gs.jar"
into "D:/bin/gs"
}
I add above task to the build.gradle which belong to gs module which will generate gs.jar.
The problem is the command gradlew build will not do the copy and this task indeed executed(I add println in myCopyTask). However, the command gradlew myCopyTask works.
First I thought maybe the copy task running too early, so I change it to
task myCopyTask(type: Copy) {
doLast {
from "build/libs/gs.jar"
into "D:/bin/gs"
}
}
This is not working even by gradlew myCopyTask. Only first version can work by command gradlew myCopyTask, the terminal will show: 1 actionable task: 1 executed
What is the problem?
You haven't wired the task into Gradle's DAG so currently it will only executed when you do gradlew myCopyTask
You'll probably do something like
apply plugin: 'base' // adds build and assemble lifecycle tasks
task myJarTask(type:Jar) {...}
task myCopyTask(type: Copy) {
dependsOn myJarTask
...
}
assemble.dependsOn myCopyTask
See https://docs.gradle.org/current/userguide/tutorial_using_tasks.html#sec:task_dependencies
I have a library, which contains 3 lib modules and 1 example module. Before deploy task I want to execute some other tasks. In command line it looks like this: ./gradlew -x:example:clean -x:example:check -x:example:uploadArchives clean check :androidLib:assembleRelease uploadArchives.
I want to write gradle task to execute all tasks sequentially for all modules besides example module. That I can do: ./gradlew deployAll. How can i do it?
I try do this:
task deployAll {
doLast {
subprojects {
if(it.plugins.withType(com.android.build.gradle.AppPlugin)) return
it.tasks.getByName('clean').execute()
it.tasks.getByName('check').execute()
...
}
}
}
But execute() is deprecated and it execute only first task and ignore any.
You can use dependsOn inside of your gradle tasks to make sure your tasks run in the correct order
task task1{
dependsOn task2
//Task one code
}
task2{
dependsOn task3
//task 3 code
}
task3{
//task3 code
}
so in this example if you call task1, first task 3 will be executed, then task2 and then finally task one, but you need only call task1.
You can make another task and set other tasks its dependencies
task deployAll {
dependsOn tasks.getByName('clean')
dependsOn(tasks.getByName('check'))
}
To ensure the order add put this somewhere
tasks.getByName('check').mustRunAfter(tasks.getByName('clean'))
I've prepared a very simple script, that illustrates the problem I see using Gradle 1.7 (need to stick with it because of some plugins not yet supporting newer versions).
I'm trying to dynamically create tasks each of which corresponds to a file in the project directory. This works fine, but the tasks I create never get executed as soon as I assign them type 'Copy'.
Here is my problem build.gradle:
file('templates').listFiles().each { File f ->
// THIS LINE DOES NOT WORK
task "myDist-${f.name}" (type: Copy) {
// NEXT LINE WORKS
//task "myDist-${f.name}" {
doLast {
println "MYDIST-" + f.name
}
}
}
task distAll(dependsOn: tasks.matching { Task task -> task.name.startsWith("myDist")}) {
println "MYDISTALL"
}
defaultTasks 'distAll'
in this way my tasks do not get executed when I call default task calling simply gradle:
MYDISTALL
:myDist-template1 UP-TO-DATE
:myDist-template2 UP-TO-DATE
:distAll UP-TO-DATE
BUILD SUCCESSFUL
If I remove type Copy from my dynamic task (uncommenting the line above), my tasks get executed:
MYDISTALL
:myDist-template1
MYDIST-template1
:myDist-template2
MYDIST-template2
:distAll
BUILD SUCCESSFUL
(You'll need to create a folder name templates in the same directory where build.gradle is located and put couple of empty files into there in order to run the test)
According to the debug output:
Skipping task ':myDist-template1' as it has no source files.
Skipping task ':myDist-template2' as it has no source files.
So how can I specify source files and make my Copy tasks execute?
I've tried adding
from( '/absolute/path/to/existing/file' ) {
into 'myfolder'
}
to the task body, I've tried assigning task's inputs.source file('/my/existing/file') with no success.
Could you please advise on how to modify my simple script leaving dynamic task creation and keeping my dynamic tasks of type Copy?
Thank you!
Edit:
All right, this way the task gets called:
file('templates').listFiles().each { File f ->
task "myDist-${f.name}" (type: Copy) {
from f
into 'dist'
doLast {
println "MYDIST-" + f.name
}
}
}
but it looks I must always specify from/into. It doesn't suffice to do that in the doLast{} body.
A Copy task only gets executed if it has something to copy. Telling it what to copy is part of configuring the task, and therefore needs to be done in the configuration phase, rather than the execution phase. These are very important concepts to understand, and you can read up on them in the Gradle User Guide or on the Gradle Forums.
doFirst and doLast blocks get executed in the execution phase, as part of executing the task. Both are too late to tell the task what to copy: doFirst gets executed immediately before the main task action (which in this case is the copying), but (shortly) after the skipped and up-to-date checks (which are based on the task's configuration). doLast gets executed after the main task action, and is therefore clearly too late.
I think the following Gradle User Guide quote answers my question the best:
Secondly, the copy() method can not honor task dependencies when a task is used as a copy source (i.e. as an argument to from()) because it's a method and not a task. As such, if you are using the copy() method as part of a task action, you must explicitly declare all inputs and outputs in order to get the correct behavior.
Having read most of the answers to "UP-TO-DATE" Copy tasks in gradle, it appears that the missing part is 'include' keyword:
task copy3rdPartyLibs(type: Copy) {
from 'src/main/jni/libs/'
into 'src/main/libs/armeabi/'
include '**/*.so'
}
Putting from and into as part of the doLast section does not work. An example of a working task definitions is:
task copyMyFile(type: Copy) {
def dockerFile = 'src/main/docker/Dockerfile'
def copyTo = 'build/docker'
from dockerFile
into copyTo
doLast {
println "Copied Docker file [$dockerFile] to [$copyTo]"
}
}
Not the behavior I was expecting.
Using gradle 3.2.1