On 10/12/2012, at 11:09 AM, Daz DeBoer wrote:

> 
> 
> On 6 December 2012 15:42, Adam Murdoch <[email protected]> wrote:
> 
> On 07/12/2012, at 8:36 AM, Daz DeBoer wrote:
> 
> Just to recap where we've gotten to so far, I think we have the following 
> options. 
> 
> Note: for all these options, there will be a DSL to allow you do explicitly 
> declare the components to be published.
> 
> 1. Publish nothing by default:
>       * Either the 'java' plugin or a new 'jvm-library' plugin (or both) 
> registers a jvm-library component.
>       * Need to declare exactly what to publish via the DSL.
>  
> I guess publishing everything would be as simple as something like:
> 
> publications {
>      publish components.all // Not sure if 'publish' is the right keyword 
> here?
> }
> 
> This option also removes the question of what to publish when no 
> component/publication is available (it's no longer implicit).
> 
> Would we want to provide a way to publish certain components to particular 
> repositories?

Possibly. There's 4 parts to the publishing stuff, which would combine:

1. Declaring 'publish these components' is simply shorthand for 'add these 
components to the default Ivy and Maven publications'.
2. There is a capability to add a component to a publication.
3. There is a capability to add new (empty) Ivy and Maven publications.
4. There is a capability to publish a publication to a repository. We have this 
now in the publish tasks.

So, if you really wanted, you could do something like this:

1. Apply the 'publish' plugin instead of the 'ivy-publish' or 'maven-publish' 
plugins, so that nothing is published by default.
2. Add (empty) publications 'a' and 'b'.
3. Add components 1 and 2 to publication 'a', and component 3 to publication 
'b'.
4. Add repositories 'internal' and 'external'.
5. Add a task that publishes publication 'a' to repo 'internal' and publication 
'b' to repo 'external'.
6. Wire up 'publish' to depend on these 2 tasks.

Maybe there'll be some DSL support for this kind of thing at some point, if we 
hit the use cases. The plan for now is that there's infrastructure 
(repositories, publications, components and a few task types) that you need to 
wire together yourself, and a very small number of opinionated plugins that 
will wire it together for you in exactly one way (publish everything to every 
repository).


> 
> 
> 2. Publish a single thing, inferred from the set of components declared for 
> the project.
>       * Either the 'java' plugin or a new 'jvm-library' plugin (or both) 
> registers a jvm-library component.
>       * Can replace or add to the inferred component via the DSL.
>       * Two variations for the rule:
>               * if there is exactly one component, then use it.
>               * if there is exactly one component, then use it. When there 
> are multiple components, then 2jee app wins over web app wins over jvm 
> library wins over jvm component.
>       * Fail if we can't infer the component to publish.
> 
> 3. Publish everything, by default don't publish the jar:
>       * The 'java' plugin does not register any component.
>       * A new 'jvm-library' plugin registers jvm-library component.
>       * This implies that the 'war' and 'application' plugins will not 
> implicitly add a jvm-library component.
> 
> I think the 'publish every component' could work pretty well, if we assume 
> that the existing plugins will not register any components:
>     * For starters, we have 'jvm-library' and 'j2ee-web-application' 
> components, with new plugins that add them to the model.
>     * 'java' & 'war' plugins do not register any components
>     * Publishing will attempt to publish all registered components. 
>     * Publishing multiple components will fail gracefully, until we implement 
> and test properly.
>     * Publishing with no components will fail.

I'm not sure it does work that well. One problem is that that java and war 
plugins really do define components - a jvm-based component and a j2ee web 
application respectively.

The other is that it stops working once you look beyond the jar + war case:

* If I have an j2ee app that bundles the web app, then I only want to publish 
the web app. So, in this case I apply the 'ear' and 'war' (or 
'j2ee-web-application') plugin. I only want the ear published, but I'm going to 
end up with both the ear and war published.
* If I have a java application that bundles a web app, then I only want to 
publish the application dist. So, in this case I apply the 'application' and 
'war' plugins. I only want the dist published, but I'm going to end up with 
both the dist and the war published.
* If I have a java library that bundles a native jni library, then I only want 
to publish the java library. So, in this case I apply the 'java' (or 
'jvm-library') plugin plus the 'cpp-lib' plugin, but I'm going to end up with 
both the java and native libraries published.


> 
> I'm not sure that this option removes the need for a DSL for specifying 
> exactly what to publish.

It doesn't, as the examples above show.

> Or perhaps this level of control is done on the Publications collection 
> instead of at the Component level?

That is certainly an option. You'd be able to add components to publications 
(and maybe remove them too).

> 
> 
> 4. Publish everything, by default don't publish jar when used with war plugin
>       * The 'java' plugin registers a jvm-library component.
>       * A new 'java-lang' plugin adds java language support.
>       * The 'war' plugin or a new 'web-application' plugin adds java language 
> support but does not implicitly add a jvm-library component.
>       * Do the same for the 'application' plugin.
> 
> I'd like to add a new option:
> 
> 5. Introduce the concept of bundling, and publish those components that do 
> not bundle (or imply) one of the other components:
>       * If I produce a jvm component and a web application that bundles that 
> library, then I almost always want to publish just the web application.
>       * If I produce a web application and a jvm component and a j2ee 
> application that bundles the web app and library, then I almost always want 
> to publish the j2ee application
>       * If I produce a java command-line application and a jvm component that 
> is bundled, then I want to publish the application.
>       * If I produce a jvm component and a native shared library, then I want 
> to publish both.
>       * If I produce a jvm library and a web application that does not 
> include that library, then I want to publish both.
> 
> Just a reminder: for all these options, there will be an underlying DSL where 
> you can change whatever it is that Gradle publishes by default. So, I think 
> the goal here is to choose an option that most often does the right thing 
> (and preferring an approach where you add missing stuff rather than remove 
> unwanted stuff). We don't need a solution that always does the right thing.
> 
> At this stage, I think option #1 or option #5 is the way to go. We can get 
> started without requiring any restructuring of the existing plugins (which we 
> still want to do at some point).
> 
> I'd vote for #1 or #3, with a slight preference for #3. My reasoning is that 
> it 'just works' in more cases: a user declares what the project produces 
> (jvm-library, etc) and that thing gets published. 

#3 really only "just works" when there's only one component defined.

So, assuming that we eventually change things so that defining a web 
application or adding Java language support does not implicitly define a 
jvm-based component, then #2 (publish one component if there is exactly one 
component defined, otherwise fail) would work just as well, and you'd adjust 
the default by adding things for publication, instead of removing things for 
publication. Adding things, rather than removing, just works better with our 
DSL.


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