TheBoegl / gradle-launch4j

A gradle-plugin to create windows executables with launch4j

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Launch4j wrapper is rebuilt every time jar changes even with dontWrapJar enabled

maikelsteneker opened this issue · comments

I'm using the following combination of properties for my launch4j task:

dontWrapJar = true
jarTask = executable.get()

The task executable is a custom task that produces a jar file.

Note that the dontWrapJar option implies that if the JAR changes, there's no need for the launch4j wrapper to change. However, when running gradle executable createExe, the createExe (launch4j) task rebuilds every time the jar has changed:

Task ':createExe' is not up-to-date because:
  Input property '$1' file project/build/test.jar has changed.

Is there a way to change this behaviour?

dontWrapJar option implies that if the JAR changes, there's no need for the launch4j wrapper to change

Actually, if the path to JAR file changes (this includes filename change), exe needs to be changed as well. But, even if we would track the change of JAR output path and content separately, it won't help to avoid task rebuild, because exe creation is not the only thing createExe task does. If dontWrapJar=true it also by default copies JAR (and all other runtimeClasspath dependencies) into libraryDir (so, changes to the JAR content would require its recopying).

Default copying behavior may be disabled by setting the copyConfigurable property, but it doesn't make sense if dontWrapJar=true (unless you also specify libraryDir pointing to the original JAR parent folder).

So, this optimization is applicable only for the very specific configuration, and the trickiest part here is to determine whether JAR output is still present in copyConfigurable (in that case dependency on JAR content should be preserved), which could hold various types of input files representations (completely disabling input dependency on JAR contents for dontWrapJar=true and any non-default copyConfigurable would be a breaking change).

This probably could be implemented by extracting copying operations from createExe into a separate task and depending on it.
This way dependency on input from jarTask may be declared as:

def jar = jarTask.outputs.files.singleFile
if (getDontWrapJar() && !copyingTask.outputs.files.contains(jar)) {
    inputs.property("jarPath", jar.toPath())
} else {
    inputs.files(jar)
}

As @naftalmm put it very well. I don't think such special cases are worth the hassle.