如何在没有相同项目根的情况下进行sbt-(本地)多项目?

Sor*_*ona 8 dependencies scala intellij-idea multi-project sbt

我想在intellij中同时处理多个sbt项目.项目是"单向依赖",意味着一个是(可重用)核心,另一个是构建在该核心上的实际应用程序.两者目前都在开发中.

我希望核心驻留在除应用程序之外的另一个基本/根目录中,因此:

- /core
-- build.sbt

- /application
-- build.sbt
Run Code Online (Sandbox Code Playgroud)

我希望能够

  1. 在同一个IntelliJ窗口中修改两个项目
  2. 将两个项目都保留在各自的文件夹中(周围没有包装文件夹!).Core也将用于其他应用程序,这些应用程序不是当前"应用程序"的兄弟,所以我不希望它们位于同一个根文件夹下!

我尝试了什么,到目前为止我发现了哪些问题:

设置如

lazy val core = project.in(file("../core"))
lazy val application = project.in(file(".")).dependsOn(core)
Run Code Online (Sandbox Code Playgroud)

因为sbt断言多项目设置中的每个项目的目录都包含在同一个构建根目录中,所以不起作用:

sbt java.lang.AssertionError:断言失败:构建根/应用程序中不包含目录/核心

设置如

lazy val core = RootProject(file("../core"))
lazy val application = project.in(file(".")).dependsOn(core)
Run Code Online (Sandbox Code Playgroud)

不是解决方案,因为:

  1. 不能在一个IntelliJ窗口中同时拥有这两个项目
  2. 奇怪的是,核心类在应用程序中找不到,尽管导入工作正在进行中

现在我是一个新手,我猜(并希望)必须有一个解决这个问题的方法.我不可能是唯一一个想要在没有包装层的情况下分离我的项目并且仍然可以在我选择的IDE中修改它们的人.

编辑:

@ OlegRudenko的解决方案对我来说是半工作的.由于core还有一些依赖项,我无法编译或使用它application.

coreapplication引入一些依赖项,例如Logger,当我进入并尝试使用core编译器的组件时,我会尖叫,因为它无法找到依赖项core(例如记录器).

另外,core拉入例如lwjgl并且我想使用它的一些组件application,没有机会,因为它无法找到该依赖项的包core.

现在我所做的是一个hacky非解决方案.我只是开发都coreapplication在同一的IntelliJ项目,并保持git的回购专用.

这根本不是一个解决方案,因为我想在开源core时暂时application关闭源代码,我仍然想同时处理这两个问题,改进core等等.

Ole*_*nko 7

如果某个框架不允许我做什么,我宁愿不打架而是寻求妥协.

SBT不允许在项目根目录之外拥有子项目.所以我的解决方案是在我的项目中创建一个符号链接到子项目,该子项目位于外部:

common/
common/core/  - I want this as a sub-project inside of my project
application/
application/ui/  - This is my project

application/ui/core/ -> ../../common/core/  - This is my goal
Run Code Online (Sandbox Code Playgroud)

它必须

  • 自动工作
  • 在不同的操作系统上工作
  • 要清楚易懂
  • 使用标准工具

解决方案是将以下行添加到SBT文件中:

val __createLinkToCore = {
  import java.nio.file.{FileSystemException, Files, Paths}
  import scala.util.Try

  val corePath = Paths.get("..", "..", "common", "core")
  if(!Files.exists(corePath)) throw new IllegalStateException("Target path does not exist")

  val linkPath = Paths.get("core")
  if(Files.exists(linkPath)) Files.delete(linkPath)

  Try {Files.createSymbolicLink(linkPath, corePath)}.recover {
    case cause: FileSystemException if System.getProperty("os.name").toLowerCase.contains("windows") =>
      val junctionCommand = Array("cmd", "/c", "mklink", "/J", linkPath.toAbsolutePath.normalize().toString, corePath.toAbsolutePath.normalize().toString)
      val junctionResult = new java.lang.ProcessBuilder(junctionCommand: _*).inheritIO().start().waitFor()
      if(junctionResult != 0) throw new Exception("mklink failed", cause)
      linkPath
  }.get
}
Run Code Online (Sandbox Code Playgroud)

它在每次启动SBT时执行,但在对代码执行任何操作之前 - 编译之前执行等等.它不会在每次编译时重新创建链接 - 每个SBT启动一次.

代码确实如下:

  • 获取所需文件夹的路径(如果不存在则失败)
  • 获取链接路径(如果存在则删除)
  • 尝试使用Java 7+ API创建新链接
  • 如果它在Windows 7+上运行而没有管理员权限则会失败.在这种情况下,我使用标准但特定于Windows的工具创建一个联结mklink /J

此解决方案的限制:

  • 它不适用于FAT文件系统
  • 你见过其他限制吗?让我知道!


Ric*_*ich 3

我认为这在 SBT 中是不可能的(但我很想听听其他情况)。

\n\n

以下是我在 IntelliJ 中为解决此问题所做的操作:

\n\n
    \n
  • 在IntelliJ中打开“应用程序”;刷新SBT定义
  • \n
  • 关闭 SBT 自动更新(文件 -> 设置 -> 构建 -> SBT)
  • \n
  • 从现有源执行文件 -> 新建 -> 模块,选择“核心”签出目录,从 SBT 导入\n\n
      \n
    • 勾选\xe2\x80\x9c下载源\xe2\x80\x9d,但不勾选\xe2\x80\x9c自动更新\xe2\x80\x9d
    • \n
  • \n
  • 您现在应该在同一个 IntelliJ 窗口中同时拥有 \xe2\x80\x9capplication\xe2\x80\x9d 和 \xe2\x80\x9ccore\xe2\x80\x9d (但“应用程序”仍然依赖于“核心”JAR,而不是您的实时来源)
  • \n
  • 右键单击 IntelliJ 中的“应用程序”项目,然后选择 \xe2\x80\x9copen module settings\xe2\x80\x9d\n\n
      \n
    • 打开 \xe2\x80\x9cdependencies\xe2\x80\x9d 选项卡
    • \n
    • 在库中找到“核心”SBT 依赖项并将其删除
    • \n
    • 在“核心”项目上添加“模块依赖”
    • \n
  • \n
  • 此时您应该手动重建项目,因为众所周知,IntelliJ 在添加模块时会对类路径感到困惑。
  • \n
  • 您现在可以在 IntelliJ 中将这两个项目作为单个代码库进行开发\n\n
      \n
    • 请注意,“应用程序”中的 \xe2\x80\x9csbt test\xe2\x80\x9d 等 SBT 命令行工具将继续使用“核心”JAR,而不是本地修改的源
    • \n
    • (“应用程序”中的 SBT Build.scala 文件仍然按版本号引用“核心”JAR)
    • \n
  • \n
  • 当您准备好提交时,您将需要:\n\n
      \n
    • 将更改提交到“core”,更新版本号
    • \n
    • 在“core”中运行“sbtpublishLocal”,记下生成的版本号
    • \n
    • 更新“application”中的 Build.scala 文件以引用新的“core”版本
    • \n
    • 运行“sbt test”或类似命令来检查 SBT 模式下一切是否正常
    • \n
    • 提交“应用程序”更改,同时推送
    • \n
  • \n
\n