简体   繁体   English

带有子模块和多个Scala版本的sbt

[英]sbt with sub-modules and multiple scala versions

I'm building a scala applications with these module and dependencies : 我正在使用这些模块和依赖项构建一个scala应用程序:

  • a shared lib "common" 共享库“常见”
  • module "A" depends on "common" and can be built in scala 2.10 only 模块“ A”取决于“ common”,只能在scala 2.10中构建
  • module "B" depends on "common" and can be built in scala 2.11+ only 模块“ B”取决于“ common”,只能在scala 2.11+中构建

I'm trying to have all the 3 modules in a single sbt build : 我正在尝试在单个sbt构建中包含所有3个模块:

import sbt._
import Keys._

lazy val root = (project in file("."))
                .aggregate(common, A, B)

lazy val common = (project in file("common"))

lazy val A = (project in file("A"))
             .dependsOn(common)

lazy val B = (project in file("B"))
             .dependsOn(common)

I've read things about crossScalaVersions, but whatever combination I try in root build, or in common, etc, I can't manage to make this work properly. 我已经阅读了有关crossScalaVersions的内容,但是无论我在root用户构建中尝试使用哪种组合,或在通用环境中尝试使用哪种组合,我都无法设法使其正常运行。

Any clue ? 有什么线索吗? I'm using sbt 0.13.8 by the way. 顺便说一下,我正在使用sbt 0.13.8。

In my experience sbt multi-module builds are quite finicky to get to work reliably if you require any extra hoops to jump through such as this requirement. 以我的经验,如果您需要诸如此类的要求来跳过任何多余的圈,则sbt多模块构建很难可靠地工作。

Have you considered the simpler way to achieve this: 您是否考虑过实现此目的的更简单方法:

  • publish your common dependency ( sbt publish-local if you only need to access it yourself) 发布您的公共依赖项(如果您只需要自己访问它, sbt publish-local
  • make two projects A and B 做两个项目A和B
  • make both A and B import common as a dependency 使A和B导入均作为依赖项

Using bare sbt this might not be possible. 使用裸露sbt可能无法实现。

An example build.sbt file representing such situation: 代表这种情况的示例build.sbt文件:

lazy val common = (project in file("common"))
                  .settings(crossScalaVersions := Seq("2.10.6", "2.11.8"))

lazy val A = (project in file("A"))
             .settings(scalaVersion := "2.10.6")
             .dependsOn(common)

lazy val B = (project in file("B"))
             .settings(scalaVersion := "2.11.8")
             .dependsOn(common)

This will work just fine. 这样就可以了。

Now. 现在。 A compilation of any project leads to a creation of a package. 任何项目的编译都会导致包的创建。 Even for the root . root If you follow the console, at some point it says: 如果您遵循控制台,则它会在某些时候显示:

Packaging /project/com.github.atais/target/scala-2.10/root_2.10-0.1.jar

So as you see sbt needs to decide on some Scala version, just to build this jar! 因此,如您所见, sbt需要决定某些Scala版本,只是为了构建此jar! That being said your projects A and B must have a common Scala version so they can be aggregated in a common project root . 话虽如此,您的项目AB 必须具有公共的Scala版本,以便可以将它们聚合到公共项目的root

Therefore, you can't have: 因此, 您不能:

lazy val root = (project in file("."))
                .aggregate(common, A, B)

if they do not share any Scala version they could be built with. 如果他们不共享任何Scala版本,则可以使用它们来构建。

But... sbt-cross to the rescue 但是... sbt-cross来了

You can use sbt-cross plugin to help you out. 您可以使用sbt-cross插件来帮助您。

In project/plugins.sbt , add project/plugins.sbt ,添加

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

And define your build.sbt in a following way: 并通过以下方式定义build.sbt

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

lazy val common_2_11 = common("2.11.8")
lazy val common_2_10 = common("2.10.6")

lazy val A = (project in file("A"))
             .settings(scalaVersion := "2.10.6")
             .dependsOn(common_2_10)

lazy val B = (project in file("B"))
             .settings(scalaVersion := "2.11.8")
             .dependsOn(common_2_11)

lazy val root = (project in file("."))
                .aggregate(common, A, B)

And then it works :-)! 然后就可以了:-)!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM