Gradle build failure - output dependencies

Hello all, I have a grade build failure with the reason being:

Reason: Task ':app:mergeDebugJniLibFolders' uses this output of task ':app:unzip' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.

I am offered the following solutions:

      1. Declare task ':app:unzip' as an input of ':app:mergeDebugJniLibFolders'.
      2. Declare an explicit dependency on ':app:unzip' from ':app:mergeDebugJniLibFolders' using Task#dependsOn.
      3. Declare an explicit dependency on ':app:unzip' from ':app:mergeDebugJniLibFolders' using Task#mustRunAfter.

I’m unable to find where to make any of the above declarations as the task mergeDebugJniLibFolders doesn’t exist within the project.

Should I be trying to locate them to make that change in the build.gradle file or is there a better way to resolve this?

I’m building using Android Studio with everything updated as of today if that makes any difference.

Thanks in advance.

Actually, the advices are imho non-sense in most cases.
They just do symptom treatment instead of properly fixing the problem, just hiding it better in most cases.

You do have the tasks in your project or you wouldn’t get that message.
You don’t necessarily add them yourself, it could also be that some plugin adds those tasks.
Nevertheless you could configure them if you would want to.

But in most cases this error is a symptom of not properly wiring task outputs to task inputs, but instead configuring paths, or of tasks with overlapping outputs.
So your unzip task has an output declared that is used in an input of mergeDebugJniLibFolders.
What the exact concrete problem is, is impossible to say for me without seeing the build.

Thank you. Its good to hear that they are configurable but my problem is that I am unable to locate them within my project directory. Can you point me to where the mergeDebugJniLibFolders and unzip tasks would likely be kept?

I’m on Ubuntu and tried the .gradle folder but no joy.

Alternatively is it possible to configure them from within my project build.gradle? When I try to do so it complains that they can’t be found.

They are tasks, you will not find them on disk like in .gradle or similar.
If it says it cannot find them in the build script, maybe you are in the wrong build script (e.g. root project instead of app project), or they are added later where you could still configure them using tasks.matching { ... }.configureEach { ... }.
But as I said, without seeing the build I can hardly give any concrete advice.

Ah! I believe I have found them now :slight_smile:

There was this line apply from: "./download_vvl.gradle" which when I followed defines the unzip task.

// unzip the downloaded VVL zip archive to the ${VVL_JNILIB_DIR} for APK packaging.
task unzip(dependsOn: download, type: Copy) {
    from zipTree(file("${VVL_LIB_ROOT}/android-binaries-${VVL_VER}.zip"))
    into file("${VVL_JNILIB_DIR}")
android.sourceSets.main.jniLibs {
        srcDirs += ["${VVL_JNILIB_DIR}/android-binaries-${VVL_VER}"]

I’ll have a play with this and see how I get on. Many thanks!

Yes, that should be the reason and exactly what I said.
You configure the path manually without having the task dependency.

Android is always a little special, so I’m not sure it will work,
but in a normal project you would just do something like

android.sourceSets.main.jniLibs {

instead and by that get the necessary task dependency automatically.

How true! For completeness and anyone else having the same issue it is solved with:


Be aware that this is a very bad idea.

As I said, by adding explicit dependencies you only do symptom treatment instead of a proper fix that can fall apart again easily.

Additionally, the main effect of afterEvaluate is to add ordering problems, timing problems, and race conditions. It is highly disouraged to use it unless you really have to, which you do not in this case if you would have followed my advise.

And by using tasks.getByName you additionally completely break task-configuration avoidance making each and every build slower than it has to be. At least use the “matching=>configureEach” I said so that you at least do not break task-configuration avoidance and also do not need afterEvaluate anymore.