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


Reply via email to