Trying to get tasks from a peer subproject

I have a weird problem with a gradle build that I’m trying to understand.

I have a series of sub-projects in a larger project and I am trying to reference the task output of one of the sub-project in another peer project.

I have a project ‘C’ with uses the palantir docker plugin and Im trying to reference the distTar task output as the files input for project ‘Z’ using:

docker {
    ...
    files project(":Z").distTar
}

This reports the error:

Could not get unknown property ‘distTar’ for project ‘:Z’

The thing I really don’t understand is that I can reference a custom task ‘foo’ from a different project, but not the duplicate custom task in Z

Example:

docker {
    ...
    files project(":B").foo
    files project(":Z").foo
}

The reference to project B works without complaint, but the reference to project A gets the error

Could not get unknown property ‘foo’ for project ‘:Z’

I cannot work out why the A.foo task can be found, but the B.foo task cannot be found. I assume it’s something stupid that I’m doing, but I can’t work out what the difference in relationship between projects A,B and Z are.

I would appreciate any help or hints as to where I should look to fix this.

After trying a few things I found that I can reference project Z by adding evaluationDependsOn(“:Z”)

Is this something to do with the order of evaluation of projects? Is it an alpha sorting issue, or the order in settings.gradle perhaps?

I have a solution, but I’d like to understand why I need an evaluationDependsOn(“:Z”) but did not need evaluationDependsOn(“:A”)

Correct.

You should assume that the evaluation order is undefined/non-deterministic, unless you use evaluationDependsOn to say otherwise.

However, you should not be reaching across project boundaries like this and instead sharing artifacts between projects via configurations and dependencies. Here’s something to get you going (untested):

// Z/build.gradle
configurations {
    applicationTarElements {
        canBeResolved = false
    }
}
artifacts {
    applicationTarElements tasks.distTar
}

// C/build.gradle
configurations {
    applicationTar {
        canBeConsumed = false
    }
}
dependencies {
    applicationTar project(path: ':Z', configuration: 'applicationTarElements')
    // if you have more projects, add them as additional dependencies
    // applicationTar project(path: ':another', configuration: 'applicationTarElements')
}
docker {
    files configurations.applicationTar
}

This can be made fancier with variant-aware dependency resolution using attributes, but I’ll leave that as a bonus exercise for you :slight_smile:

2 Likes

Thanks a lot for the solution here. I agree that reaching across projects blindly doesn’t feel like a very good solution. I’ll take some time to go through your resolution and see if I can make it work in my specific case (which varies from my simplistic example).