SBT - 使用程序集

时间:2016-09-07 13:22:45

标签: scala sbt sbt-assembly

我有一个由多个较小项目组成的项目,其中一些项目彼此依赖,例如,有一个依赖于commons项目的实用程序项目。 其他项目可能会也可能不依赖于公用事业或公共场所,或者两者都不依赖。

在build.sbt中,我在文件末尾有汇编合并策略,汇编中的测试为{}。

我的问题是:如果每个项目都有自己的合并策略,这是正确的吗?如果是这样,依赖它的其他项目是否会从它们继承这个策略?将所有项目定义中包含的合并策略看起来很笨拙,并且意味着需要重复代码。

这个问题也适用于测试,如果每个项目都有关于是否应该进行测试的线,还是会继承测试?

提前致谢。如果有人知道一个明智的(相对复杂的)例子的链接,那也很棒。

1 个答案:

答案 0 :(得分:9)

在我的日常工作中,我目前正在从事一个大型的多项目。不幸的是它的封闭源代码因此我无法分享具体内容,但我可以分享一些指导。

  1. 创建仅由root / container项目使用的rootSettings,因为它通常不是程序集或发布步骤的一部分。它将包含类似的内容:

    lazy val rootSettings := Seq(
      publishArtifact := false,
      publishArtifact in Test := false
    )
    
  2. 创建所有子项目共享的commonSettings。将基础/共享装配设置放在此处:

    lazy val commonSettings := Seq(
    
      // We use a common directory for all of the artifacts
      assemblyOutputPath in assembly := baseDirectory.value /
        "assembly" / (name.value + "-" + version.value + ".jar"),
    
      // This is really a one-time, global setting if all projects
      // use the same folder, but should be here if modified for
      // per-project paths.
      cleanFiles <+= baseDirectory { base => base / "assembly" },
    
      test in assembly := {},
    
      assemblyMergeStrategy in assembly := {
        case "BUILD" => MergeStrategy.discard
        case "logback.xml" => MergeStrategy.first
        case other: Any => MergeStrategy.defaultMergeStrategy(other)
      },
    
      assemblyExcludedJars in assembly := {
        val cp = (fullClasspath in assembly).value
        cp filter { _.data.getName.matches(".*finatra-scalap-compiler-deps.*") }
      }
    )
    
  3. 每个子项目使用commonSettings,并应用项目特定的覆盖:

    lazy val fubar = project.in(file("fubar-folder-name"))
      .settings(commonSettings: _*)
      .settings(
        // Project-specific settings here.
        assemblyMergeStrategy in assembly := {
          // The fubar-specific strategy
          case "fubar.txt" => MergeStrategy.discard
          case other: Any =>
            // Apply inherited "common" strategy
            val oldStrategy = (assemblyMergeStrategy in assembly).value
            oldStrategy(other)
        }
      )
      .dependsOn(
        yourCoreProject,
        // ...
      )
    
  4. BTW,如果使用IntelliJ。不要命名根项目变量root,因为这是最近项目菜单中显示的项目名称。

    lazy val myProjectRoot = project.in(file("."))
      .settings(rootSettings: _*)
      .settings(
        // ...
      )
      .dependsOn(
        // ...
      )
      .aggregate(
        fubar,
        // ...
      )
    
  5. 您可能还需要添加自定义策略以组合reference.conf个文件(对于Typesafe配置库):

    val reverseConcat: sbtassembly.MergeStrategy = new sbtassembly.MergeStrategy {
      val name = "reverseConcat"
      def apply(tempDir: File, path: String, files: Seq[File]): Either[String, Seq[(File, String)]] =
        MergeStrategy.concat(tempDir, path, files.reverse)
    }
    
    assemblyMergeStrategy in assembly := {
      case "reference.conf" => reverseConcat
      case other => MergeStrategy.defaultMergeStrategy(other)
    }
    
相关问题