Кросс-версии SBT Scala, с агрегацией и зависимостями
Я борюсь с тем, как crossScalaVersions
работает с подпроектами.
У меня есть проект, который компилируется с 2.10 (foo) и проект, который компилируется с 2.11 (bar). Они разделяют кросс-скомпилированный проект (общий).
Как мне скомпилировать проекты foo и bar?
build.sbt
lazy val root = (project in file(".")).aggregate(foo, bar).settings(
crossScalaVersions := Seq("2.10.4", "2.11.4")
)
lazy val foo = (project in file("foo")).dependsOn(common).settings(
crossScalaVersions := Seq("2.10.4"),
scalaVersion := "2.10.4"
)
lazy val bar = (project in file("bar")).dependsOn(common).settings(
crossScalaVersions := Seq("2.11.4"),
scalaVersion := "2.11.4"
)
lazy val common = (project in file("common")).settings(
crossScalaVersions := Seq("2.10.4", "2.11.4")
)
проект / build.properties
sbt.version=0.13.7
Foo / SRC / Основной / Scala / Foo.scala
object Foo {
<xml>{new C}</xml>
}
бар / SRC / главная / Скала / Bar.scala
case class Bar(a: C, b: C, c: C, d: C, e: C, f: C, g: C,
h: C, i: C, j: C, k: C, l: C, m: C, n: C, o: C, p: C,
q: C, r: C, s: C, t: C, u: C, v: C, w: C, x: C, y: C,
z: C)
общий / SRC / основной / Scala / Common.scala
class C {}
Попытка 1
$ sbt compile
[info] Resolving jline#jline;2.12 ...
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: UNRESOLVED DEPENDENCIES ::
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: common#common_2.11;0.1-SNAPSHOT: not found
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn]
[warn] Note: Unresolved dependencies path:
[warn] common:common_2.11:0.1-SNAPSHOT
[warn] +- bar:bar_2.11:0.1-SNAPSHOT
sbt.ResolveException: unresolved dependency: common#common_2.11;0.1-SNAPSHOT: not found
Попытка 2
$ sbt +compile
[error] /home/paul/test/bar/src/main/scala/Bar.scala:1: Implementation restriction: case classes cannot have more than 22 parameters.
[error] case class Bar(a: C, b: C, c: C, d: C, e: C, f: C, g: C,
[error] ^
[error] one error found
[error] (bar/compile:compile) Compilation failed
Попытка 3
$ sbt foo/compile bar/compile
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: UNRESOLVED DEPENDENCIES ::
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: common#common_2.11;0.1-SNAPSHOT: not found
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn]
[warn] Note: Unresolved dependencies path:
[warn] common:common_2.11:0.1-SNAPSHOT
[warn] +- bar:bar_2.11:0.1-SNAPSHOT
sbt.ResolveException: unresolved dependency: common#common_2.11;0.1-SNAPSHOT: not found
Попытка 4
$ sbt +foo/compile +bar/compile
[error] /home/paul/test3/foo/src/main/scala/Foo.scala:2: To compile XML syntax, the scala.xml package must be on the classpath.
[error] Please see http://docs.scala-lang.org/overviews/core/scala-2.11.html#scala-xml.
[error] <xml>{new C}</xml>
[error] ^
[error] one error found
[error] (foo/compile:compile) Compilation failed
Попытка 5
Я даже пытался определить common_2_10
а также common_2_11
проекты с тем же базовым каталогом, но с разными версиями Scala. Я помню, что читал, что цели имеют пространство имен по версии Scala, но SBT говорит, что существует конфликт.
$ sbt
[error] Overlapping output directories:/home/paul/test3/common/target:
[error] ProjectRef(file:/home/paul/test3/,common_2_10)
[error] ProjectRef(file:/home/paul/test3/,common_2_11)
Единственное, что мне удалось - это указать версии вручную:
$ sbt ++2.10.4 foo/compile ++2.11.4 bar/compile
Но это много команд, они никогда не могут использовать параллелизм и исключают полное использование (1) агрегации проектов и (2) перекрестного построения.
Я что-то упускаю из-за намерения crossScalaVersions
? Или есть способ заставить его играть хорошо с остальной частью SBT, и для меня, чтобы собрать мои разнородные проекты?
2 ответа
Я в итоге объявил общее дважды, по одному разу для каждой версии.
lazy val root = (project in file(".")).aggregate(foo, bar)
lazy val foo = (project in file("foo")).dependsOn(common_2_10).settings(
scalaVersion := "2.10.4"
)
lazy val bar = (project in file("bar")).dependsOn(common_2_11).settings(
scalaVersion := "2.11.4"
)
def commonProject = (project in file("common")).settings(
target := baseDirectory.value / s"target-${scalaVersion.value}"
)
lazy val common_2_10 = commonProject.settings(
scalaVersion := "2.10.4"
)
lazy val common_2_11 = commonProject.settings(
scalaVersion := "2.11.4"
)
Обратите внимание, что я должен был сделать целевые каталоги другими, иначе SBT отклонит его, потому что они перекрываются.
Также обратите внимание, что def
марки commonProject
не включает волшебный (основанный на отражении) поиск SBT для определения проекта.
Это не самый красивый, но надежный, читаемый и разумный. Все команды / задачи работают так, как можно было бы ожидать.
С одной стороны, это даже лучше, чем crossScalaVersions
в этом 2.10 и 2.11 проекты теперь могут быть скомпилированы параллельно, что не происходит с crossScalaVersions
:)
РЕДАКТИРОВАТЬ: я создал плагин SBT, sbt-cross, чтобы помочь с этим.
Проверьте мой sbt-doge:
плагин sbt для агрегирования задач по подпроектам и их кросс-фалам