harrah/xsbt — Issue #295: Allow "Compatible" Scala Versions in Cross-Build Mechanism
Author: djspiewak
Created: 2011-12-11 17:41:46+00:00
State: open

Cross-builds are a lovely hack that do a very good job of resolving many of the common cases of Scala version incompatibilities across dependencies. Unfortunately, they also couple libraries together in a very unpleasant way. This is particularly apparent when a new version of Scala lands and the entire community needs to perform a topological walk of their libraries, pushing new cross-builds. Projects that are dependencies for numerous other projects (think: Specs and ScalaCheck) become blockers for the entire community, since no one can push an updated cross-build for their own library before their dependencies. This has given rise to an extremely common pattern of dependency specification, where a project will use the cross-build artifact id for a particular library, but only for certain versions of Scala, using a custom id for other version (generally the latest one).

In theory, minor releases of Scala are now backwards compatible. Thus, cross-builds that were built against 2.9.0 *should* be compatible with dependant libraries being built against 2.9.1 (and vice versa). We certainly can't guarantee this in general, but it's a safe rule of thumb. In any case, it should be possible to take advantage of this fact without having to manually override cross-build artifact identifiers.

I am proposing a new property, `compatibleScalaVersions` of type `Seq[String]`. This property would default to simply `Seq(scalaVersion)` for backwards compatibility with prior SBT semantics. The functionality of this property would be visible in the cross-build semantics. Specifically, if the value of `scalaVersion` is `"2.9.1"` and the project is dependent on some artifact `foo` that has a cross-build for `2.9.0` but not `2.9.1`, a build could specify `compatibleScalaVersion += "2.9.0"` and the cross-build of `foo` for `2.9.0` would be selected in lieu of a more specific cross-build for `2.9.1`. When a cross-build for `scalaVersion` is available, it will always be selected. Otherwise, SBT should attempt to resolve cross-builds for each value in `compatibleScalaVersions` in order. This would give library and project authors a controlled and declarative way of specifying compatible Scala versions, effectively relaxing the (currently lexical) constraints of cross-build resolution.

There are some issues here, such as the fact that `compatibleScalaVerions` includes `scalaVersion`, which makes the fallback semantics a little strange. It might be better to just implicitly assume that `scalaVersion` will *always* be tried first, defaulting `compatibleScalaVersions` to `Seq()`.