Use subproject properties in shared task

I want to share a task code between subprojects, however the task requires subprojects to provide a specific property. How do I get this property in shared task?

root/build.gradle

subprojects { sub ->
	task buildZip(type: Zip, dependsOn: assemble) {
		archiveName = "${sub.name}-${sub.foo}"
	}
}

I tried to declare foo property in root/subProj/build.gradle in many different ways. I also tried to access the property as ${sub.ext.foo}. None of it helped and the error is roughly the same:

Could not get unknown property 'foo' for project ':subProj' of type org.gradle.api.Project.

How do I declare and access foo property correctly?

In my understanding, the problem is that root script is executed first in configuration time and it cannot find the properties of not-yet-evaluated sub-projects. If so how do I access the properties lazily?

The root script is evaluated first as the default order is top down. You can reverse this ordering by adding evaluationDependsOnChildren(), but this might have other side effects depending on your build.

Without changing the evaluation order, this would be a case where a configuration task can be used. The only work this task would do is setting the archivePath of the buildZip task.

subprojects { sub ->
    task buildZip(type: Zip, dependsOn: assemble) {
        // ...
    }

    task configureBuildZip {
        buildZip.dependsOn it
        doLast { buildZip.archiveName = "${project.name}-${project.foo}" }
    }
}
1 Like