* 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 should be possible with Groovy 1.6 in any case.
A minor point. For single project builds this looks a bit unintuitive.
Anyway, compared to 0.6 where you would need your settings.gradle file
to change the name, this is still a big improvement.
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.
My first thought is that this is legal and that ancestor should win.
The use case I have in mind is a loosely coupled multi-project build.
The subprojects are not aware that they take part in such a build.
They might set their names, possibly even using equal ones.
- 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?
As said in the other email. We might remove the ProjectDescriptor.
That would expose the whole API (also for the ancestor). This might
raise some issues. For example what to do with
projects {
subproject {
println name // name is not defined in the subproject
either
}
}
* 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.
That would be excellent.
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?
I would say we should configure first the project closure. Then the
buildclasspath can make use of the information. Project stuff that
needs the buildclasspath can always be added later. Unless you need
the buildclasspath to figure out the project name. But this latter,
rather uncommon, problem could always be solved with a multi-project I
think.
- Do we continue with a single classloader for all projects? I'd be
tempted to create a classloader per project.
We need one per project I'd say. Otherwise we will bump into issues.
It would be easy to come up with use cases.
* 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.
I think plugins should be able to contribute two things. One is
manipulating the project object. The other is providing a library to
the project. Let's look at the Java plugin. You might want to apply
the Java plugin but you also want to use the Jar class in a custom
way. What would we gain by a separate configuration? What I think is
important are the transitive dependencies. It would be cool if every
buildclasspath dependency would not expose its transitive dependencies
to the build script. As far as I understand, the Spring Bundlor
project for example, can create OSGi manifest files from ivy.xml and
pom.xml. Of course this would require the big leap to OSGi.
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.
The use case I see for the latter is a strongly coupled multi-project
build where the first rule doesn't work for some reason. I think this
would be nice to have as it would avoid different behavior for
identical command line statements across machines.
- Hans
--
Hans Dockter
Gradle Project Manager
http://www.gradle.org
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email