On 16/11/2012, at 5:57 AM, Adam Murdoch wrote:

> Hi,
> 
> One issue we need to sort out with the new publication DSL is what should be 
> published by default, and how the user can override this.
> 
> So, for example, if I apply both the 'java' and 'war' plugins, what should be 
> published by default? The war and its meta-data? The war + jar + their 
> meta-data? Nothing? How do I change this? What happens when I then apply the 
> 'ear' plugin?
> 
> Another question is whether we make a distinction between those publications 
> that should end up in a repository and those publications that should be used 
> locally within the same build.
> 
> So, for example, if I apply both the 'java' and 'war' plugin and I specify 
> (however it is I do this) that only the war should be published (to a 
> repository), should the jar + meta-data still be available via a project 
> dependency? How do I change this?
> 
> Right now, we use a series of hacks that don't really work. I think we should 
> take this opportunity to move away from this and fix some issues while we're 
> there.

It would be a shame to drag this mess with us into the new world.

> Given that we want to move to a high-level model that describes components 
> and their relationships, I think the solution should start us down this path. 
> Components feel like a good solution here.
> 
> So let's say that when you apply the 'java' plugin, you're declaring that the 
> project produces a Java-based component of some kind. Some kind of 
> JavaBasedComponent instance is created and shoved in a container somewhere. 
> And when you apply the 'war' plugin, you're declaring that the project 
> produces an J2EE based web application. Some kind of J2EEWebApplication 
> instance is created and shoved in a container somewhere.
> 
> We have a few options as to what to publish:
> 
> 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:
> 
> This would publish the web application as a war + meta-data, as we do now 
> (sort of):
> 
> apply plugin: 'java'
> apply plugin: 'war'
> apply plugin: 'ivy-publish'
> 
> This would publish the web application as a war + meta-data and the java 
> component as a jar + meta-data:
> 
> apply plugin: 'java'
> apply plugin: 'war'
> apply plugin: 'ivy-publish'
> 
> publishing.publications.ivy {
>     publish components.java // a few too many 'publish'es in there, but you 
> get the idea
> }
> 
> 2. Don't publish anything. You need to declare it, perhaps something like:
> 
> apply plugin: 'java'
> apply plugin: 'war'
> 
> publishing.publications.ivy {
>     publish components.java
>     publish components.webApplication
> }
> 
> 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.
> 
> 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'
> 
> This would publish the web application as a war + meta-data:
> 
> apply plugin: 'java'
> apply plugin: 'war'
> 
> This would publish both the war and the jar:
> 
> apply plugin: 'java'
> apply plugin: 'java-library'
> apply plugin: 'war'
> 
> This would publish an application distribution and the web application as a 
> war:
> 
> apply plugin: 'java'
> apply plugin: 'application'
> apply plugin: 'war'
> 
> 4. Don't publish anything and add an opinionated 'publish-main-component' 
> plugin that works like #1 above.
> 
> I don't really like any of these options, except maybe the 'publish nothing 
> by default' option. Any other suggestions?

I think we can simplify things a lot if we assume that nothing is published by 
default, at the cost of convenience for the simple case of course.

Huge +1 for a 'java-library' plugin and not having the 'java' plugin assume 
that there is a jar to be created (tricky backwards compatibility issue of 
course).

One other option I can think of:

1. Components have 'publishedByDefault' flag, and there are 'java-library' and 
'published-java-library' plugins. Or more generally, 'published-«X»' plugins 
that pre wire a component into the project. Plugins like 'ivy-publish' 
automatically try and publish anything that's marked as publish by default.

> As far as what should be available via a project dependency, it feels like we 
> should make every component available, assuming components have some kind of 
> identity so that they can be referenced from another project. So, perhaps we 
> would add an implicit local publication for each component.

I don't think this is right. I'm convinced, at this stage, that using a 
fundamentally different mechanism for project dependencies vs. external 
dependencies is flawed. Project dependencies are just inferred dependencies on 
publications of a different project.

2 main reasons:
1. Makes dynamic composites simpler on the consumer side
2. Unifies the behaviour when the dependency is sometimes source and sometimes 
binary

For #1, what I have in my head going forward is this:

1. Each project forward declares its publications, including their identities 
(think org/module/group)
2. Projects forward declare their dependencies in terms of the identity of 
dependencies
3. Gradle can detect if a dependency can be satisfied locally, if so it wires 
in a project dependency. If it can't it looks externally for it.

This means that projects are islands that are oblivious to their context WRT 
the multi project environment they are in. You don't need to reconfigure 
projects based on their context. At the moment, to achieve this we have to 
introduce an indirection layer at the client which I think is wrong.

For #2, I want _exactly_ the same semantics when I'm consuming something via 
“project dependency” vs. external dependency… most of the time. There are 
issues with this though…

1. It appears to restrict our ability to make performance optimisations, such 
as using class files instead of jars for project dependencies.
2. More expensive because we have to convert to the publishable model, and 
consume that.

I don't think doing this prevents #1. I think it is still possible.
I'm also not concerned about #2 as we have to be fast at consuming the 
descriptors/models of dependencies and incremental build compensates on the 
producer side I think.


In summary, what I find appealing is a unified model; there are publications 
and dependencies… no weird “project dependencies”. Whether it's coming from 
somewhere in the build vs external is a contextual thing that Gradle works out 
for you.

I appear to have derailed the original topic.


-- 
Luke Daley
Principal Engineer, Gradleware 
http://gradleware.com


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to