|
View:
New views
16 Messages
—
Rating Filter:
Alert me
|
|
|
removing the settings.gradle fileHi,
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 |
|
|
Re: removing the settings.gradle file2009/5/23 Adam Murdoch <a@...> Hi, I like this.
I agree. 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. That would be cool :) 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 would only allow the name to be set once and fail when the second time it is a different value. I think this is very likely to happen a lot. When the module is not yet part of a larger build it will need the name in a local build script. When it is incorporated in the larger build it will be defined in the larger build hierarchy with it's name to make the larger build independent of changes to the lower module build files (like removing the name because it is no longer needed).
I would make them immutable after configuration.
I wouldn't make a distinction between the two location where a project can be configured. Everything can be configured in both locations, but only once (and ignoring multiple configurations of the same thing that are trying to configure it in the same way - like I'm suggested with the possible names issue).
I'd go for the classpath in the project { } closure, I can imagine some custom build logic wanting to add some custom properties to project.
I agree we should have separate classloaders per project.
I'd opt for something like this, allow configurations to be defined in the buildclasspath, and when you say usePlugin(SomeClass, somePluginConfiguration) this does imply that we need separate classloaders for plugins aswell.
If the *.gradle file scan doesn't work it would indeed be nice to be able to specify the parent project in the build file, you wouldn't want to specify it every time you want to execute a gradle command. So allowing them both is indeed a good idea.
|
|
|
Re: removing the settings.gradle fileAdam 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. > > 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). > One of the reasons that we have our own fork of Gradle currently is that we needed to be able to programmatically construct the set of projects used in a build. We would like to to accomplish the same goals with this, but it looks like you may be planning to use AST transformations or another compile time technique to implement your scheme. If so, please provide an API oriented alternative. A common situation may be a single root project with a large number of child projects where all you want to specify in the root is the location of all the children's gradle files. In this case, all of the project configuration may be done in the individual subproject gradle files. A simplified syntax for this case might be: projects { include 'sub/sub.gradle', 'sub2/gradle/sub2.gradle' } > > * 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? > In our Gradle fork, some of the changes we made were to allow us to debug .gradle files in IDEA. We found it necessary to have distinct names for the gradle files in each project, so for the project "reportengine", the gradle file would just be "reportengine.gradle". This is also much nicer to deal with in an IDE's editor where you often just see the file name on a editor's tab, not the full path. It was confusing to see 6 different "build.gradle" files. Is there a problem with just using the base name of the .gradle file as the project name? Is there a reason to ever change this? Other configured properties: Currently we need to store the gradle files in a subdirectory of the project directory to avoid some problems with the location of IDEA's source directories. Please allow both the project and build dirs to be configured. > > * 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? > We would like to be able to use classes from the buildclasspath inside the project closure. It would be nice to be able to share some of this from the root project. It will be verbose to redefine things like the company repo in every build file. Currently we inject the company repo from the root project for the configuration phase so it is only specified in one place. Syntactically it might be nice to nest the "buildclasspath" section inside of the root projects "projects" section, but this may conflict with my goal of using the buildclasspath in the evaluation of this section. > - Do we continue with a single classloader for all projects? I'd be > tempted to create a classloader per project. > A classloader per project helps avoid conflicts as projects age and diverge. Over time older subprojects may have different (and possibly conflicting) buildclasspath needs from a newer subproject. > > * 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. > Having a separate configuration sounds the most flexible even though we don't currently have a need for this. > > * 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. You can scan up the hierarchy by default, but please allow some way to specify the parent in the project descriptor. Currently in our system, the root project is actually a peer in the directory structure. > > > Adam > > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > Thanks for taking the time to think all this through. This is an important step to help gradle scale up to large projects. -- Steve Appling Automated Logic Research Team --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: removing the settings.gradle file[ . . . ] > One of the reasons that we have our own fork of Gradle currently is that we > needed to be able to programmatically construct the set of projects used in a > build. We would like to to accomplish the same goals with this, but it looks > like you may be planning to use AST transformations or another compile time > technique to implement your scheme. If so, please provide an API oriented > alternative. [ . . . ] Having a fork already at this stage in the life of a project is clearly not a good thing. Hopefully there is a way of reconciling this issue so that we can return to having a single mainline. I appreciate this email is not contributing anything technical to the debate I just wanted to point out the need to avoid a fork that is not a friendly, and temporary, one. -- Russel. ============================================================ Dr Russel Winder Partner Concertant LLP t: +44 20 7585 2200, +44 20 7193 9203 41 Buckmaster Road, f: +44 8700 516 084 voip: sip:russel.winder@... London SW11 1EN, UK. m: +44 7770 465 077 xmpp: russel@... |
|
|
Re: removing the settings.gradle fileRussel Winder wrote: > [ . . . ] >> One of the reasons that we have our own fork of Gradle currently is that we >> needed to be able to programmatically construct the set of projects used in a >> build. We would like to to accomplish the same goals with this, but it looks >> like you may be planning to use AST transformations or another compile time >> technique to implement your scheme. If so, please provide an API oriented >> alternative. > [ . . . ] > > Having a fork already at this stage in the life of a project is clearly > not a good thing. Hopefully there is a way of reconciling this issue so > that we can return to having a single mainline. > > I appreciate this email is not contributing anything technical to the > debate I just wanted to point out the need to avoid a fork that is not a > friendly, and temporary, one. > Our fork is intended to be temporary. We have discussed several of our concerns with Hans and I think all of our needs will be met in a future release (hopefully 0.7). We just couldn't get everything addressed in 0.6. The fork is a way for us to apply our own bug fixes in an timely manner and try out ideas for new features we need. -- Steve Appling Automated Logic Research Team --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: removing the settings.gradle fileOn Thu, 2009-05-28 at 07:46 -0400, Steve Appling wrote:
> Our fork is intended to be temporary. We have discussed several of our concerns > with Hans and I think all of our needs will be met in a future release > (hopefully 0.7). We just couldn't get everything addressed in 0.6. The fork is > a way for us to apply our own bug fixes in an timely manner and try out ideas > for new features we need. Sounds exactly like what branches are for :-) The bug fixes perhaps should just be applied to trunk anyway, that would leave this as a feature branch. -- Russel. ============================================================================= Dr Russel Winder Partner xmpp: russel@... Concertant LLP t: +44 20 7585 2200, +44 20 7193 9203 41 Buckmaster Road, f: +44 8700 516 084 voip: sip:russel.winder@... London SW11 1EN, UK m: +44 7770 465 077 skype: russel_winder |
|
|
Re: removing the settings.gradle fileThe funny thing is that with github, you don't need 'committer' access to have your own 'branch'. Steve is hosting his version at http://gist.github.com/sappling/gradle/tree/master, which is actually downstream from yours ;) (in case you didn't notice).
(I came over it while looking from which repo I could fork my own patches). And would just like to congratulate the Gradle team on the how to contribute page. I didn't very often submit patches to OSS projects, usually because the things I have issues with are either tiny or I it's discussed in depth on the mailinglist. The ability to sport my own repository of Gradle in about 10 seconds, and have a patch uploaded a couple of minutes later help me personally a lot to lower the barrier for participation. Cheers, -Daniel On Thu, May 28, 2009 at 9:11 PM, Russel Winder <russel.winder@...> wrote:
|
|
|
Re: removing the settings.gradle fileSteve Appling wrote: > > > Adam Murdoch wrote: >> >> * 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). >> > > One of the reasons that we have our own fork of Gradle currently is > that we needed to be able to programmatically construct the set of > projects used in a build. We would like to to accomplish the same > goals with this, but it looks like you may be planning to use AST > transformations or another compile time technique to implement your > scheme. If so, please provide an API oriented alternative. > The general approach we've taken so far is to sit the DSL on top of a public API, and I'm pretty sure we'll do the same here (though, often the public API doesn't get any real coverage in the user guide). To be more specific: There are 3 events in a project's life that we're interested in here: 1) project declaration, where the project is added to the build, 2) build script compilation, where the class-path is assembled, and 3) project evaluation, where the build script proper is executed. The approach which I'm suggesting is really to simply allow a build script to register an event handler closure for any of these events, just like it can for afterEvaluate { } or taskGraph.whenReady {}. So, project { } is simply an event handler for the project declared event and buildclasspath { } is an event handler for the assemble classpath (or before-compile) event. We're going to need some AST magic to extract whichever of these event handlers need to execute before the script has been compiled. The less of these, the better, I think. There will not be any AST magic within the closures themselves. They will just contain statements executed against a Project (or maybe a ProjectDescriptor/Settings combo thing). What this means, is that you'll be able to drive the API directly, or indirectly using your own DSL classes, in these closures. Also, I imagine this will all sit on top of a ProjectContainer interface, returned by Build.getProjects() and Project.getSubprojects(). This container, like TaskContainer, ConfigurationContainer, etc, will allow you to programatically declare and configure projects. > A common situation may be a single root project with a large number of > child projects where all you want to specify in the root is the > location of all the children's gradle files. In this case, all of the > project configuration may be done in the individual subproject gradle > files. A simplified syntax for this case might be: > > projects { > include 'sub/sub.gradle', 'sub2/gradle/sub2.gradle' > } > I agree we want to optimise for this case. This is how I want to be able to compose my own builds :) >> >> * 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? >> > Names: > In our Gradle fork, some of the changes we made were to allow us to > debug .gradle files in IDEA. We found it necessary to have distinct > names for the gradle files in each project, so for the project > "reportengine", the gradle file would just be "reportengine.gradle". > This is also much nicer to deal with in an IDE's editor where you > often just see the file name on a editor's tab, not the full path. It > was confusing to see 6 different "build.gradle" files. Is there a > problem with just using the base name of the .gradle file as the > project name? I don't think so. I want to use the build file name as the default project name. > Is there a reason to ever change this? > Not sure. There will be :) Until we find out what that reason is, perhaps we don't need a way for a build file to specify the project name, other than by naming the build file appropriately. Which removes (for now) the need to the build file to register a 'project declared' event handler. > Other configured properties: > Currently we need to store the gradle files in a subdirectory of the > project directory to avoid some problems with the location of IDEA's > source directories. Please allow both the project and build dirs to > be configured. > Definitely. The question is where and how should it be configured? >> >> * 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? >> > > We would like to be able to use classes from the buildclasspath inside > the project closure. It would be nice to be able to share some of > this from the root project. It will be verbose to redefine things > like the company repo in every build file. Currently we inject the > company repo from the root project for the configuration phase so it > is only specified in one place. Syntactically it might be nice to > nest the "buildclasspath" section inside of the root projects > "projects" section, but this may conflict with my goal of using the > buildclasspath in the evaluation of this section. > If "projects" closure evaluation is not a special event in the life of a project, ie it is part of the regular build script evaluation, then everything in the build class-path will be available to the "projects" closure. Also, you'll be able to inject configuration into sub projects, something like: projects { ... declare some projects subprojects { projectDir = file("projects/$name") buildclasspath { ... inject the classpath config } } } or projects { whenProjectAdded { buildclasspath { ... inject the classpath config } } ... declare some projects } An alternative to this configuration injection, would be for a project classloader to extend their parent's classloader. This might be a simple starting point for now, as I think the classloader graph will need to be re-done for whatever modularisation solution we come up with in 0.8. > Thanks for taking the time to think all this through. This is an > important step to help gradle scale up to large projects. > And thank you for the feedback. Adam --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: removing the settings.gradle fileOn 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). Does this makes sense? I need to understand this before commenting on the other issues. - Hans -- Hans Dockter Gradle Project Manager http://www.gradle.org --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: removing the settings.gradle fileHans 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 |
|
|
Re: removing the settings.gradle fileOn Jun 3, 2009, at 11:15 AM, Adam Murdoch wrote: >>> 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. Right. That would simplify things. We would expose the whole project API by that. But that would be a feature. And parts of the API which are not supposed to be used at that lifecycle phase can be shielded with an exception. - Hans -- Hans Dockter Gradle Project Manager http://www.gradle.org --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: removing the settings.gradle file> * 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 |
|
|
Re: removing the settings.gradle file<snip>
> usePlugin(SomeClass) { > dependencies group: 'myOrg', name: 'myBuildInfrastructureProject', > version: '1.0+' > } What is the use case for custom dependencies of a plugin. Wouldn't rather the plugin declares its dependencies. - Hans -- Hans Dockter Gradle Project Manager http://www.gradle.org --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: removing the settings.gradle fileHans Dockter wrote: > <snip> > >> usePlugin(SomeClass) { >> dependencies group: 'myOrg', name: 'myBuildInfrastructureProject', >> version: '1.0+' >> } > > What is the use case for custom dependencies of a plugin. Wouldn't > rather the plugin declares its dependencies. > This is defining the jar for the plugin. As you say, the plugin would declare its dependencies in its meta-info somewhere. I guess 'dependencies' is the wrong term to use in the example. Perhaps 'classpath' is better: usePlugin(SomeClass) { classpath group: 'myOrg', ... } Adam --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: removing the settings.gradle fileOn Thu, 2009-06-04 at 10:11 +0200, Hans Dockter wrote:
> <snip> > > > usePlugin(SomeClass) { > > dependencies group: 'myOrg', name: 'myBuildInfrastructureProject', > > version: '1.0+' > > } > > What is the use case for custom dependencies of a plugin. Wouldn't > rather the plugin declares its dependencies. Isn't the problem here how to tell Gradle where the jar is that contains the code of the plugin itself? For the Cobertura plugin I need to extend the Gradle class path to include the Cobertura jar. -- Russel. ============================================================================= Dr Russel Winder Partner xmpp: russel@... Concertant LLP t: +44 20 7585 2200, +44 20 7193 9203 41 Buckmaster Road, f: +44 8700 516 084 voip: sip:russel.winder@... London SW11 1EN, UK m: +44 7770 465 077 skype: russel_winder |
|
|
Re: removing the settings.gradle fileHans Dockter wrote: > > >> * 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. Any thoughts on what would be more intuitive? I wonder if we even need this, if we use the build file name as the default project name. > 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. > > This is a good option. >> - 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 > } > } > The name would default to 'subproject'. But it might change at some point (soon) after the println statement. >> >> 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. > Right. Alternatively, the classes from buildSrc runtime would be available in the project { } closure. Which means you could add stuff to the buildSrc runtime config to make it available. >> - 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. > Should a project's classloader extend it's parent's classloader? >> * 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. I wonder if it has to be such a big leap. For example, we could use it to wire up Gradle itself to start with, and only later use it to wire up plugins and projects. Or the other way around (which might be a better option). In addition, I imagine we could build the OSGi plugin system to sit alongside the old plugin system, so that we can port the plugins (if that is needed) one at a time. I can't really think of any general solution to this problem that doesn't involve a ClassLoader DAG + some declarative meta-data + a packaging format, ie what OSGi provides. So I think a plan might be to leave the plugin + build script classpaths together for now, and look at using OSGi to wire plugins into projects (and only that) soon. Adam --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
| Free embeddable forum powered by Nabble | Forum Help |