单声道存储库的SBT构建结构

时间:2016-07-11 13:16:17

标签: scala sbt

我希望将SBT用于围绕具有数十个项目的单个Git存储库构建的构建。我希望从构建中获得以下可能性:

  1. 一键构建/测试/发布构建中的所有项目。
  2. 为构建中的所有项目定义和应用常用设置。
  3. 在项目子目录中定义项目特定的设置,保持构建的根目录清洁。
  4. 项目应该能够相互依赖,但是......
  5. 大多数项目在类路径意义上不会相互依赖。
  6. 某些项目将是应包含在其他项目中的SBT插件(但不包括所有项目)。
  7. 现在考虑到这些要求,构建的结构应该是什么?由于要求3,我不能在构建的根目录中使用单个build.sbt,因为我不想将所有项目设置放在那里,因为它会很多文本,并且单个项目中的每个更改都将反映在顶层。

    我还听说根项目和子项目的*.sbt文件的使用容易出错,一般不推荐(Producing no artifact for root project with package under multi-project build in SBTHow can I use an sbt plugin as a dependency in a multi-project build?,{ {3}}等。我只尝试了在不同级别上使用*.sbt文件的简单多项目构建,它只是起作用。考虑到上述要求,如果我采用多*.sbt文件方法,我需要记住哪些陷阱?

1 个答案:

答案 0 :(得分:4)

好的,因为到目前为止还没有人发布任何内容,我发现我发布了迄今为止我从SBT单声道存储库中学到的内容。

首先是一些事实:我们的SBT构建包括40多个项目,10个以上的共同项目(在其他项目依赖于它们的意义上),以及与单个产品相关的5组项目(每个项目中有5-7个项目)组)。在每个小组中,通常只有一个小组共同项目。

构建组织

我们有以下构建结构:

  1. 整个版本的一个主要build.sbt
  2. 每个项目一个build.sbt
  3. project目录中的几个本地SBT插件。
  4. 让我们谈谈这些项目。

    1。主要build.sbt

    在此文件中,定义了常规构建结构。也就是说,我们在那里保持跨项目依赖。我们使用标准commonSettings方法,如:

    val commonSettings = Seq(scalaVersion := "2.12.3", ...)
    ...
    val proj1 = (project in file("p1")).settings(commonSettings)
    val proj2 = (project in file("p2")).settings(commonSettings)
    ...
    

    这对于一个新项目来说太过冗长而容易出错。相反,我们使用一个本地SBT项目,该项目自动应用于构建中的每个项目(稍后将详细介绍)。

    2。每个项目build.sbt

    在这些文件中,我们通常定义所有项目设置(非自动插件,库依赖项等)。我们在这些文件中定义跨项目依赖项,因为这并不像预期的那样真正起作用。 SBT按特定顺序加载所有*.sbt个文件,每个构建中的项目定义都会覆盖以前找到的文件。换句话说,如果您避免(重新)在每个项目*.sbt文件中定义项目,那么事情就会很好。所有其他设置都可以保留在那里,以避免在主build.sbt中出现过多的混乱。

    3。本地SBT插件

    我们使用技巧在<root_dir>/project/目录中定义SBT自动插件,并使它们自动加载到构建中的所有项目。我们使用这些插件自动定义所有项目的设置和任务(适用于Scalastyle,scalafmt,Sonar,部署等)。我们还在那里保持常见设置(scalaVersion等)。我们在<root_dir>/project/中保留的另一件事是常见的依赖版本(不是插件,只是纯*.scala文件)。

    摘要

    将SBT用于单声道存储库似乎有效,并且具有某些优点和缺点。

    优势:在产品之间重复使用代码非常容易。此外,Scalastyle,scalafmt等常见的SBT内容定义一次,所有新项目都免费获得。升级依赖版本在一个地方为所有项目完成,因此当有人升级版本时,他或她会立即为所有项目执行此操作,以便不同的团队从中受益。这需要团队之间的某些纪律,但到目前为止它对我们有用。

    另一个优点是使用通用工具。我们有一个Gerrit + Jenkins持续集成,我们只有一个工作,例如提交前验证。新项目再次免费获得了很多这种机器。

    缺点:一,构建加载时间。在前13名&#34; MacBook Pro它可以轻松持续30秒以上(这是从启动SBT到达SBT&#39命令提示符的时间)。如果你能保持SBT不断运转,这并不是那么糟糕。 Intellij刷新构建信息会更糟糕,它可能需要大约15 分钟。我不知道为什么它需要的时间比SBT要长得多,但就是这样。除非绝对必要,否则可以通过避免刷新Intellij来缓解,但这真的很痛苦。

    另一个问题是,您无法将单个项目或项目组加载到Intellij IDEA中。您被迫加载整个单声道存储库的构建。如果那是可能的话,那么,我猜,Intellij的情况可能会更好。

    另一个缺点是,不能为不同的项目使用不同版本的相同SBT插件。当一个项目由于某种原因无法升级到新的插件版本时,整个存储库必须等待。有时这很有用,也就是说,它可以加快维护工作,并迫使我们将项目保持在维护模式中。但有时对于遗留项目而言,这可能具有挑战性。

    结论

    总而言之,我们在这种模式下工作了大约一年,我们打算在可预见的未来继续这样做。我们担心的是Intellij IDEA刷新时间长,而且随着我们在此版本中添加更多项目,情况会变得更糟。我们稍后可能会评估替代构建系统,以避免我们单独加载项目以帮助Intellij性能,但SBT似乎可以完成任务。