Hans Dockter wrote:
On May 23, 2009, at 11:32 PM, Adam Murdoch wrote:
Hi,
I'd like to come up with a plan for removing the settings.gradle file.
(apologies for the essay - I think this stuff needs to be considered
as a whole)
There's 5 things we use settings.gradle for, which we will need
replacements for:
1. Defining the project heirarchy. That is, which projects are
included in thie build?
2. Defining the project descriptor for each project in the build.
That is, what is the project name, build file, project dir and build
dir for each project?
3. Defining the build script classpath(s). That is, which classes are
available at compilation time and execution time for each build script.
And right now there is the additional constraint, that there is only
one build script classpath for all of the build scripts of a
multi-project build.
4. Defining the classpath(s) for custom plugins to be used in the
build script. Currently we use the build script classpath for the
custom plugin classpath, but I think they really are separate use cases.
5. Locating the root project of the build when running from the
command-line.
Plus, the solution should allow us to later add better ways of
composing the build and plugin classpaths, such as by using project
dependencies.
I have some suggestions, but they're really just a starting point for
discussion.
* Defining the heirarchy
It would be useful, I think, for any project to be able to define its
own subprojects. This allows for better build encapsulation, and
would allow small builds to be more easily composed into multiple
larger builds. Perhaps something like this in the build file:
projects {
subProject {
buildFile = 'sub-project.gradle'
}
anotherSubProjectUsingDefaults
aSubProjectConfiguredUsingAMap(projectDir: 'sub', buildFile:
'sub.gradle')
}
This could be nested to allow a project tree to be specified:
projects {
subProject {
anotherProject { ... }
}
}
I think a builder syntax is a natural way to express and configure a
project hierarchy.
I think having aggregate multi-project builds are very important. I
see two types of multiproject builds. One is a strongly coupled one,
where the subprojects depend on the configuration of the parent
project and where artifact project dependencies are used. This is well
supported in Gradle at the moment. The other type of multi-project
build is much more loosely coupled. The subprojects don't know of each
other and can be build independently. Artifacts dependencies are
realized as external dependencies. An aggregate multi-project build
will often contain both types of multi-project builds. Those aggregate
builds are an important requirement on our way to become a good build
integration tool.
Right now we have the behavior that only the root and the leafs of the
project hierarchy need to be specified. The nodes in between are
automatically created. I don't think this makes a lot of sense. I just
want to mention it.
I think we should do away with the processing stage which figures out
which projects are included in the build, and simply allow them to be
added at any point during the evaluation stage. That is, projects are
just regular domain objects, not anything special. I think this
consistency important. In addition, this would mean you can use
plugins or classes in buildSrc to define or influence the project
hierarchy without us doing anything special to support it. The same
would be true of any future capability we add to let you compose the
build logic. To me, this approach seems more flexible and more likely
to handle use-cases we haven't anticipated, than would special-casing
assembly of the project hierarchy.
I'm trying to understand the lifecycle we would have then. Let's say
we have a non aggregate multi-project build. All subprojects are
declared in the root project. During the evaluation phase of the root
project we hit the projects closure. After a declaration of each
subproject, we would create an empty project instance for this
subproject. After the projects closure is evaluated the root project
can configure the sub projects. After the root project is evaluated,
the subprojects are evaluated (let's say by default in alphabetical
order). The evaluation order can be customized by calling the
subproject.evaluate() method or by creating a dependsOn relation (for
example because subproject1 needs an evaluated subproject2).
Pretty much. To add a little more detail:
for projects { subproject { ... } }
when subproject { ... } is executed:
1. create a project descriptor
2. execute the closure to configure the project descriptor
3. execute the project { } closure from the subproject's build file, if
present, to configure the project descriptor
4. use the project descriptor to create an empty project and add to
parent project
5. fire a project added notification
6. repeat this process for any projects nested in the configure closure.
Step 3 is possibly not needed. Also, we could skip a project descriptor
and create a project in step 1 instead.
Adam
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email