15

I have a project using Scala 2.10 and one using Scala 2.11. They depend on a common project, which can compile with both.

lazy val foo = (project in file("foo")).dependsOn(baz).settings(
  scalaVersion := "2.10.4"
)

lazy val bar = (project in file("bar")).dependsOn(baz).settings(
  scalaVersion := "2.11.4"
)

lazy val baz = (project in file("baz")).settings(
  crossScalaVersions := Seq("2.10.4", "2.11.4"),
  scalaVersion := "2.10.4"
)

And then

$ sbt bar/update
[info] Updating {file:/home/paul/Private/test/}bar...
[info] Resolving baz#baz_2.11;0.1-SNAPSHOT ...
[warn]  module not found: baz#baz_2.11;0.1-SNAPSHOT
[warn] ==== local: tried
[warn]   /home/paul/.ivy2/local/baz/baz_2.11/0.1-SNAPSHOT/ivys/ivy.xml
[warn] ==== public: tried
[warn]   http://repo1.maven.org/maven2/baz/baz_2.11/0.1-SNAPSHOT/baz_2.11-0.1-SNAPSHOT.pom
[info] Resolving jline#jline;2.12 ...
[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[warn]  ::          UNRESOLVED DEPENDENCIES         ::
[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[warn]  :: baz#baz_2.11;0.1-SNAPSHOT: not found
[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[trace] Stack trace suppressed: run last bar/*:update for the full output.
[error] (bar/*:update) sbt.ResolveException: unresolved dependency: baz#baz_2.11;0.1-SNAPSHOT: not found
[error] Total time: 1 s, completed Jan 13, 2015 11:42:51 AM

How can I have baz usable by both projects?

Paul Draper
  • 78,542
  • 46
  • 206
  • 285
  • 1
    Have you tried the `crossPaths := false` option, to ignore scala versions at all? – eugen-fried Jan 26 '15 at 09:03
  • There is a chance that you'll have some comparability issues (not 100%), but to be honest your situation smells bad anyways; so I would suggest this as a temporary fix, until you make *foo* and *baz* use 2.11.4 both. – eugen-fried Jan 26 '15 at 11:15

3 Answers3

10

Yevgeniy Mordovkin's proposed solution, to declare crossPaths := false in the baz project, works.

Another thing you might do, is to prepend a + before the command: sbt '+ bar/update'. That will build baz for all declared Scala versions.

Ionuț G. Stan
  • 176,118
  • 18
  • 189
  • 202
  • Thanks. **(1)** Will `crossPaths` cause problems, as Scala minor versions are not binary compatible? **(2)** It seems for `+` to work, I also need to add `crossVersions` to `bar`, and switch projects with `project bar` and then `+update` (instead of `+bar/update`), otherwise it uses 2.10. – Paul Draper Jan 26 '15 at 09:52
  • @PaulDraper no need to add `crossScalaVersions` to `bar`. What you have to do is set the `settings` before declaring `dependsOn`: `lazy val bar = (project in file("bar")).settings(scalaVersion := "2.11.4").dependsOn(baz)`. – Ionuț G. Stan Jan 26 '15 at 10:42
  • @PaulDraper you can use `update` without a preceding `+` inside `bar` as long as you've already compiled `baz` for all declared versions. – Ionuț G. Stan Jan 26 '15 at 10:43
  • 3
    @PaulDraper and yes, setting `crossPaths := false` might cause problems down the line, so you're better off not using it. – Ionuț G. Stan Jan 26 '15 at 10:44
  • @IonuțG.Stan Unfortunately, putting `settings` before `aggregate` in the same way doesn't seem to work. Is it expected to? See http://stackoverflow.com/questions/27231293/cross-compiling-aggregate-projects-with-different-crossscalaversions-for-subproj and https://github.com/scalan/scalan-ce/tree/include-lms-backend-in-root – Alexey Romanov Feb 09 '15 at 07:05
4

I created an SBT plugin for this.

project/plugins.sbt

resolvers += Resolver.sonatypeRepo("releases")

addSbtPlugin("com.lucidchart" % "sbt-cross" % "1.0")

build.sbt

lazy val foo = (project in file("foo")).dependsOn(baz_2_10).settings(
  scalaVersion := "2.10.4"
)

lazy val bar = (project in file("bar")).dependsOn(baz_2_11).settings(
  scalaVersion := "2.11.5"
)

lazy val baz = (project in file("baz")).cross

lazy val baz_2_10 = baz("2.10.4")

lazy val baz_2_11 = baz("2.11.5")

It takes a couple more lines, but now everything compiles as expected: sbt foo/compile works, and sbt bar/compile works.

You don't have to remember unique commands, you don't have bugs from crossPath := false, and unlike ++, this is parallelizable: sbt compile will compile foo, bar, and baz with the correct Scala versions concurrently.

Paul Draper
  • 78,542
  • 46
  • 206
  • 285
1

I had a similar setup, and got it work like so:

lazy val baz = (project in file("baz")).settings(
  crossScalaVersions := Seq("2.10.4", "2.11.4")
)
lazy val bar = (project in file("bar")).dependsOn(baz).settings(
  scalaVersion := "2.10.4"
)
lazy val foo = (project in file("foo")).dependsOn(baz).settings(
  scalaVersion := "2.11.4"
)

And building with

sbt '++ 2.10.4 baz/compile' 'bar/compile' '++ 2.11.4 baz/compile' 'foo/compile'
poroszd
  • 592
  • 4
  • 12