Martin
06/23/2025, 2:57 PMproject.gradle.lifecycle.beforeProject {}
is there a way to do the usual trick of aggregating all projects into the root project? I can add a plugin to every project. But how do I collect the list of all projects to add as dependencies to the root project?Anze Sodja
06/23/2025, 3:13 PMJendrik Johannes
06/23/2025, 3:56 PMisolated.subProjects
or isolated.subProjectPaths
or/and isolated.rootProject.subProjects
. The information provided should be the project names/paths as these are fixed after the initialization phase.
The article uses the traditional subprojects { }
block, which I assume is still allowed as long as you do not call any methods on the subproject object (this
in the example in the article).
But it does not feel like this is a good solution on the long run (?)Martin
06/23/2025, 4:11 PMoverride fun apply(target: Settings) {
target.gradle.lifecycle.beforeProject { project ->
if (project.rootProject == project) {
project.pluginManager.apply("com.gradleup.nmcp.aggregation")
project.subprojects {
project.dependencies.add(nmcpConsumerConfigurationName, project.dependencies.create(it))
}
} else {
project.pluginManager.apply("com.gradleup.nmcp")
}
}
}
Martin
06/23/2025, 4:11 PMsubprojects { it.path }
is PI-isolation compatibleAlex Semin
06/24/2025, 7:29 AMsubprojects
and such, as long as you only touch immutable project state of other projects.
Establishing dependencies between projects also does not require anything except project identity, so it’s safe too.Alex Semin
06/24/2025, 7:30 AMAlex Semin
06/24/2025, 7:33 AMThe article uses the traditionalAs explained above, you can still call some methods on the other project instance. But I agree that there is no easy way to tell what is allowed and what will be treated as a violation. On the one hand, theblock, which I assume is still allowed as long as you do not call any methods on the subproject object (subprojects { }
in the example in the article).this
subprojects
calls are ubiquitous in the wild, so we want to support them as much as we can. But maybe introducing a new “definitely-safe” API for the same thing is still warranted, if only to avoid mental exercises of figuring out what is allowed and what is not.Martin
06/24/2025, 7:46 AMsubprojects {}
aggregations and potentially missing a more flexible cross project API. I managed to do what I want with the subprojects {}
block above but this comes with a big caveat that my aggregation now needs to use lenient(true)
. This is making me quite uncomfortable. I've been hit a couple of times already with resolution errors (bad artifact being resolved, undetected misconfiguration, etc...).Martin
06/24/2025, 7:48 AMAlex Semin
06/24/2025, 7:50 AMThis is making me quite uncomfortable. I’ve been hit a couple of times already with resolution errors (bad artifact being resolved, undetected misconfiguration, etc...)Can you describe your use case from the user experience you expect? For instance, does it mean, you’d like a mechanism that fails fast, instead of silently skipping “non-producing” projects?
Martin
06/24/2025, 7:51 AMMartin
06/24/2025, 7:52 AMMartin
06/24/2025, 7:55 AMApplication
or AppDelegate
. Just like my UI is a graph of views that can interact with each others, I'd expect my build system to be a graph of tasks and projects that can interact with each other.Martin
06/24/2025, 7:56 AMVampire
06/24/2025, 10:50 AMlenient
?
It ignores any error that could arise.
Without lenient
, the artifact view should still only give you those that have the variant but not fail on non-producing projects, at least it you set any attributes. (https://github.com/gradle/gradle/issues/27773 / https://github.com/gradle/gradle/issues/30314)Alex Semin
06/24/2025, 11:26 AMIn my case, what I’d like is that the subproject plugin can add its own project to a known-in-advance root project (doesn’t have to be the root project but root is probably the simplest mental model). I don’t think this is currently possible?If by “add” you mean adding a dependency, then it’s not possible. Isolated Projects come with a promise of safe configure-on-demand and incrementality. If a subproject was allowed to contribute anything to a mutable container of a parent (e.g. a dependency on itself into the root project), then the build result could be different depending on whether that subproject was scheduled for configuration or not (e.g. when running a qualified task like
:myRootTask
).
In other words, unless the root project (or any project with the aggregating logic) does not explicitly request something from the subprojects, those might not be configured at all.Martin
06/24/2025, 11:59 AMWithoutTIL, thanks @Vampire! This is good to know but also reinforces my impression that these APIs are more complicated than need be., the artifact view should still only give you those that have the variant but not fail on non-producing projects, at least it you set any attributes.lenient
Martin
06/24/2025, 12:16 PMunless the root project does not explicitly request something from the subprojects, those might not be configured at all.Ah, Yes! I remember this discussion now, Thanks! But then isn't what I'm doing with
subprojects {}
and adding all the projects to the root dependencies essentially just killing any configure-on-demand benefits?Vampire
06/25/2025, 10:35 AMMartin
06/25/2025, 10:46 AMMartin
06/25/2025, 12:12 PMAlex Semin
06/25/2025, 2:09 PMBut then isn’t what I’m doing withPossibly, but this would be only for this case, when you do expect to aggregate things across all projects. It doesn’t mean that other builds that don’t do a similar thing shouldn’t benefit from configure-on-demand. Moreover, even in that case you should still be able to run a task only in a subproject (aka you don’t need the aggregation for that invocation), and not pay the price of configuring all sibling subprojects.and adding all the projects to the root dependencies essentially just killing any configure-on-demand benefits?subprojects {}