On 2 Dec 2013, at 8:30 pm, Michael Putters <michael.putt...@binarygenetics.com> 
wrote:

> On 2013-12-02 00:40, Adam Murdoch wrote:
>> Good question. There’s 4 things the DSL needs to do:
>> 1. Allow you to define a source set of a given type and configure it,
>> e.g. to set the source directories or whatever.
>> 2. Allow you to declare dependencies between source sets (and other
>> things).
>> 3. Allow you to combine source sets into a component.
>> 4. Allow plugins to do these things as a convention and allow you to
>> change what the convention has done.
>> One option is to flatten the whole thing out, so that definition and
>> wiring and composition are all separate things. For example, to wire
>> up the source for a library ‘mylib’ the plugins might do something
>> like:
>> sources {
>> // headers and source files are separate things
>> mylibApi(HeaderSet) {
>> srcDirs = ‘src/mylib/public’
>> }
>> mylibShared(HeaderSet) {
>> srcDirs = ‘src/mylib/include’
>> dependsOn mylibApi
>> }
>> mylibCpp(CppSourceSet) {
>> srcDirs = ’src/mylib/cpp’
>> dependsOn mylibShared
>> }
>> mylibC(CSourceSet) {
>> srcDirs = ‘src/mylib/c’
>> dependsOn mylibShared
>> }
>> mylib(NativeLibrarySourceSet) {
>> api mylibApi
>> source mylibCpp, mylibC
>> }
>> }
>> libraries {
>> mylib {
>> source = sources.mylib
>> }
>> }
>> You’d be able to navigate to things via their relationships in order
>> to configure them and query them:
>> libraries {
>> mylib {
>> sources {
>> cpp {
>> srcDirs = ‘…’
>> dependsOn libraries.someOtherLib
>> }
>> }
>> }
>> }
>> To wire in more source sets, you’d do something like:
>> // a generated source set
>> sources {
>> mylibGeneratedC(CSourceSet) {
>> generatedBy someTask
>> dependsOn libraries.someLib
>> }
>> mylib {
>> source mylibGeneratedC
>> }
>> }
>> // some private headers visible only to the C source files
>> sources {
>> mylibCHeaders(HeaderSet) {
>> srcDirs = ‘…'
>> }
>> mylibC {
>> dependsOn mylibCHeaders
>> }
>> }
>> // windows specific cpp
>> sources {
>> mylibWindowsCpp(CppSourceSet) {
>> srcDirs = ‘src/mylib/windows/cpp’
>> dependsOn operatingSystems.windows
>> }
>> mylib { source mylibWindowsCpp }
>> }
>> That is, most stuff happens at the source set level. This is flexible
>> but ignores that, from most people’s point of view, the component is
>> the more important concept.
>> So, another option is to combine definition and aggregation. The
>> plugins would do something like:
>> libraries {
>> mylib {
>> sources {
>> api(HeaderSet) {
>> srcDirs = ‘src/mylib/public’
>> }
>> shared(HeaderSet) {
>> srcDirs = ‘src/mylib/include’
>> dependsOn api
>> }
>> cpp(CppSourceSet) {
>> srcDirs = ’src/mylib/cpp’
>> dependsOn shared
>> }
>> c(CSourceSet) {
>> srcDirs = ‘src/mylib/c’
>> dependsOn shared
>> }
>> }
>> }
>> api = sources.api
>> }
>> Each source set could probably be visible as a separate thing via the
>> sources container:
>> sources {
>> mylibApi { // tweaks the libraries.mylib.sources.api source set }
>> }
>> To wire in more source sets, you’d do something like:
>> // a generated source set
>> libraries {
>> mylib {
>> sources {
>> generatedC(CSourceSet) {
>> generatedBy someTask
>> dependsOn libraries.someLib
>> }
>> }
>> }
>> }
>> // some private headers visible only to the C source files
>> libraries {
>> mylib {
>> sources {
>> cHeaders(HeaderSet) {
>> srcDirs = ‘…'
>> }
>> c {
>> dependsOn cHeaders
>> }
>> }
>> }
>> }
>> // windows specific cpp
>> libraries {
>> mylib {
>> sources {
>> windowsCpp(CppSourceSet) {
>> srcDirs = ‘src/mylib/windows/cpp’
>> dependsOn operatingSystems.windows
>> }
>> }
>> }
>> }
>> This approach seems more natural for most use cases, but is more rigid
>> because source sets can only be defined as part of a native component,
>> and this isn’t always the reality.
>> We might also combine the two approaches, so you can define source
>> sets either at the top level or as part of a component, or wherever it
>> makes sense, and refer to them from either context:
>> sources {
>> someArbitrarySourceSet(CSourceSet) {
>> dependsOn libraries.myotherlib
>> dependsOn sources.someSourceSet
>> dependsOn libraries.mylib.sources.cpp
>> }
>> }
>> libraries {
>> mylib {
>> // An alias for
>> libraries.mylib.sources.add(project.sources.someArbitrarySourceSet)
>> buildFrom sources.someArbitrarySourceSet
>> }
>> myotherlib {
>> buildFrom sources.someSourceSet
>> }
>> }
> 
> Hm I wouldn't mind working on that (assuming nobody is already doing it)…

That would be great.

> 
> First on the source level approach then expand it so the combined approach is 
> also possible.
> 
> But I believe it might be still be a a bit big for a single pull request 
> (especially considering I'm still quite new to the codebase), how do you 
> think this task could best be split up so that it can become multiple pull 
> requests? Unless it's actually not that big and will look simple once I dive 
> in :)

I think we should do this as a series of pull requests. I’ve fleshed out a bit 
of a plan for how we could do this: 
https://github.com/gradle/gradle/blob/master/design-docs/continuous-delivery-for-c-plus-plus.md#feature-flexible-source-sets

There are 3 stories, each with a couple of steps.


--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com



Reply via email to