Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do scala maven artifacts have an artifact for each scala version instead of a classifier per scala version?

Since you have only source compatibility between Scala-versions you unfortunately need to compile libraries like scalatest or scalamock for each scala version they support. What puzzles me is that the libraries are provided with loads of artifacts (scalatest_2.9.0, scalatest_2.9.1, scalatest_2.10 and so forth) - one for each scala version, such that the maven repository is littered with many artefacts that are built from the same source. My instinct tells me rather to use one artifact with a classifier for each scala version. (In fact, the maven pom reference mentions that this was sometimes done with jdk14 and jdk15 classifiers for artifacts, which seems similar to me.) So, why did the Scala people go for the many artifact overkill :-) instead?

like image 905
Hans-Peter Störr Avatar asked Feb 26 '13 19:02

Hans-Peter Störr


1 Answers

I may be wrong, but if a classifier's purpose is to "distinguish artifacts that were built from the same POM but differ in their content", then I see a very good reason not to use them for scala versioning: scala versions are not just binary incompatible, they can very well be source incompatible. By example, when upgrading scala from 2.7 to 2.8, I had to make some significant changes to the code base. If I wanted to keep both a scala 2.7 and 2.8 version at the same time, I would have needed to create a parallel branch, and both branches would definitely not have the same source code.

When I read "from the same POM", I understand that it means from the same source code too, which would clearly not be the case with those two branches of code.

Another more important reason is that a classifier is essentially a single string, which is already used for many things. More or less standard classifiers include "sources", "javadoc" or "resources". The meanings of these classifiers are the same in scala project, and are totally orthogonal to the scala version, as I'll try to show.

Maven's documentation suggests using classifiers such as "jdk15" or "jdk14" to denote which version of the jvm the binary artifact was compiled against. Given that java code is backward compatible, in principle the artifacts with both classifiers ("jdk15" or "jdk14") are compiled from the same source code. This is why you don't need to duplicate classifiers for "sources" artifact, or in other words you don't need to have a classifier named "sources-jdk14" and "sources-jdk15". But you cannot apply the same rationale to the scala version: given that you might need different source code whether you compile against scala 2.7 or scala 2.8, you would indeed need two different artifacts with classifiers such as "sources-scala2.7" or "source-scala2.8". So we have composite classifiers already. As for binary artifacts, you would also not only need to distinguish between the target jvm version (remember, you can compile your scala code to target different jvm versions) but also the scala version it was compiled against. So you would end up with something like "jdk14-scala2.7" or "jdk14-scala2.8" or "jdk15-scala2.7" or "jdk15-scala2.8". Yet another set of composite classifiers. So the take home message is that the scala version really is a separate way of classifying artifacts, that is totally orthognal to all the existing classifiers. Yes, we could really use composite classifiers as above (such as "sources-scala2.7") but then we would not be using standard classifiers, which is confusing enough in itself, but would also require to modify all the tooling around classifiers: what if I use a build tool that has no knowledge of scala (only java) but knows how to automatically publish a "source" artifact? Will I need to modify this build tool so that he knows to publish a "sources-scala2.7" artifact instead? On the other hand, if I encode the scala version in the (base) artifact name and give that to the build tool, everything works as usual and I get a an artifact with the "source" classifier.

All in all, and contrary to immediate intuition, encoding the scala version in the name allows for better integration in the existing java build ecosystem.

like image 166
Régis Jean-Gilles Avatar answered Oct 13 '22 01:10

Régis Jean-Gilles