On 07/12/2012, at 5:20 AM, Daz DeBoer wrote:

> G'day
> Sorry to come late to the party. I'm responding to the original email that 
> kicked off this thread:
> 
> On 15 November 2012 22:57, Adam Murdoch <[email protected]> wrote:
> 1. Infer the 'main' component and publish this, as we do now. To publish an 
> additional component, you'd add it to the appropriate publication:
> 
> I think we all agree that we don't want this magic.  
> 
> 2. Don't publish anything. You need to declare it, perhaps something like:
> 
> It's nice if things "just work" in most cases. In this case, do you mean 
> "Don't publish anything by default, ever", or "Don't publish anything when 
> there are multiple main artefacts"?

I meant "don't publish anything by default, ever", but they're both options.

> For the latter case, I would suggest that publishing without explicitly 
> declaring which artifact(s) is a failure situation? So basically, if there is 
> one 'main' publication, just publish it. If there are more, ask the user for 
> more information.
> 
> So this could work by leaving the plugins as-is, but introducing a DSL for 
> declaring which artifacts to publish. Default would be to publish 1 main 
> publication if available, or fail for multiple main artefacts.

The problem is that currently the java (and groovy, scala) support tangles up 
the knowledge of how to compile Java source with the assumption that you're 
building a Jvm-based library. So, without detangling those things, as soon as 
you want to build something other than a Jvm-based library, then suddenly 
you've got more than one main publication. If you're building a command-line 
application, or a web app, or an J2EE app, or an Android app, and this thing 
contains some classes compiled from Java source, then Gradle decides that 
you're building two things: the thing you actually want to build, plus a 
Jvm-based library.

To make any of these options (except "don't publish anything") work well, we're 
going to have to separate the language support from the assumption that you're 
building a library.


> 
>  
> 3. Split the 'java' plugin into a Java language plugin that knows how to 
> compile and test Java based stuff, and a Java library plugin that knows how 
> to publish a Java library for use outside the project.
> 
> An alternative would be to do the split by introducing a 'java-lang' plugin 
> that adds the language support (all of the current 'java' plugin),  leaving 
> the 'java' plugin to mean "I'm building a jar". The 'war' plugin would apply 
> the 'java-lang' plugin. This means that applying 'war' on it's own would 
> publish the war file, and applying 'java' on it's own would publish the jar. 
> Applying both would require more configuration. Just an idea. 
> 
> The benefits would be that the 'war' and 'java' plugins would continue to 
> publish the same as they currently do. They would not need to add "apply 
> plugin: 'java-library'" to get their jar published. The downside is that 
> effectively renaming the current 'java' plugin to 'java-lang', and adding a 
> new 'java' plugin to extend this, is not back-compatible?

I suspect many projects currently apply both the 'java' and 'war' plugins, so 
this change would mean that these projects would start publishing the jar.

There's also the case where configuration is injected conditionally based on 
which plugins have been applied.

We could tweak this approach to make it backwards compatible (in a way): One 
goal that we have is that the 'war' plugin should not imply a particular 
implementation language, or even that there is any source at all. So, we would 
do something like:

- Introduce a 'java-lang' plugin that knows how to compile java source. Same 
for Scala and Groovy.
- Introduce a 'jvm-library' plugin that knows how to build a jvm-based library. 
Does not apply any language plugins.
- Change the 'java' plugin to apply both these things.
- Introduce a 'web-application' plugin that knows how to build a j2ee web 
application. Does not apply any language plugins.
- Change the 'war' plugin to apply both the 'web-application' and 'java' 
plugins.
- New publishing DSL publishes all components
- Deprecate and remove the 'war' plugin
- Deprecate and remove the 'java' plugin (or rename it to 'java-library')

To use the new DSL to publish a web app, you'd need to apply the 
'web-application' and the language plugins for whichever implementation 
languages you happen to be using. Or, you can use the 'war' plugin, but you'll 
also end up publishing the jar.

To use the new DSL to publish an EAR, you'd need to apply the 'ear' plugin plus 
the language plugins for whichever implementation languages you happen to be 
using.

However, it all stops working when you're building an EAR that contains a WAR, 
as now you'll be publishing both of them.


> 
> We'd need to introduce 'groovy-lang' and 'scala-lang' too, I guess.
> 
> 
> This does not publish anything:
> 
> apply plugin: 'java'
> 
> This would publish the Java library as a jar + meta-data:
> 
> apply plugin: 'java'
> apply plugin: 'java-library'
> 
> Would this be more like 'jvm-library'? What if you were compiling groovy or 
> scala? Are they different library plugins for different languages? Or is 
> 'java' the language and 'jvm-library' the component type'?

It should be 'jvm-library'.

> 
> Are plugins the right way to compose this sort of behaviour? I guess I mean: 
> are we thinking that over time builds will start to apply lots of smaller 
> plugins to get all of the support they require?

I don't know if 'lots' is the right word. The idea is that you need to tell us:

1. Which languages you'd like to build things from
2. What things you'd like to build

In general, that would be 2 plugins, and I think we'd continue to have some 
plugins that package up common combinations, so for many projects it would be 1 
plugin.

> Is there a lower-level concept that opinionated plugins could be composed of, 
> rather than other plugins?

Implicit in this discussion is that for each opinionated plugin there is a 
toolkit plugin that adds support for the type of thing that the opinionated 
plugin will build. Something like this:

* A 'jvm-library' plugin would apply a 'jvm-library-base' plugin (we need to 
work on the naming scheme). The 'jvm-library-base' plugin would add an empty 
container of JvmLibrary domain objects and rules for how to add tasks to build 
each JvmLibrary in the container. The 'jvm-library' plugin would add an 
instance to this container and wire up its inputs.
* A 'web-application' plugin would do the same thing, but there'd be a 
container of WebApplication instances.
* A 'java-lang' plugin would apply a 'source-sets' plugin. It would add Java 
support to each source set.


--
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