[opensuse-packaging] Automated binary java packaging using maven central
I've written a successful prototype that does the following: * generates a completely functional .spec file based on the metadata of java artifacts (POM) that is available at Maven Central (http://repo1.maven.org/maven2/) * does *NOT* build from source but, instead, simply takes the .jar file from Maven Central and installs it into %{_javadir} (including the usual symlinks) * optionally also creates a subpackage with the source jar from Maven Central (very useful for IDEs such as Eclipse) * all that including dependencies, as far as they're declared in the POM file * written in Perl (hey, it's a prototype ;)), just one file, no exotic dependencies The script is there: https://gitorious.org/pbleser/pbleser/blobs/master/pom2spec Here's an example on how to run it: 1) pull the script and chmod it: cd ~/bin wget https://gitorious.org/pbleser/pbleser/blobs/raw/master/pom2spec chmod +x pom2spec 2) go to your OBS sandbox and create a new package: osc mkpac log4j-log4j-1_2_15 3) generate the .spec file, passing groupId artifactId and version: pom2spec log4j log4j 1.2.15 (if you don't specify the version, pom2spec will give you a list of possible versions, i.e. those that are available in Maven Central) 4) well, obviously, build it ;) osc build ... ===== The longer story... First of all, I guess that everyone knows by now that the packaging situation around Java libraries (and, hence, applications (desktop and server) that depend on those libraries) is ... let's say... suboptimal. It is very complex to build those from source as the build systems that are typically used for Java projects (Ant, Maven, Gradle, Ant+Ivy, ...) have a dependency management of their own that is quite difficult to integrate with RPM packaging. Stephen Shaw has been putting a lot of effort into doing it properly since some time and while he's made a lot of progress already, I think we're still far away from having a useful set of common Java libraries (there are gazillions of open source Java libraries and frameworks out there). Hence, I believe that having them as "bad" RPMs (because they're not built from source but just install the already compiled .jar files from Maven Central (hence upstream)) is better than not having them _at all_. Of course, starting from there, we should still continue to improve our tool set and experience with building Java packages from source, in order to replace at least some of those "bad" RPMs with "good" ones. The drawback is that we cannot add our own patches to the upstream sources, for obvious reasons. But the advantage of this approach is that it is very easy to build the RPMs. And, to be honest, I don't think that, in the past or in the future, we often need to add patches to portable Java source code that haven't been included upstream already. Sure, that doesn't work well with the typical policy for the distribution updates (backport patches instead of version bumps) but hey... better than nothing, don't you think ? ===== Now the interactive part... While writing the pom2spec script, a few questions or, rather, a need for some decisions, appeared. We probably can all agree that we should add Provides in those Java library packages in the same fashion as with Perl packages, along the lines of this: Provides: java(${groupId}:${artifactId}) = ${version} e.g.: Provides: java(org.springframework:spring-beans) = 2.5.6.SEC02 (the g:a and g:a:v notation is very commonly used in Java/Maven/Gradle/...) That would make it easier, more portable and clearly more future-proof in dependencies (Requires). But what I'm not sure about, at this point, is how to name the packages themselves. I believe we should use fully qualified ${groupId}-${artifactId} names, e.g.: Name: org.springframework.spring-beans ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^ ${groupId} ${artifactId} That (${ŋroupId}:${artifactId}) already is a unique and canonical name as of Maven Central, which is what 90%+ Java projects on the planet use (either through Maven, or Ant+Ivy, or Gradle, or ...). But that's too long for Joliet. Is that still an issue ? Another thing is that I believe that it would make our life easier if we also included the ${version} in the %{NAME} of the package, in order to be able to install several different versions of libraries side-by-side. That way we can always reflect upstream's dependencies as defined in their POM file (e.g. org.springframework:spring-beans:2.5.6.SEC02 requiring log4j:log4j:1.2.15). Example: Name: org.springframework.spring-beans-2_5_6_SEC02 Version: 2.5.6.SEC02 Yes, that's a pretty long package name alright. That would also mean dropping the symlink that drops the %{version} in %{_javadir}. Feedback please :) (And thanks for reading this far, I know this email is way too long, but I wanted to give enough background :)). cheers -- -o) Pascal Bleser /\ http://opensuse.org -- we haz green __v http://fosdem.org -- we haz conf
participants (4)
-
Adrian Schröter
-
Duncan Mac-Vicar P.
-
Pascal Bleser
-
Peter Linnell