Search code examples
gradlebuild.gradlemulti-project

Gradle: Common Zip task for every subproject


I have a multi-project gradle build, where all subprojects of root project have common zip task. They should zip some source, depending of the subproject's settings.

First, I configured it in parent build.gradle:

subprojects { subproject ->
    apply plugin: 'java'
    ...

    task submission(type: Zip) { 
        destinationDir = subproject.buildDir
        archiveName = subproject.name

        from subproject.ext.submissionFiles
    }
}

But this does not work with Cannot get property 'submissionFiles' on extra properties extension as it does not exist. So i moved the task in each subproject's build.gradle, which breaks DRY principle.

I think the problem is that the configuration phase takes place before subprojects are configured. How can I "defer" configuration of this task, so that I only configure ext.submissionFiles in subprojects?


Solution

  • I think you're saying that submissionFiles is set in the subproject's build.gradle?

    There are a few ways of doing it.

    Option 1. You could defer the evaluation of subproject.ext.submissionFiles by wrapping it in a closure:

    task submission(type: Zip) { 
        destinationDir = subproject.buildDir
        archiveName = subproject.name
    
        from ({ subproject.ext.submissionFiles })
    }
    

    Option 2. I think it could be better if you didn't use the intermediate variable (submissionFiles) and directly configured the submission task in the children:

    // In root
    task submission(type: Zip) { 
        destinationDir = subproject.buildDir
        archiveName = subproject.name
    }
    
    // In child
    submission {
        from("path/to/files")
    }
    

    Using an intermediate variable like that to move configuration around can make your builds harder to understand connections between tasks.


    Option 3. In some cases, it makes sense to use evaluationDependsOnChildren(), but I would generally not recommend it.