Dynamically created task of type Copy is always UP-TO-DATE
build.gradle, gradle
Solution
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.
Problem
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.