I am trying to do something like this:
jar {
doLast{
from "build/libs/TheJar.jar"
into "."
}
}
So far, I have tried various tutorials including all forms from this answer but non have worked. The only thing that works is calling a separate task but I'd like to know why my construction is wrong and why can't I run something after the jar or shadowJar tasks.
It looks like you took some parts of the answers in the linked post and somehow mixed them without knowing what your final code actually does.
Tasks in Gradle may have a type (e.g. Copy
, Jar
, ...). This type defines what the task will do once it gets executed (so called task actions). A task without a type won't do anything when its executed, unless you add task actions manually. Using doFirst
will add the passed action (also called closure) to the start of the list of task actions, using doLast
will add it to the end of the list.
Everything outside of doFirst
and doLast
closures is not part of the execution of the task, but can be used to configure the task:
task example {
doLast {
println "second action"
}
doFirst {
println "first action"
}
println "configuration"
}
Run the code above with gradle example
and you will see the order of the log messages as configuration
, first action
, second action
.
Task configuration will run, even if the task won't be executed later on. Even if you call gradle
(without any task names as arguments), the console will still print configuration
. This was the actual problem in the linked question.
Lets come to the real question: How to copy a file?
Well, Gradle offers two ways to copy a file. The first one is the task type Copy
. You can create a task based on this type, apply your configuration and then either call it directly from the command line or define task dependencies using dependsOn
or finalizedBy
:
task copySomeFiles(type: Copy) {
from '...'
into '...'
}
However, you don't want to create an additional task. Gradle also has a method called copy
that may be called anywhere in your script and will instantly copy the files:
copy {
from '...'
into '...'
}
The code above will copy your files, but it will copy your files every time Gradle executes (which may be often, e.g. when using an IDE). To solve this problem, you may move your code with copy
to a task action, e.g. inside a doFirst
or doLast
closure:
jar {
doLast {
copy {
from "build/libs/TheJar.jar"
into "."
}
}
}
As you can see, your code was missing the copy
statement. Now, whenever your task jar
gets executed, its last task action will copy the files as intended.
Bonus question: Why is there no error?
The "problem" in your case is that your code is perfectly valid Gradle code. The task jar
is of type Jar
. Every task of type Jar
may be configured using methods called from
and into
. The method from
adds files to the JAR file and the method into
sets the destination directory inside the JAR. So instead of copying, your code configures the underlying task jar
. However, this has no negative consequences, as this configuration gets applied inside doLast
, which only runs once the JAR file has already been created. Something that already happened cannot be configured.