Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gradle configure task based on subproject property

I'm trying to configure a Zip task based on one of the property inside sub-projects, but the property is not yet accessible at the time of configuring the task. For instance, I want to exclude all my projects that has toexclude = true from my zip file. So, the build.gradle of the sub-projects that I want to exclude starts with this:

ext.toexclude = true;
...

And my main build.gradle has this task:

task zipContent (type: Zip){
    def excludedProjects = allprojects.findAll{Project p -> p.toexclude == true}.collect{it.name}
    println excludedProjects
    destinationDir = "/some/path"
    baseName = "myFile.zip"
    exclude excludedProjects
    from "/some/other/path"
}

The problem is that excludedProjects is always empty. Indeed, when I am executing the task, I can see []. I believe this is due to the fact that the property that I set in the subproject's build.gradle is not available at the moment the task is configured. As a proof, if I replace the first line of the task by this:

def excludedProjects = allprojects.collect{it.name}

The task prints out all of my project's name, and the zip contains nothing (which means the problem is in the p.toexclude == true).

Also, if I try this:

task zipContent (type: Zip){

    def excludedProjects = []
    doFirst{
        excludedProjects = allprojects.findAll{Project p -> p.toexclude == true}.collect{it.name}
        println "IN DOFIRST"
        println excludedProjects
    }

    println "IN TASK CONFIG"
    println excludedProjects
    destinationDir = "/some/path"
    baseName = "myFile.zip"
    exclude excludedProjects
    from "/some/other/path"
}

The task prints out IN TASK CONFIG followed by an empty array, then IN DOFIRST with the array containing only the subprojects that I set ext.toexclude == true.

So, is there a way to get the properties of the sub-projects at configuration time?

like image 256
GammaOmega Avatar asked Sep 15 '25 21:09

GammaOmega


1 Answers

Well, the crucial question is: At which point of the build is all necessary information available?

Since we want to know each project in the build, where the extra property toexclude is set to true and it is possible (and by design) that the property is set via the build script, we need each build script to be evaluated.

Now, we have two options:

  1. By default, subprojects are evaluated after the parent (root) project. To ensure the evaluation of each project, we need to wait for the point of the build, where all projects are evaluated. Gradle provides a listener for that point:

    gradle.addListener(new BuildAdapter() {
        @Override
        void projectsEvaluated(Gradle gradle) {
            tasks.getByPath('zipContent').with {
                exclude allprojects.findAll { it.toexclude }.collect{ it.name }
            }
        }
    })
    
  2. Gradle provides the method evaluationDependsOnChildren(), to turn the evaluation order around. It may be possible to use your original approach by calling this method before querying the excluded projects. Since this method only applies on child projects, you may try to call evaluationDependsOn(String) for each project in the build to also apply for 'sibling' projects. Since this solution breaks Gradle default behavior, it may have undesired side effects.

like image 124
Lukas Körfer Avatar answered Sep 17 '25 17:09

Lukas Körfer