控制 SBT 多项目上的依赖项加载歧义
Posted
技术标签:
【中文标题】控制 SBT 多项目上的依赖项加载歧义【英文标题】:Control dependency loading ambiguity on SBT multi-project 【发布时间】:2015-12-29 22:27:51 【问题描述】:我有一个 SBT Scala 多项目,其结构如下:
multiprojectRoot
project/SharedProjectBuildCode.scala
project1
src/sourceFiles
project1-build.sbt
project2
src/sourceFiles
project2-build.sbt
projectN
src/sourceFiles
projectN-build.sbt
multiprojectRoot/project/SharedProjectBuildCode.scala:包含使用dependsOn创建本地项目依赖的多项目定义。例如:
lazy val project2 = Project(
...
).dependsOn(project1)
multiprojectRoot/project2/project2-build.sbt:包含给定项目的设置和依赖项。例如:
name := "project2"
libraryDependencies ++= Seq(
...
"my.company" % "project1" % "1.0"
)
对 project1 的第一个依赖项是在 SharedProjectBuildCode.scala 文件上使用 dependsOn 声明的,第二个是在独立的 project2-build.sbt 构建定义文件上创建的。
所以,project2 定义包含:
对 project1 或 的模糊依赖 对 project1 的双重依赖我们希望保持这个项目结构,因为它最适合我们当前的工作流程:
独立的 .sbt 文件用于我们持续交付服务器上的每个项目的独立部署。 带有dependsOn的多项目.scala文件用于方便开发,让我们避免连续publishLocal之类的事情。我们需要以某种方式控制这种依赖模糊。你能帮助我吗?
【问题讨论】:
【参考方案1】:我认为你应该在SharedProjectBuildCode.scala
lazy val root = Project(id = "Main-Project",
base = file(".")) aggregate(project1, project2,..)
lazy val project2 = Project(id = "project2",
base = file("project1")).dependsOn(project1)
...
并且不再需要在 build.sbt 中添加依赖项。
【讨论】:
谢谢泰勒。问题是我们希望将独立的 .sbt 文件也保留为独立的,以用于部署目的。 DependsOn 应该用于开发,而独立项目构建将用于在我们的持续交付服务器上部署。 我认为你可以在没有多模块项目的情况下实现它。只需将它们全部设为独立项目并使用 sbt publish-local 构建,然后 libraryDependencies 应该在 sbt 文件中按预期工作。 嗯,publishLocal 正是我们希望在非部署开发周期中避免的。由于项目之间共享大量代码,因此必须为共享代码的每次更改执行手动步骤来 publishLocal 会真正减慢我们的速度,并使过程更加手动控制。一定有办法解决这个问题。 有两个 build.sbt 版本,一个用于生产,带有 libraryDependencies,另一个没有它,这样您就可以摆脱双重依赖。 是的,这将是最后的解决方案。我现在要尝试的只是为项目的独立构建添加“增量”属性,通过添加项目构建定义文件进行部署。它有效,我将其作为解决方案发布。【参考方案2】:通过使用 SBT 提供的构建文件加载规则,我能够控制在每个用例上加载的依赖集。
当您从给定的根目录加载 SBT 时,它会在根目录中查找 *.sbt 文件,并在根/项目目录中查找 *.scala。如果你有一个多项目构建,那么它也会读取在子项目上遇到的 .sbt 文件的定义,但它不会在子项目上使用 project/.scala 文件:
.sbt build definition
Multi-project builds
所以,我通过以下方式更改了我的多项目构建:
multiprojectRoot
project/SharedProjectBuildCode.scala
project1
src/sourceFiles
project/DeploymentOnlyCode.scala
project1-build.sbt
project2
src/sourceFiles
project/DeploymentOnlyCode.scala
project2-build.sbt
projectN
src/sourceFiles
project/DeploymentOnlyCode.scala
projectN-build.sbt
这样,根据我从多项目根目录或项目内部目录运行 SBT 的用例:
开发:SBT 从 multiprojectRoot 目录运行。它利用了多项目构建的优势(例如使用dependsOn 和避免publishLocal)。 生产:SBT 在具体项目目录中运行,例如 multiprojectRoot/project2。它允许将项目构建为独立的,将所有依赖项都作为显式的外部依赖项(用于声明对生产、持续集成服务器的一系列依赖项)。现在,一个项目有 3 个代码实例,它们为最终构建聚合它们的属性:
-
multiprojectRoot/project/SharedProjectBuildCode.scala:包含与多项目构建相关的本地依赖项和其他代码。
multiprojectRoot/project1/project1-build.sbt:包含项目构建属性,常见于项目的多项目和独立构建,例如始终外部的名称或依赖项。对于同级别的其他多项目项目也应该这样做,以明确地视为外部依赖项。
multiprojectRoot/project1/project/DeploymentOnlyCode.scala:包含仅在独立构建时才会考虑的构建属性。如果其他子项目需要定义部署特定属性,也可以这样做。
这还可以最大程度地控制项目的构建方式,是否是可发布的工件,并将仅与给定项目相关的源代码作为完整且独立的部分处理。
【讨论】:
以上是关于控制 SBT 多项目上的依赖项加载歧义的主要内容,如果未能解决你的问题,请参考以下文章
sbt 插件和使用插件本身的多项目构建中的项目之间的相互依赖关系