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.
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 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.
There are some down-sides, but I think we can come up with simple
solutions to those (or already have, in the Task model).
* Project Descriptor
It makes sense that a build script should be able to define the name of
the project, something like:
project {
name = 'myProject'
// maybe some other properties as well
}
Given that the name is fundamental to the identity of the project, this
closure would have to be executed as soon as the project is included in
the build (regardless of how that might happen). We would need to do
some magic to extract just this closure. I think it should be possible.
It's a closure so that 1) we can find it easily, 2) you can use
statements to configure the descriptor, and 3) so we can add more
properties or methods to the descriptor later.
Some issues:
- There is the potential for 2 different names to be specified for the
project: one in the ancestor project, and one in the project itself. Not
sure how to resolve this.
- Which properties should be available for configuring in the
descriptor? For example, do we let you specify the project or build
dirs? Let you apply plugins? Define tasks/configurations/repositories?
Set arbitrary project properties? Are you simply configuring a Project
object, where the name property is mutable while the closure executes?
- Which properties can only be specified in the descriptor? Certainly
the name is one. If we let you specify the project or build dirs, should
we make them immutable after the descriptor has been configured?
- What about the ancestor parent which includes the project? What can it
configure?
* Build Script Classpath
Again, it makes sense that each project can specify its own classpath.
Perhaps, something like:
buildclasspath {
repositories { .... }
dependencies {
build name: 'somelib', version: '..'
build group: '..' ...
}
}
That is, a mini project which allows you specify repositories and
dependencies (but maybe not configurations). Like the project
descriptor, this closure would be executed as a special step before
compiling the build script proper.
Some issues:
- Do we configure the project descriptor before the build classpath? Or
the other way around? That is, can you use the project name in the
buildclasspath { } closure, or can you use the classpath in the project
{ } closure?
- Do we continue with a single classloader for all projects? I'd be
tempted to create a classloader per project.
* Custom plugins
Some possibilities:
- Continue to use the build script classpath for locating plugins.
- Use a separate configuration for plugins in the buildclasspath { }
closure.
- Allow dependencies for a plugin to be declared closer to where the
plugin is applied, something like:
usePlugin(SomeClass) {
dependencies group: 'myOrg', name: 'myBuildInfrastructureProject',
version: '1.0+'
}
By teasing apart the build script and plugin classpaths, particularly if
we end up with a classpath per plugin, we are taking a big step towards
Gradle modularisation. In addition, if we add file dependencies and
project dependencies to the mix, we end up with a really flexible
solution for composing build logic - in particular sharing this stuff
across the organisation.
* Finding the root project.
When settings.gradle disappears, we lose the marker file which helps us
find the root project.
A simple replacement is to scan up the directory hierarchy and treat the
highest *.gradle file we find as the root project's build file. We would
replace the --settings-file command-line option with a --root-project
command-line option in those cases where this doesn't work.
Alternatively, we could allow the project descriptor to point to the
parent project. Or combine these two options.
Adam
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email