On 05/09/2012, at 6:55 AM, Hans Dockter wrote:

> 
> 
> On Tuesday, September 4, 2012, Adam Murdoch wrote:
> Hi,
> 
> One question we need to answer soon is how variants should be mapped to Ivy 
> and Maven repositories. Have a look at the dependency model spec for a 
> definition of variant: 
> https://github.com/gradle/gradle/blob/master/design-docs/dependency-model.md#variant
> 
> We want to define some conventions (or a standard in the cases where there's 
> no obvious convention), and build some plugins that can do useful stuff based 
> on these. As always, the infrastructure needs to be flexible to some degree, 
> so you can choose to use some other convention (but the further you go from 
> our convention, the more work you have to do).
> 
> Some concrete examples we're interested in:
> * I want to publish Groovy 1.8 and Groovy 2.0 variants of my Groovy library.
> * I want to publish x86 and amd64 variants of my native library.
> * I want to publish minified and non-minified variants of my Javascript 
> library.
> 
> There's another dimension that we're not interested in here (it's a separate 
> discussion), and that is packaging:
> * I want to publish my Groovy library as both a jar and as a distribution.
> * I want to publish both a jar and a war from my Java project.
> 
> There are a few basic options for mapping component variants to a repository:
> 
> 1. Publish every variant as a single module. So, for my native library, 
> Gradle would publish module 'my-org:my-lib' that contains both the x86 and 
> amd64 binaries, the header archive, maybe source and API documentation 
> archives, plus meta-data for both variants.
> 
> For a maven repository, this might look like:
> 
> my-org/my-lib/1.2
>     pom.xml
>     my-lib-1.2-x86.so
>     my-lib-1.2-amd64.so
>     my-lib-1.2-cpp-headers.zip
>     my-lib-1.2-source.zip
>     my-lib-1.2-doxygen.zip
> 
> For an ivy repository, it would look more or less the same. The artefacts 
> might have different names - e.g. my-lib-x86-1.2.so instead of 
> my-lib-1.2-x86.so.
> 
> 2. Publish every variant as a separate module. So, for my native library, 
> Gradle would publish module 'my-org:my-lib-x86' that contains the x86 
> binaries, and 'my-org:my-lib-amd64' for the amd64 binaries. Variant 
> independent archives would go in both places.
> 
> For a maven repository, this might look like:
> 
> my-org/my-lib-x86/1.2
>     pom.xml
>     my-lib-1.2.so
>     my-lib-1.2-cpp-headers.zip
>     my-lib-1.2-source.zip
>     my-lib-1.2-doxygen.zip
> 
> 3. Publish each variant as a separate module, plus publish a 
> variant-independent module. For my native library, Gradle would publish 
> 'my-org:my-lib-x86' for the x86 binaries and meta-data, 'my-org:my-lib-amd64' 
> for the amd64 binaries and meta-data, and 'my-org:my-lib' for the headers, 
> source, documentation and meta-data about the available variants.
> 
> For a maven repository, this might look like:
> 
> my-org/my-lib-x86/1.2
>     pom.xml
>     my-lib-1.2.so
> 
> my-org/my-lib/1.2
>     pom.xml
>     my-lib-1.2-cpp-headers.zip
>     my-lib-1.2-source.zip
>     my-lib-1.2-doxygen.zip
> 
> Option 1. has some downsides
> * Often, the meta-data for each variant is different. For example, my Groovy 
> 1.8 variant depends on groovy:1.8, and my Groovy 2.0 variant depends on 
> groovy:2.0. Or, in native space, my windows variants need library a, and my 
> linux variants need completely different library b. For this option, there's 
> a single descriptor that we have to jam everything into.
> 
> Which is impossible with Maven. Though I think the non Java world is not 
> strongly bound to Maven. So why not have it in one descriptor in the case of 
> Ivy. If we would model our own descriptor, how would we do it? Having one 
> descriptor provides one place to get all the Metadata you need.

I'm tending towards separate meta-data files for each variant. Some of this 
meta-data you don't know until you build the variant (think ivy-deliver type 
meta-data). If you had a single meta-data file for all variants, you'd need to 
update this each time you published a variant and merge in the version-specific 
stuff. Which means every meta-data file has to be considered as changing, which 
is nasty.

>  
> * The variants are not directly addressable from some other build tool.
> 
> Why?

Not easily addressable, I should have said. If I map the Groovy 1.8 and Groovy 
2.0 variants to separate modules, then in Maven I can do:

<dependency>
    <groupId>my-group</groupId>
    <artifactId>my-lib-groovy18</artifactId>
    <version>1.2</version>
</dependency>

Or in Ant + Ivy:

<dependency org="my-group" name="my-lib-groovy18" rev="1.2"/>

If I map all variants to a single module, then I need to add more stuff: a 
classifier attribute, or a configuration name, or an <artefact> element.

If I wanted my Groovy library to be consumed by Maven or Ant+Ivy builds, it 
would make a lot more sense to publish it as module-per-variant than 
single-module.

>  
> * Often, the variants are not all built and published in one build. For 
> example, my Windows variants are built on a different machine to my Linux 
> variants. This means that the module is effectively a changing module for 
> some period of time.
> 
> Makes sense.
>  
> 
> Option 2 addresses these, but adds some new issues:
> * There's no meta-data for the component as a whole. For example, which 
> variants are available? which variants are available that can be linked into 
> a 32 bit windows debug multi-threaded executable?
> * Variant independent artefacts are published multiple times. For example, if 
> I have 16 different combinations of operating system, data model, debug and 
> compiler, I end up with 16 copies of my headers and source.
> 
> Option 3 feels pretty good to me. It adds physical representations for each 
> of the 3 'things' here: the 2 variants and the component itself.
> 
> Which has also the same downside of being a changing module as in option 1, 
> i.e. the metadata of the component. 

Not necessarily. You just publish the component metadata last, once all the 
variants are built. This would mark the component as ready for consumption.


> 
> We do have some other options for publishing to Ivy repositories. For 
> example, we might publish a single module and add [variant] as something you 
> can refer to in an artifact pattern, so you can do something like this:
> 
> my-org/my-lib/1.2
>     ivy.xml
>     my-lib-cpp-headers-1.2.zip
>     my-lib-source-1.2.zip
>     x86/
>         my-lib-1.2.dll
>         my-lib-1.2.lib
>         my-lib-1.2.pdb
>     amd64/ 
>         ...
> 
> I'd rather use the same mapping for both Maven and Ivy, however.
> 
> I'm not sure. I'd rather not have the pom model influence what we think is 
> the best design for this. I think having different mappings for Ivy if we 
> think the Ivy mapping is better is fine.

Not sure yet. Let's see what comes out of this discussion.


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