I've not seen any major issues identified with this scheme (other than perhaps platformId might be a better name than architectureId)
Will I take a stab at writing this up more formally then? Should we circulate it more widely? Did anyone involved with the NMaven effort have any thoughts? On Thursday 1 September 2016, Stephen Connolly < [email protected]> wrote: > One of the things I feel is necessary to grow Maven in the modelVersion > 5.0.0 world is to start taking account of architecture specific artifacts. > > Currently, the Maven repository layout does not handle architecture > specific dependencies well. > > So, for example: > > Say I have a foo.jar that depends on a native library... bar.dll / > libbar.so / etc > > Ideally we'd like to say that foo just depends on bar... > > A consumer of foo that is running on, say my local machine, could then see > that I am running on os-x- x86_64 and because I am wanting to run tests... > it would look for bar with the architecture of `os-x-x86_64` to get the > native library for me > > When I am building the installer for windows on my os-x machine (using say > .NET and the WiX toolchain) the corresponding (future does not exist yet) > maven plugin could request the win-x86 architecture of the dependency and > the rpm plugin could request the linux-ppc, linux-arm64, linux-x86 and > linux-x86_64 artifacts in order to produce the corresponding rpm > architecture artifacts > > So when I think about this concept... I feel it is important that we find > a way to introduce the architectureId into the GACVT of the repository. > > When we do this, to my mind, we need to be mindful that modelVersion 4.0.0 > consumers would like to be able to consume these architecture specific > dependencies also... and the 4.0.0 GAV constraints will constrain the > possible solutions that we can pick if we value letting 4.0.0 consumers > access these architecture specific artifacts via the `default` layout we > currently employ for the maven repository. > > So the first things first... our current `default` layout transforms the > GroupId:ArtifactId:Version:Classifier:Type into a repository URL of > > `${groupId.replaceAll('.','/')}/${artifactId}/${version}/${ > artifactId}-${version}${classifier==null?'':'-'+classifier}.${type}` > > If we want to add architectureId into that URL Path and still have that > resolvable by GAVCT at a modelVersion 4.0.0 coordinate, we are basically > left with stuffing the architectureId into one of the existing components... > > Now when we think about an architecture specific artifact, the first thing > that comes to mind is that each architecture specific artifact most likely > has different dependencies... hopefully the .pdt file (that would be > deployed at the GAV without an architecture... modulo multi-machine builds) > would provide the architecture specific dependency trees so that > modelVersion 5.0.0 aware consumers would - just naturally - be aware of > those differences in dependencies > > But - if we want to give the modelVersion 4.0.0 consumers our best effort > - we probably need to give each architectureId it's own modelVersion 4.0.0 > pom. > > In other words, I do not think we should try to munge the architectureId > into either classifier or type as both of those would force the > dependencies to be viewed as having the same dependencies in the > modelVersion 4.0.0 world > > So that leaves us with groupId, artifactId and version... > > I personally think version is a non-runner. In modelVersion 4.0.0 you can > only depend on one version of a dependency at a time... version ranges > would become completely and utterly unusable (never mind that they are > unusable now)... plus my gut tells me that it would be a total mess! > > So that leaves groupId and artifactId... our choices basically boil down to > > legacyGroupId == '${groupId}'; legacyArtifactId == '${architectureId}.${ > artifactId}' > legacyGroupId == '${groupId}'; legacyArtifactId == '${architectureId}-${ > artifactId}' > legacyGroupId == '${groupId}'; legacyArtifactId == '${artifactId}.${ > architectureId}' > legacyGroupId == '${groupId}'; legacyArtifactId == '${artifactId}-${ > architectureId}' > legacyGroupId == '${groupId}.${architectureId}'; legacyArtifactId == > '${artifactId}' > legacyGroupId == '${groupId}.${artifactId}'; legacyArtifactId == > '${architectureId}' > > I personally think that the ones that place `architectureId` lexically > before `artifactId` are not "right"... the most important coordinate is the > groupId, the next most is the artifactId, then the architecture, then the > version, etc > > So to my mind that leaves us with: > > legacyGroupId == '${groupId}'; legacyArtifactId == '${artifactId}.${ > architectureId}' > legacyGroupId == '${groupId}'; legacyArtifactId == '${artifactId}-${ > architectureId}' > legacyGroupId == '${groupId}.${artifactId}'; legacyArtifactId == > '${architectureId}' > > Now when we look at how, say, a modelVersion 4.0.0 consumer would use > these dependencies... the variant where we shift the artifactId into the > groupId would mean that you would end up with loads of `linux-arm` > "legacyArtifactId" dependencies in your modelVersion 4.0.0 consumer... > which would presumably be ugly (just like now if you have two matching > `artifactId` dependencies in your .war which forces us to disambiguate by > prefixing the groupId when copying into WEB-INF/lib)... so I am going to > reject that one also. > > The convention seems to be that the artifactId does not contain a `.` with > most artifacts that I am aware of using `-` as the separator... this could > be used to argue either way... my preference is to run with `-` as the > separator... though I am open to using `.` to provide a convention that > architecture is distinguished using a `.` > > So how would this work... > > Ok, I have my foobar project that builds a .jar and the native libraries > that are required by that .jar > > So from the reactor for that project we want to deploy > > com.example:foobar:::1.0:pom (the legacy pom for the .jar to allow > modelVersion 4.0.0 consumption of the jar) > com.example:foobar:::1.0:pdt (the modern project dependency trees for all > attached artifacts) > com.example:foobar:::1.0:jar (the jar) > com.example:foobar::javadoc:1.0:jar (the javadoc jar) > com.example:foobar::sources:1.0:jar (the source jar) > com.example:foobar:win_x86::1.0:pom (the legacy pom for the 32-bit DLL) > com.example:foobar:win_x86::1.0:dll (the 32-bit DLL... alternatively the > type might be `native-library` or `lib` but let's assume DLL) > com.example:foobar:win_x86_64::1.0:pom (the legacy pom for the 64-bit DLL) > com.example:foobar:win_x86_64::1.0:dll (the 64-bit DLL) > com.example:foobar:osx_x86_64::1.0:pom (the legacy pom for the 64-bit > OS-X .dylib) > com.example:foobar:osx_x86_64::1.0:dylib (the 64-bit .dylib... > alternatively the type might be `native-library` or `lib` but let's assume > dylib) > com.example:foobar:elf_arm::1.0:pom (the legacy pom for the linux ARM .so) > com.example:foobar:elf_arm::1.0:so (the ARM .so ... alternatively the > type might be `native-library` or `lib` but let's assume so) > com.example:foobar:elf_x86::1.0:pom (the legacy pom for the linux x86 > 32-bit .so) > com.example:foobar:elf_x86::1.0:so (the x86-32-bit .so) > com.example:foobar:elf_x86_64::1.0:pom (the legacy pom for the linux x86 > 64-bit .so) > com.example:foobar:elf_x86_64::1.0:so (the x86 64-bit .so) > > My main build machine cannot cross-compile for PPC or ARM64... so we have > two other build machines that will want to produce the extra architecture > specific artifacts... > > com.example:foobar:elf_ppc::1.0:pom (the legacy pom for the linux PPC .so) > com.example:foobar:elf_ppc::1.0:so (the PPC .so) > > and > > com.example:foobar:elf_arm_64::1.0:pom (the legacy pom for the linux ARM > 64-bit .so) > com.example:foobar:elf_arm_64::1.0:so (the ARM 64-bit .so) > > In order to accommodate delayed deployment, I am going to suggest that the > PPC and ARM64 deployments should publish their *supplemental* pdts at their > coordinates, e.g. > > com.example:foobar:elf_ppc::1.0:pdt (the suplemental project dependency > trees for the PPC reactor artifacts) > > and > > com.example:foobar:elf_arm_64::1.0:pdt (the suplemental project > dependency trees for the ARM64 reactor artifacts) > > So ultimately we would end up with the following files being deployed (in > three "atomic" deployments): > > com/example/foobar/1.0/foobar-1.0.pom > com/example/foobar/1.0/foobar-1.0.pdt > com/example/foobar/1.0/foobar-1.0.jar > com/example/foobar/1.0/foobar-1.0-javadoc.jar > com/example/foobar/1.0/foobar-1.0-sources.jar > com/example/foobar-win_x86/1.0/foobar-win_x86-1.0.pom > com/example/foobar-win_x86/1.0/foobar-win_x86-1.0.dll > com/example/foobar-win_x86_64/1.0/foobar-win_x86_64-1.0.pom > com/example/foobar-win_x86_64/1.0/foobar-win_x86_64-1.0.dll > com/example/foobar-osx_x86_64/1.0/foobar-win_x86_64-1.0.pom > com/example/foobar-osx_x86_64/1.0/foobar-win_x86_64-1.0.dylib > com/example/foobar-elf_arm/1.0/foobar-elf_arm-1.0.pom > com/example/foobar-elf_arm/1.0/foobar-elf_arm-1.0.so > com/example/foobar-elf_x86/1.0/foobar-elf_x86-1.0.pom > com/example/foobar-elf_x86/1.0/foobar-elf_x86-1.0.so > com/example/foobar-elf_x86_64/1.0/foobar-elf_x86_64-1.0.pom > com/example/foobar-elf_x86_64/1.0/foobar-elf_x86_64-1.0.so > > com/example/foobar-elf_ppc/1.0/foobar-elf_ppc-1.0.pom > com/example/foobar-elf_ppc/1.0/foobar-elf_ppc-1.0.pdt > com/example/foobar-elf_ppc/1.0/foobar-elf_ppc-1.0.so > > com/example/foobar-elf_arm_64/1.0/foobar-elf_arm_64-1.0.pom > com/example/foobar-elf_arm_64/1.0/foobar-elf_arm_64-1.0.pdt > com/example/foobar-elf_arm_64/1.0/foobar-elf_arm_64-1.0.so > > When a modelVersion 5.0.0 consumer does something like: > > compile: { > dependencies: ["com.example:foobar:1.0:jar"] > } > test: { > dependencies: ["org.junit:junit:5.0:jar"] > } > > and wants to run its tests on linux ARM64 it will start by resolving > `com/example/foobar/1.0/foobar-1.0.pdt` this will give it the dependency > tree of the `.jar` which will declare an architecture dependent native > library dependency (somehow or other... this is why we may use > `native-library` as the "type")... because it knows that it is running on > ARM64 architecture it will then know that it needs > `com.example:foobar:elf_arm_64::1.0:so` since this is not available in > the `com/example/foobar/1.0/foobar-1.0.pdt` trees it will then attempt to > download `com/example/foobar-elf_arm_64/1.0/foobar-elf_arm_64-1.0.pdt` if > that exists, it will use that tree... if it doesn't exist... we fail the > build (technically we could fall back to checking for > `com/example/foobar-elf_arm_64/1.0/foobar-elf_arm_64-1.0.pom` and > `com/example/foobar-elf_arm_64/1.0/foobar-elf_arm_64-1.0.so` before > failing the build... but as we know the artifacts were produced by a 5.0.0 > aware producer - as we have `com/example/foobar/1.0/foobar-1.0.pdt` > resolved) > > A modelVersion 4.0.0 consumer is not really going to be able to have as > flexible a build... but at least they can - through declarations such as > > <dependency> > <groupId>com.example</groupId> > <artifactId>foobar-elf_arm64</artifactId> > <version>1.0</version> > <type>so</type> > </dependency> > > grab the .so to bundle into a .zip or installer and if they want to write > a pom with architecture based profile activation injecting test scoped > dependencies they can do that also > > WDYT? > > If anyone has any experience from the NMaven experiments, or learnings > from .deb or .rpm attempts to solve architecture dependent artifacts mixed > with noarch artifacts... please step forward and join the discussion. > > -Stephen > > Notes: > > 1. I am not saying what conventions will be used to define the > `architectureId` values here > 2. I am not discussing the schema for the .pdt files here... other than > the general priciple that they will contain multiple dependency trees for > each artifact produced by the project > 3. I am not discussing how a modelVersion 5.0.0 build would be invoked or > detect that it should just do the PPC deployment > 4. This proposal does not include the new metadata schema that we would > likely require to assist with such a deployment format > 5. I am not discussing or proposing a modelVersion 5.0.0 schema here... I > use a non-XML format to help people mentally disassociate thinking about > the architectureId specific things from the current 4.0.0 way of doing > things > -- Sent from my phone
