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