gpt4 book ai didi

scala - 如何在没有相同项目根目录的情况下做一个 sbt-(local) 多项目?

转载 作者:行者123 更新时间:2023-12-04 06:35:19 29 4
gpt4 key购买 nike

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

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

- /core
-- build.sbt

- /application
-- build.sbt

我希望能够
  • 在同一个 IntelliJ 窗口中修改两个项目
  • 将两个项目留在各自的文件夹中(周围没有包装文件夹!)。核心也将用于其他应用程序,即 的应用程序。没有当前“应用程序”的 sibling ,所以我这样做 不想他们驻留在同一个根文件夹下!

  • 我尝试过的以及到目前为止发现的问题:

    像这样的设置
    lazy val core = project.in(file("../core"))
    lazy val application = project.in(file(".")).dependsOn(core)

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

    sbt java.lang.AssertionError: assertion failed: Directory /core is not contained in build root /application



    像这样的设置
    lazy val core = RootProject(file("../core"))
    lazy val application = project.in(file(".")).dependsOn(core)

    不是解决方案,因为:
  • 我可以不是 将两个项目放在一个 IntelliJ 窗口中,然后
  • 奇怪的是,在应用程序中找不到核心类,尽管
    进口立即生效

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

    编辑:

    @OlegRudenko 的解决方案对我来说是半工作的。如 core也有一些依赖项,我无法在 application 中编译或使用它.
    core引入一些依赖项,例如一个记录器,当我在 application并尝试使用 core 的组件编译器对我大喊大叫,因为它在 core 中找不到依赖项(例如记录器)。

    另外, core拉入例如lwjgl 和我想在 application 中使用它的一些组件,没有机会,因为它找不到 core 的依赖项的包.

    现在我所做的是一个 hacky 非解决方案。我只是开发了 coreapplication在同一个 intellij-project 中并保持 git-repo 私有(private)。

    这根本不是解决方案,因为我想开源 coreapplication现在是封闭源代码,我仍然想同时处理这两个问题,完善 core等等

    最佳答案

    如果某些框架不允许我做某事,我宁愿不争,而是寻求妥协。

    SBT 不允许在项目根目录之外有子项目。
    所以我的解决方案是在我的项目内部创建一个指向位于外部的子项目的符号链接(symbolic link):

    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

    它必须
  • 自动工作
  • 在不同的操作系统上工作
  • 清晰易懂
  • 使用标准工具

  • 解决方案是将以下行添加到 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
    }

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

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

  • 此解决方案的限制:
  • 它不适用于 FAT 文件系统
  • 你见过其他的限制吗?让我知道!
  • 关于scala - 如何在没有相同项目根目录的情况下做一个 sbt-(local) 多项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32290180/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com