简体   繁体   中英

Gradle not running copy task after jar

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 (eg 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, eg when using an IDE). To solve this problem, you may move your code with copy to a task action, eg 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM