gradlebuild.gradle

Gradle wait for all dependencies' tasks complete


My project structure looks like this

sales-distribution-recording
---backend
------build
------build.gradle
------gradle.properties
---ui
------build
------build.gradle
------gradle.properties
gradle.properties
...other files

the subproject ui needs all tasks (clean, compile, build, etc, but most especially build since it will populate build folder under backend with artifacts needed by ui tasks) in backend to complete. Content of build.gradle under ui:

dependencies{
    compile org.springframework:spring-webapp

    //other jars
    compile project(":backend")
}

mytask{
    artifactFolder("../backend/build")
}

//other tasks

but still when I run ./gradlew clean build --info, I can see the sequence of tasks being run:

Tasks to be executed: [task 'ui:clean', task 'backend:clean', task 'ui:mytask', task 'backend:compile', task 'backend:build']

I assumed with compile project(":backend:") would mean all tasks in backend would run first before continuing with tasks in ui, but apparently not. With current sequence, mytask would run and get empty ../backend/build folder since backend:build is not run until much later. how do I solve this?

Thanks


Solution

  • What Gradle is doing

    When you have the line:

    dependencies{
        compile project(":backend")
    }
    

    You are telling Gradle to add the artifact output by the backend project that matches the attributes of the compile configuration to that configuration. Assuming your compile configuration is created by the Java plugin, Gradle will build the Java library (ie the JAR) output by backend. Gradle knows this is the correct artifact because it is contained within a "consumable" configuration in the backend project with attributes that match the compile configuration.

    The "right" way to deal with other artifacts

    The right way of providing additional artifacts from the backend project is to mimic this pattern, with an additional consumable configuration in the backend project that contains the relevant output artifacts, and an additional "resolvable" configuration in your ui project which has matching attributes. Then you can write something like:

    dependencies{
        myNewResolvableConfiguration project(":backend")
    }
    

    And somewhere else in the build you can access the files in myResolvableConfiguration, which is an object in the ConfigurationContainer that extends FileCollection.

    The Gradle documentation has more on this approach.

    The quick way

    The quick way to deal with your issue is to make a direct task dependency between the task(s) that need the artifacts from backend and the tasks that produce those artifacts. This, however, is brittle and not recommended:

    myDependentTask.dependsOn ":backend:build"