如何使用 SBT 和 IntelliJ IDEA 管理多个相互依赖的模块?

Posted

技术标签:

【中文标题】如何使用 SBT 和 IntelliJ IDEA 管理多个相互依赖的模块?【英文标题】:How to manage multiple interdependent modules with SBT and IntelliJ IDEA? 【发布时间】:2012-02-04 12:08:45 【问题描述】:

我正在开发几个相互依赖的模块,并希望在一个 IDEA 项目中一起使用它们。我正在使用sbt-idea 从 sbt 构建定义生成 IDEA 项目,这对单个项目非常有用。然而,在多模块的情况下,到目前为止我尝试过的事情并不完全有效:

使用 sbt-idea 为每个模块独立生成 IDEA .iml 文件;然后从头开始创建一个主 IDEA 项目并将这些模块添加到其中。这使得模块源在同一个窗口中都是可编辑的,但它们之间的依赖关系不会被跟踪(因此尝试从 foo 项目中的某个源导航到 bar 中的某个源带我到 bar 的导入库版本,而不是本地资源)。

使用 sbt multi-project builds(又名子项目),其中父项目的 Build.scala 包含以下内容:

lazy val foo = Project(id = "foo", base = file("foo"))
lazy val bar = Project(id = "bar", base = file("bar")) dependsOn(foo)

这几乎可以工作,因为 sbt-idea 会生成一个主 IDEA 项目,并跟踪子项目之间的依赖关系。但是有两个警告:

    这似乎是一个 sbt 限制,即子项目必须位于主项目的子目录中(即,file("../foo") 是不允许的)。这不是我真正想要的(如果一个模块——例如“utils”或“commons”包——用于两个不同的主项目呢?)但我可以接受它。 我的一个子项目有自己的子项目;我不确定 sbt 本身是否正确处理这些嵌套项目,但无论如何它们都会被 sbt-idea 忽略。显然,我需要将嵌套子项目递归地包含在主项目中。

总结一下:我想将可能已经有子项目的模块收集到一个带有跟踪依赖项的大型 IDEA 项目中,以便于编辑。我该怎么做?谢谢!

【问题讨论】:

尝试设置一个元项目,作为外部项目参考链接到其他项目 (github.com/harrah/xsbt/wiki/Full-Configuration)。我自己没有用 sbt-idea 尝试过,所以这是评论而不是答案。 感谢您的想法——但遗憾的是 sbt-idea 完全忽略了外部引用。 也许这将有助于下一个版本的 sbt-idea:github.com/mpeltonen/sbt-idea/commit/9f17cc8github.com/mpeltonen/sbt-idea/commit/4b4adf75 酷,所以我从最新的 git 源安装了 svn-idea 以获取这些更改,然后清理项目并再次运行 sbt-idea。有一些我不完全理解的奇怪的依赖解决问题,但不知何故我最终得到了一个工作项目!我确实必须在 IDEA 中为子子项目手动设置源目录;回想起来,我不确定我一开始就不能用股票 sbt-idea 11.1 做到这一点。无论如何,谢谢——我想我现在可以停止给牦牛剃毛了。 写完最后一条评论后,我发现我根本没有工作项目(再次,子子项目有问题)。所以我只是把它们分成了一级项目,所以我的主项目现在只有一个级别的子项目。当然,我只能这样做,因为这是我自己的全部代码。 【参考方案1】:

多项目构建的方法是正确的。您可以拥有任意长度的子项目的嵌套树,但不能拥有属于多个父项目的模块。这是绝对有道理的,在 Maven 中也是如此。

原因是很难将同一个模块放入多个项目并保持源同步。正常的工作流程如下:

您有一个模块所属的项目,您可以在其中修改模块源代码。 您将模块发布到本地存储库中 在需要该模块的其他项目中,将其声明为 libraryDependency

如果您想在 Idea 中加载不属于当前项目的模块,这是可行的,因为您可以将其作为外部模块添加到工作区:

SBT-IDEA 为您的项目生成 .iml 文件,然后您将它们导入工作区 您可以将其他项目的other.iml添加到工作区 如果您修改手动添加到工作区的外部 SBT 模块,您应该重新发布它们以使更改在“主”项目上可见,该项目将这些外部模块视为“库依赖项”

【讨论】:

感谢您的意见。但是问题在于,“您可以拥有任意长度的子项目的嵌套树”并非如此。我同意这应该与 sbt 一起使用,但 sbt-idea 显然不包含在生成的 IDEA 项目文件中的子子项目。 这个限制是不是来自idea? 不,我确实让 IDEA 项目层次结构深了几个层次。【参考方案2】:

子项目必须位于主项目的子目录中似乎是一个 sbt 限制(即,不允许使用 file("../foo"))。这并不是我真正想要的(如果一个模块——例如“utils”或“commons”包——用于两个不同的主项目呢?)但我可以接受它。

在 sbt 13.5 和 intellij 13.x 中,您可以使用 Build.scala 指定具有相对路径的项目间依赖关系。 假设您有两个项目,一个核心项目 commons 和另一个项目 foo,它们都位于一个公共目录 code/

    在 code/foo/project/ 下创建 Build.scala

    把这段代码 sn -p insde Build.scala

    object ProjectDependencies 
        val commons = RootProject(file("../commons"))
    
    
    object ProjectBuild extends Build 
        import ProjectDependencies._
    
        lazy val root = Project(id = "foo", base = file(".")).dependsOn(commons)
    
    

    通过sbt gen-idea sbt 生成您的IntelliJ 项目

【讨论】:

这是否允许通过“foo”链接来编辑“commons”源? 是的,它允许。它适用于我的 sbt 0.13.7 和 intellij 14.0.3 安装

以上是关于如何使用 SBT 和 IntelliJ IDEA 管理多个相互依赖的模块?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Intellij Idea 中使用自定义 sbt 版本?

如何在 sbt 项目中使用来自不同位置的 scala 源并使其与 IntelliJ IDEA 一起使用?

更改后如何强制 IntelliJ IDEA 从 build.sbt 重新加载依赖项?

如何将 SBT 类附加到 Intellij Idea?

为 Scala/SBT 设置 IntelliJ IDEA Ultimate

如何从 IntelliJ IDEA 的 bash 设置 SBT 以避免格式化字符被破坏?