SBT - 使用程序集时的多项目合并策略和构建 sbt 结构
SBT - Multi project merge strategy and build sbt structure when using assembly
我有一个由多个较小的项目组成的项目,其中一些项目相互依赖,例如,有一个实用项目依赖于 commons 项目。
其他项目可能依赖也可能不依赖公用事业或公共设施,或者两者都不依赖。
在 build.sbt 中,我在文件末尾有程序集合并策略,以及程序集中的测试 {}。
我的问题是:这是正确的吗,每个项目都应该有自己的合并策略吗?如果是这样,依赖它的其他人会从他们那里继承这个策略吗?将合并策略包含在所有项目定义中似乎很笨重,并且意味着大量重复代码。
这个问题也适用于测试,每个项目是否应该有关于是否应该进行测试的行,还是也会被继承?
提前致谢。如果有人知道 link 到一个合理(相对复杂)的例子,那也很好。
在我的日常工作中,我目前正在处理一个大型的多项目。不幸的是它是闭源的,所以我不能分享细节,但我可以分享一些指导。
创建一个仅供 root/container 项目使用的 rootSettings
,因为它通常不是组装或发布步骤的一部分。它将包含如下内容:
lazy val rootSettings := Seq(
publishArtifact := false,
publishArtifact in Test := false
)
创建一个由所有子项目共享的commonSettings
。将 base/shared 程序集设置放在这里:
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
,并应用项目特定的覆盖:
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
,因为这是在最近的项目菜单中显示的项目名称。
lazy val myProjectRoot = project.in(file("."))
.settings(rootSettings: _*)
.settings(
// ...
)
.dependsOn(
// ...
)
.aggregate(
fubar,
// ...
)
您可能还需要添加自定义策略来组合 reference.conf
文件(对于 Typesafe Config 库):
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)
}
我有一个由多个较小的项目组成的项目,其中一些项目相互依赖,例如,有一个实用项目依赖于 commons 项目。 其他项目可能依赖也可能不依赖公用事业或公共设施,或者两者都不依赖。
在 build.sbt 中,我在文件末尾有程序集合并策略,以及程序集中的测试 {}。
我的问题是:这是正确的吗,每个项目都应该有自己的合并策略吗?如果是这样,依赖它的其他人会从他们那里继承这个策略吗?将合并策略包含在所有项目定义中似乎很笨重,并且意味着大量重复代码。
这个问题也适用于测试,每个项目是否应该有关于是否应该进行测试的行,还是也会被继承?
提前致谢。如果有人知道 link 到一个合理(相对复杂)的例子,那也很好。
在我的日常工作中,我目前正在处理一个大型的多项目。不幸的是它是闭源的,所以我不能分享细节,但我可以分享一些指导。
创建一个仅供 root/container 项目使用的
rootSettings
,因为它通常不是组装或发布步骤的一部分。它将包含如下内容:lazy val rootSettings := Seq( publishArtifact := false, publishArtifact in Test := false )
创建一个由所有子项目共享的
commonSettings
。将 base/shared 程序集设置放在这里: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
,并应用项目特定的覆盖: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
,因为这是在最近的项目菜单中显示的项目名称。lazy val myProjectRoot = project.in(file(".")) .settings(rootSettings: _*) .settings( // ... ) .dependsOn( // ... ) .aggregate( fubar, // ... )
您可能还需要添加自定义策略来组合 reference.conf
文件(对于 Typesafe Config 库):
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)
}