SBT - 使用汇编时多项目合并策略和构建 sbt 结构 [英] SBT - Multi project merge strategy and build sbt structure when using assembly

查看:39
本文介绍了SBT - 使用汇编时多项目合并策略和构建 sbt 结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个由多个较小项目组成的项目,其中一些项目相互依赖,例如,有一个实用程序项目依赖于公共项目.其他项目可能依赖也可能不依赖于公用事业或公共资源,或者两者都不依赖.

I have a project that consists of multiple smaller projects, some with dependencies upon each other, for example, there is a utility project that depends upon commons project. Other projects may or may not depend upon utilities or commons or neither of them.

在 build.sbt 中,文件末尾有程序集合并策略,程序集中的测试为 {}.

In the build.sbt I have the assembly merge strategy at the end of the file, along with the tests in assembly being {}.

我的问题是:这是正确的,每个项目都应该有自己的合并策略吗?如果是这样,依赖它的其他项目是否会从他们那里继承这个策略?将合并策略包含在所有项目定义中似乎很笨拙,并且意味着大量重复代码.

My question is: is this correct, should each project have its own merge strategy and if so, will the others that depend on it inherit this strategy from them? Having the merge strategy contained within all of the project definitions seems clunky and would mean a lot of repeated code.

这个问题也适用于测试,每个项目是否应该有测试是否应该进行,或者也可以继承?

This question applied to the tests as well, should each project have the line for whether tests should be carried out or not, or will that also be inherited?

提前致谢.如果有人知道一个指向合理(相对复杂)示例的链接,那也很棒.

Thanks in advance. If anyone knows of a link to a sensible (relatively complex) example that'd also be great.

推荐答案

在我的日常工作中,我目前正在处理一个大型的多项目.不幸的是,它是封闭的源代码,所以我无法分享具体细节,但我可以分享一些指导.

In my day job I currently work on a large multi-project. Unfortunately its closed source so I can't share specifics, but I can share some guidance.

  1. 创建一个仅由根/容器项目使用的 rootSettings,因为它通常不是程序集或发布步骤的一部分.它将包含以下内容:

  1. Create a rootSettings used only by the root/container project, since it usually isn't part of an assembly or publish step. It would contain something like:

lazy val rootSettings := Seq(
  publishArtifact := false,
  publishArtifact in Test := false
)

  • 创建一个所有子项目共享的commonSettings.将基本/共享程序集设置放在这里:

  • Create a commonSettings shared by all the subprojects. Place the base/shared assembly settings here:

    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.*") }
      }
    )
    

  • 每个子项目都使用 commonSettings,并应用特定于项目的覆盖:

  • Each subproject uses commonSettings, and applies project-specific overrides:

    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,
        // ...
      )
    

  • 顺便说一句,如果使用 IntelliJ.不要将您的根项目变量命名为 root,因为这是最近项目菜单中显示的项目名称.

  • And BTW, if using IntelliJ. don't name your root project variable root, as this is what appears as the project name in the recent projects menu.

    lazy val myProjectRoot = project.in(file("."))
      .settings(rootSettings: _*)
      .settings(
        // ...
      )
      .dependsOn(
        // ...
      )
      .aggregate(
        fubar,
        // ...
      )
    

  • 您可能还需要添加用于组合 reference.conf 文件的自定义策略(用于类型安全配置库):

    You may also need to add a custom strategy for combining reference.conf files (for the Typesafe Config library):

    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)
    }
    

    这篇关于SBT - 使用汇编时多项目合并策略和构建 sbt 结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆