* 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


Reply via email to