Rustam A.
Rustam A.

Reputation: 879

Basic Gradle copy-task not working (until directly called)

I have a simple Gradle script:

task copyall(){
    println 'starting...'
    task copyA(type: Copy) {
        mkdir 'web'
        from 'src'
        into 'web'
    }
}

It behaves strangely: if I call "gradle copyall" from command line - it creates directory but doesn't copy files from 'src' to 'web' folders. If I call directly task.copyA ("gradle copyA") from command line - it does both makes dir and copying files (with subfolders).

Why task.copyA is only partially executed as subtask of task.copyall?

Upvotes: 1

Views: 8338

Answers (1)

Lukas Körfer
Lukas Körfer

Reputation: 14493

Well, I understand why your Gradle script behaves the way you describe, but it behaves this way for various reasons.

First of all, there is no such thing as a subtask in Gradle. You can create tasks and you can define dependencies between tasks, that's it. So your task copyA is exactly the same thing if you just define it on its own (the recommended way):

task copyAll {
    println 'starting...'
}

task copyA(type: Copy) {
    mkdir 'web'
    from 'src'
    into 'web'
}

Now you have two tasks, but the task copyAll does nothing at all. Even your println statement is not, what the task does, but how it is configured:

Gradle has two major phases when executing build scripts: configuration phase and execution phase. The whole build script will be evaluated (executed) during configuration phase and only the task actions (e.g. copying for a Copy task), doFirst and doLast closures of selected tasks will be executed during execution phase. The selected tasks are determined from the command line parameters and task dependencies.

As a conclusion, the 'starting ...' output is printed when task copyAll is configured, not when it is started!

Last but not least, the mkdir command is causing confusion, because it is not part of the Copy task, but a method of the Project instance. It executed directly when called, so in your case directly during the configuration phase, completely independent from any task execution. It will be executed every time you execute Gradle.

But, to hear some good news, you simply don't need it. A Copy task will create all required target directories on its own.

Now, to summarize all points from above, we come up with the following build script:

task copyAll {
    dependsOn 'copyA'
}

task copyA(type: Copy) {
    from 'src'
    into 'web'
}

Upvotes: 5

Related Questions