On 17/01/2013, at 12:10 PM, Adam Murdoch wrote:
>
> Another question is how to group source sets and packagings.
>
> For source sets, we currently use two approaches:
>
> - For Java, Scala, Groovy, ANTRL and resources, we use the functional source
> sets, adding the source to `sourceSets.${function}.${language}`.
> - For C++, we use language specific source sets, adding the source to
> `cpp.sourceSets.${function}.source` and
> `cpp.sourceSets.${function}.exportedHeaders`.
>
> I'd like to come up with a consistent pattern here, which can allow arbitrary
> groupings of source files by language and by function. I can see three
> options. For all these options, assume that all source sets are composable to
> some degree, so, for example, you can add a given Java source set to another
> Java source set, or you can add a given Java source set to a composite source
> set.
>
> 1. Java plugin style, where the primary grouping is functional:
> `sourceSets.${function}.${language}`:
>
> sourceSets {
> main {
> cpp { srcDirs = '…' }
> cppHeaders { srcDirs = '…' }
> javaScript { srcDirs = '…' }
> }
> }
>
> 2. C++ plugin style, where the primary grouping is by language:
> `${language}.sourceSets.${function}`
>
> java {
> sourceSets {
> main { srcDirs = '…' }
> }
> }
> groovy {
> sourceSets {
> main { srcDirs = '…' }
> }
> }
> resources {
> sourceSet {
> main { srcDirs = '…' }
> }
> }
> javaScript {
> sourceSets {
> main { srcDirs = '…' }
> }
> }
>
> 3. Both, where defining `sourceSets.${function}.${language}` also defines
> `${language}.sourceSets.${function}` and vice versa.
>
> 4. A polymorphic container of source sets. You use whatever groupings you
> like, and can add language specific or composite source sets to this
> container. The opinionated language plugins would continue to group by
> function and add a `main` and `test` composite source set.
>
> sourceSets {
> main(CompositeSourceSet) { // possibly the default type
> java { srcDirs = '…' }
> cpp { srcDirs = '…' }
> resources { srcDirs = '…' }
> }
> test(GroovySourceSet) {
> srcDirs = '...'
> }
> }
>
My preference at this stage is to go with option #1. Let's dig into this a bit
more.
The goal, regardless of whichever grouping option we choose, is to introduce
language specific source sets as a layer underneath this. So, we'd add types
like JavaSourceSet, GroovySourceSet, CppSourceSet, and so on. These types would
have some stuff common - mainly just a set of source files - and some meta-data
about the source files:
- For a Java source set, this would include the Java language level and Java
API that the source is written against, and the compile and runtime
dependencies of the source.
- Same for Groovy and Scala source sets, except with the Groovy and Scala
languages and runtimes. The Java API is also relevant for this source, I guess.
These source sets also have some way to declare the compiler macros/AST
transforms that the source expects to be available, probably as a set of
dependencies on the implementation libraries.
- For a C/C++ source set, this would include the language dialect that the
source is written against, and the compile, link and runtime dependencies of
the source.
- For an ANTLR source set, this would include the ANTLR language version that
the grammars are written to.
- For a Javascript source set, this would include the runtime dependencies of
the source.
One question is how to model source sets that are related to each other at the
language level:
- C/C++ source files and their public headers and private headers.
- Java (Scala/Groovy) source and their resource source files.
- Jointly compiled Java/Scala/Groovy source files.
Currently, the C++ plugin groups the C++ source files and headers into a
CppSourceSet, with separate SourceDirectorySets for the source and for the
headers. The Jvm language plugins group the Java/Scala/Groovy and resources
into a SourceSet, with separate SourceDirectorySets for each language. So,
these plugins are effectively grouping the source based on the target platform,
or by target output component, depending on your view.
Do we keep these typed groupings (or something similar), or do we model this as
an untyped composite source set that contains a bunch of atomic language source
sets? There are some problems with the current groupings:
- The ANTLR source is currently attached to the 'jvm' group, but ANTLR can
generate C, C#, and bunch of other languages.
- Java source and JVM byte code can be compiled to native code.
- Groovy, Scala and ANTLR source are added in dynamically via a convention
object, so don't make use of the typing anyway. It would be the same for native
languages other than C/C++ as well. So you've got this first-and second-class
thing going on. It feels like a good solution should not treat certain
languages specially.
- Sometimes multiple groups of source in a given language make up a logical
group. Eg API + impl, java 5 + java 6, windows + posix, etc.
Let's say we remove the typed groupings (in a backwards compatible way, as
always). It might work something like this:
- Some basic 'language' plugin adds the concept of (composite) source sets. You
can define source sets and add whichever language source sets you like.
- A 'jvm-language' plugin adds a rule that adds a resources source set to each
source set, adds the concept of JVM packagings, and a rule that knows how to
copy the resource files that are inputs to a JVM packaging.
- A 'java-language' plugin adds a rule that adds a Java source set to each
source set, and a rule that knows how to compile the Java source that are
inputs to a JVM packaging.
- Groovy and Scala language plugins, as above.
- A 'standard-source-sets' plugin adds the 'main' and 'test' source sets.
- The 'java-base' plugin adds a rule that adds a classes dir packaging for each
source set, and wires up the source set as input to the packaging.
- The 'java', 'groovy' and 'scala' plugins just apply various combinations of
the above plugins.
- The 'android' plugin adds an Android resources source set to each source set
(these are different to the JVM resource files above), and APK packaging, and a
rule that knows how to compile the resources and classes packaging into an APK
packaging.
- A 'native-language' plugin adds the concept of native packagings.
- A 'cpp-language' plugin adds a C/C++ source set, a public headers source set
and a private headers source set to each source set, and a rule that compiles
C/C++ source that are inputs to a native packaging.
- The 'cpp-lib' and 'cpp-exe' plugins just apply various combinations of the
above plugins.
- An 'assembly-language' plugin adds an assembly source set to each source set
and a rule that compiles assembly source that are inputs to a native packaging.
- A 'javascript-language' plugin adds a Javascript source set to each source
set, and the concept of a Javascript packaging.
> Thoughts? Other options?
>
> On 16/01/2013, at 5:06 PM, Adam Murdoch wrote:
>
>> Hi,
>>
>> To better support building Android apps (and other things), we want to
>> rework the jvm language plugins so that they can handle building multiple
>> outputs from a given set of source files.
>>
>> I've made a bit of a start on a spec here, but's pretty rough:
>> https://github.com/gradle/gradle/blob/master/design-docs/building-multiple-outputs-from-jvm-languages.md
>>
>> I need some suggestions for terminology:
>>
>> 1. A term for the things that Gradle builds. With this work, plus
>> publications, components, reports and distributions work that is happening,
>> we're starting to model more of the things that Gradle can build. It feels
>> like we should have a term for this. So far we've been calling these things
>> 'things' and sometimes 'outputs'. I kind of like the term 'build item' from
>> abuild.
>>
>> 2. A term for a thing that runs on a JVM. This is the focus of the spec
>> above. The spec calls these things a 'packaging', but this doesn't really
>> work that well. Note that this isn't the logical thing - we're calling them
>> 'components' - but the physical thing. Initially, there are 2 types of this
>> thing - a class directory packaging and a JAR packaging. If we come up with
>> a good term for 'things' in #1 above, we could just shove 'jvm' in front of
>> it as a name for these things (e.g. 'jvm build item').
>>
>> 3. A term for a set of source of a specific language, that forms the input
>> to a compilation step. This is different to what we call 'source set' at the
>> moment - that's a logical grouping of source. The spec calls these things a
>> 'language source set'.
>>
>> 4. A term for a logical set of source. Currently we call these a 'source
>> set'. The spec calls these things a 'functional source set'.
>>
>> Suggestions?
>>
>> --
>> Adam Murdoch
>> Gradle Co-founder
>> http://www.gradle.org
>> VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
>> http://www.gradleware.com
>>
>
>
> --
> Adam Murdoch
> Gradle Co-founder
> http://www.gradle.org
> VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
> http://www.gradleware.com
>
--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com