Depending on a task in project dependencies?

Suppase that I have a series of projects: projD depends on projC, projC depends on projB, etc, and suppose that every project has a “foo” task.

How do I set it up so that running “foo” on a project will also execute it on all of the projects it depends on?

Until now, I’ve been using the following ugly piece of code:

afterEvaluate {
  configurations.compile.copy {it.group == 'com.my.group'}.dependencies.each { dep ->
    tasks.foo.dependsOn(":${dep.name}:foo")
    tasks.bar.dependsOn(":${dep.name}:bar")
    tasks.baz.dependsOn(":${dep.name}:baz")
  }
}

However, with configuration on demand, the afterEvaluate executes too soon, and no dependencies are created.

I know I could use a beforeTask {} block, but that’s even uglier. I’m sure there’s a “proper” Gradleish way to do this - what is it?

Can you explain what bigger problem you are trying to solve, ideally with a concrete example?

Every project has uploadArchives as well as copyPackages. uploadArchives is the normal one; copyPackages does something similar, but organizes the files for our deploy scripts to pick up.

I want to make sure that if :someProject:uploadArchives is run, that uploadArchives is run for every one of its dependent projects as well. Likewise, if :someProject:copyPackages is run, then copyPackages should run for every project that someProject depends on.

Suppose I have the following projects, with their dependencies:

Base: no dependencies Log: depends on Base Lib: Depends on Log and Base App1: Depends on Lib, Log, and Base App2: Depends on Lib, Log, and Base

If I tell Gradle to execute :App1:copyPackages, i want to see Gradle run: :Base:copyPackages :Log:copyPackages :Lib:copyPackages :App1:copyPackages

Well, I found the problem. Ever since I made this project, I’d been using the following:

configurations.compile.copy {it.group == ‘com.my.group’}.dependencies.each { dep -> … }

For some reason, the group is now “master,” so nothing in the configuration matched. This is what i’d need now:

configurations.compile.copy {it.group == ‘master’}.dependencies.each { dep -> … }

That being said, I’ve changed the filter to what it probably should have been all along:

configurations.compile.copy {it instanceof DefaultProjectDependency}.dependencies.each { dep -> … }

Still, I’d like to know if there’s a better way to do this.

If you want to align task dependencies with project dependencies, Configuration.getTaskDependencyFromProjectDependency is the way to go. This is, for example, used by the Java plugin to wire up the ‘buildNeeded’ and ‘buildDependent’ tasks.

Wow, I never would have found that.

For anyone else finding this thread, the solution was:

tasks.uploadArchives.dependsOn(configurations.compile.getTaskDependencyFromProjectDependency(true, 'uploadArchives'))

Also, I found out why my group was showing up as “master.” When I switched to configuration-on-demand, I just replaced my subprojects { … } section with gradle.beforeProject { project -> configure(project) { … } }. Since the code to set each subproject’s group was contained in that block, it didn’t get set unless the project was needed. By moving those lines back into a subprojects {} block, my groups are back to what they should be.

It’s not used very often, but can be handy at times.