When upgrading our build from 12.4 to 13.1 I observed that although the build specified scalaVersion := "2.10.2"
, the resulting archive (created via the sbt-pack plugin) contained scala-library-2.10.3.jar. A quick check confirmed that the 12.4 build was including scala-library-2.10.2.jar.
It appears that sbt 0.13 included a change to treat the scala libraries as normal dependencies, with the consequence that if a project dependency was built with a later 2.10.x version of scala then that transitive dependency will "win" the ivy dependency resolution conflict resolution, and the compile, test and run classpaths will contain the later version of scala libraries.
Is this the desired behavior, or a bug in sbt 0.13?
If the desired behavior, then does that mean I have to use the mechanisms to "force/override" the conflict resolution to use my desired version of the scala libraries? (If so, the scalaVersion configuration setting seems a bit pointless....)
Here is an extremely minimal test case to illustrate the behavior:
test-proj/
build.sbt
project/
build.properties
build.sbt:
scalaVersion := "2.10.2"
//scalaVersion := "2.10.3"
libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.3.0"
//libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.2.4"
build.properties:
sbt.version=0.13.1
Akka 2.2.4 was built against scala 2.10.2, so firing up sbt and running "update", "show update", "show compile:dependencyClasspath", "show test:dependencyClasspath" and "show runtime:dependencyClasspath" all show scala-library 2.10.2 on the classpath.
Switching to Akka 2.3.0, which was built against scala 2.10.3, results in scala-library 2.10.3 appearing on all the classpaths, and "show update" clearly shows 2.10.2 being evicted by Ivy's conflict resolution.
Interestingly (and inconsistently), entering the REPL in both cases (via the sbt console command) results in scala 2.10.2 being utilized.
According to the docs, in sbt 0.13
The scalaVersion configures the version of Scala used for compilation. By default, sbt also adds a dependency on the Scala library with this version.
Based on that, I would expect the compilation classpath above to include 2.10.2 in both circumstances.
However, the release notes for 0.13 say
Scala dependencies (like scala-library and scala-compiler) are now resolved via the normal update task
which does at least explain the observed behavior.
You wrote:
It appears that sbt 0.13 included a change to treat the scala libraries as normal dependencies, with the consequence that if a project dependency was built with a later 2.10.x version of scala then that transitive dependency will "win" the ivy dependency resolution conflict resolution, and the compile, test and run classpaths will contain the later version of scala libraries.
sbt 0.13.0 Changes has somewhat conflicting note on this issue. Features, fixes, changes with compatibility implications section says:
- sbt no longer overrides the Scala version in dependencies. This allows independent configurations to depend on different Scala versions and treats Scala dependencies other than scala-library as normal dependencies. However, it can result in resolved versions other than scalaVersion for those other Scala libraries.
Resolving Scala dependencies section says:
Scala dependencies (like scala-library and scala-compiler) are now resolved via the normal
update
task.
(Emphasis added by Eugene) So the quick answer to your "Is this the desired behavior, or a bug in sbt 0.13?" as you've already answered yourself is: In sbt 0.13.x, this behavior seems to be intended. Akka 2.3.0 depends on scala-library 2.10.3, and Ivy has evicted scala-library 2.10.2 in favor of 2.10.3.
To workaround this, you can use dependencyOverrides
setting as follows:
dependencyOverrides += "org.scala-lang" % "scala-library" % scalaVersion.value
Before:
sbt-so-22551430> show fullClasspath
[info] List(... Attributed(/Users/xxx/.sbt/0.13/boot/scala-2.10.3/lib/scala-library.jar) ...)
After:
sbt-so-22551430> show fullClasspath
[info] List(... Attributed(/Users/xxx/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.10.2.jar) ...)
Your question was not whether if this is by design, but if this is desirable. I think the current behavior is quite surprising, and sbt should at least improve on notifying the build users of this behavior. And perhaps change its default Ivy conflict management policy to force()
the version specified in scalaVersion
. Here are two GitHub issues I created:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With