Authors of plugins and anyone else who might understand the nuances of their application to multi-project builds perhaps you can help.
The Problem, Briefly
A root project applies a plugin to its subprojects. This works when I invoke gradle from the root project. This breaks when I invoke gradle from a subproject directory, complaining that it does not understand the DSL.
Do I really need to go into the build.gradle for each subproject and add evaluationDependsOn ':parent'
to get :parent
to be evaluated before its children regardless of where gradle is invoked from?
Edit further experimentation shows this problem is specific to the presence of the --configure-on-demand
flag. For performance reasons removing this flag is really not an option for me.
##Some Context
- Gradle 3.3
- Multi-project build with ~270 projects, most of them Java
- Size of build necessitates always using
--configure-on-demand
together with--parallel
- Aside from parent project configuring child projects, there is no other cross-project-configuration (projects are decoupled)
##The Problem, not so briefly
I’m attempting to create a plugin which aggregates build and dependency artifacts from sub-projects. Because reasons currently outside of my control there is a many-to-many mapping from project artifacts to where those artifacts need to be copied to
Simplified structure of the buildstructure:
: (root project)
:parent
:child1
:child2
:parent
's build.gradle defines a plugin which creates a DSL on the subprojects of :parent
:
class ExampleExtension {
String foo
}
class ExamplePlugin implements Plugin<Project> {
void apply(Project project) {
project.subprojects { subproject ->
subproject.extensions.create('example', ExampleExtension)
subproject.afterEvaluate {
println subproject.example.foo
}
}
}
}
apply plugin: ExamplePlugin
Allowing the build.gradle in :parent:child1
and :parent:child2
to have a DSL like so:
example {
foo = 'bar'
}
So now if I’m :parent
's directory and I invoke gradle everything works just like I expect it to! I see 'bar'
printed once during configuration time for each of :parent
's subprojects.
But if I cd into the directory of :parent:child1
or :parent:child2
configuration of those projects will fail with a message indicating that ExampleExtension
has not yet been applied, demonstrating that I don’t understand project evaluation order as well as I thought I did:
* What went wrong:
A problem occurred evaluating project ':parent:child1'.
> Could not find method example() for arguments [build_7z4mibcpx3v4soamzppwy1fnu$_run_closure2@6281add3] on project ':parent:child1' of type org.gradle.api.Project.
Again, if I go into each child project and add an evaluationDependsOn ':parent'
it works.
But I thought that parent projects were already evaluated before their children? There are examples of parent projects configuring their child projects throughout the documentation. What am I missing about project evaluation order/plugin application?