On Wed, Sep 5, 2012 at 2:18 AM, Adam Murdoch <[email protected]>wrote:
> > 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. > That is what I was thinking. > > 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. > Now that you mention it, I agree that it is 'against' the normal flow of those build systems, in particular Maven. > > > >> * 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. > OK. Makes sense. Hans > > > >> 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 > >
