understand the dependsOn and the tasks. This is my build.gradle.kts code:
tasks.register<Copy>("extractJar") {
dependsOn(tasks.assemble)
val zipFile = file("${buildDir}/libs/backend-${version}.jar") // TODO: pending to fix
val outputDir = file("${buildDir}/extracted/")
from(zipTree(zipFile))
into(outputDir)
}
tasks.register<Delete>("deleteClasses") {
delete("${buildDir}/extracted/BOOT-INF/classes/")
}
tasks.register<Copy>("copyObfuscatedClasses") {
from(zipTree("${buildDir}/obfuscatedClasses.jar"))
into("${buildDir}/extracted/BOOT-INF/classes/")
}
tasks.register<Delete>("deleteObfuscated") {
delete("${buildDir}/obfuscatedClasses.jar")
}
tasks.register<Zip>("repackage") {
dependsOn(tasks.named<Delete>("deleteClasses"))
dependsOn(tasks.named<Copy>("copyObfuscatedClasses"))
dependsOn(tasks.named<Delete>("deleteObfuscated"))
from("${buildDir}/extracted")
entryCompression = ZipEntryCompression.STORED
archiveFileName.set("backend-${archiveVersion.get()}-obfuscated.jar")
destinationDirectory.set(file("${buildDir}/libs"))
}
tasks.register<ProGuardTask>("proguard") {
dependsOn(tasks.named<Copy>("extractJar"))
verbose()
injars("${buildDir}/extracted/BOOT-INF/classes")
outjars("${buildDir}/obfuscatedClasses.jar")
libraryjars(mapOf("jarfilter" to "!**.jar", "filter" to "!module-info.class"), configurations.compileClasspath.get())
libraryjars(mapOf("jarfilter" to "!**.jar", "filter" to "!module-info.class"), "${System.getProperty("java.home")}/jmods/java.base.jmod")
libraryjars(mapOf("jarfilter" to "!**.jar", "filter" to "!module-info.class"), "${System.getProperty("java.home")}/jmods/java.logging.jmod")
//allowaccessmodification()
//repackageclasses("")
keepdirectories()
configuration("proguard-rules.pro")
printmapping("build/proguard-mapping.txt")
dependsOn(tasks.named<Zip>("repackage"))
}
And this is the error:
A problem was found with the configuration of task ':repackage' (type 'Zip').
- Gradle detected a problem with the following location: '/root/backendv2/build/extracted'.
Reason: Task ':repackage' uses this output of task ':extractJar' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
Possible solutions:
1. Declare task ':extractJar' as an input of ':repackage'.
2. Declare an explicit dependency on ':extractJar' from ':repackage' using Task#dependsOn.
3. Declare an explicit dependency on ':extractJar' from ':repackage' using Task#mustRunAfter.
For more information, please refer to https://docs.gradle.org/8.5/userguide/validation_problems.html#implicit_dependency in the Gradle documentation.
It complain that the repackage task uses the output of task extractJar. But what is the problem? I dont understand... The tasks with dependsOn are executed sequentially?
the problem is that the result may vary depending on whether extractJar was executed or not
Welcome to gradle clusterfuck
How can I order the execution of the tasks?
read the possible solutions and implement one of them, i would go with depends on
You need to learn more about the "task tree" concept, which is the basis for all build systems I know. Basically, the idea is that instead of defining the order of tasks to be executed, you define what other tasks the task you're declaring "depends on". Which is a synonym to "should be executed after". For example "createPackage" depends-on "compileJava" and "processResourceFiles" (properties, yamls, and other static files). Which is very natural to express - to create package you need to have compiled java classes to put into package, and have processed static files to put in the same jar/zip file too. Such way of defining "task-A depends on task-B, task-C, task-D..." is waaay more practical than trying to order them absolutely. And build system then builds the task dependency tree to figure out which tasks to run first, and which after. In gradle you can add this plugin to help you to learn standard built-in tasks dependencies and your custom ones too. Highly recommend. https://github.com/dorongold/gradle-task-tree Then specifically gradle goes further in this "task-A depends-on task-B" relationships. It also has a concept of "task inputs" and "task outputs". It works similar to make (I assume that you didn't work with make). Basically, when you declare a task, you also specify what this task produces, and what this task consumes. This helps gradle to avoid unnecessary work. If gradle can see that task inputs haven't changed since last run, then gradle assumes that there's no sense to run the task again. For example, for "compileJava" task inputs are all file-tree in "src/main/java". If no files changed there since last compilation, there's no any sense to repeat compilation. And gradle will mark this task "UP-TO-DATE" and will avoid doing the work. Hence, for your specific case, you have a task extractJar with *output* declared as: val outputDir = file("${buildDir}/extracted/") into(outputDir) Yes, it's not obvious, but task of type Zip has "from" and "into" options, which also register arguments as task inputs and task outputs automatically. So your extractJar task this way declared task output in ile("${buildDir}/extracted/") directory. And gradle detects that another task repackage declares same directory as its "input": tasks.register<Zip>("repackage") { from("${buildDir}/extracted") But without saying that "task repackage depends-on task extractJar", which is obviously a mistake. In short, just add dependsOn(tasks.named<Copy>("extractJar")) to your repackage task declaration and it should work.
Обсуждают сегодня