Как управлять несколькими взаимозависимыми модулями с SBT и IntelliJ IDEA?

Я разрабатываю несколько модулей с зависимостями между ними и хотел бы работать с ними все вместе в одном проекте IDEA. Я использую sbt-idea для создания проектов IDEA из определений сборки sbt, которые отлично подходят для отдельных проектов. Однако в случае с несколькими модулями все, что я пробовал до сих пор, не совсем работает:

Использовать sbt-idea для генерации IDEA файла .iml для каждого модуля независимо; затем создайте мастер-проект IDEA с нуля, добавьте к нему эти модули. Это делает источники модулей доступными для редактирования в одном окне, но зависимости между ними не отслеживаются (поэтому попытка перехода от некоторого источника в проекте foo к чему-то в строке приведет меня к импортированной библиотечной версии бара, а не к локальным источникам).

Используйте sbt многопроектные сборки (aka subprojects), где родительский проект Build.scala содержит такие вещи, как

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

Это почти работает, поскольку в sbt-идее генерируется мастер-проект IDEA с зависимостями отслеживаемых подпроектов. Есть, однако, два оговорки:

  • Кажется, это ограничение sbt, что подпроекты должны жить в подкаталогах главного проекта (т.е. file("../foo") не допускается). Это не совсем то, что я хочу (что, если модуль - например, "utils" или "commons" - используется в двух разных мастер-проектах?), Но я могу жить с ним.
  • Один из моих подпроектов имеет свои собственные подпроекты; Я не уверен, правильно ли sbt справляется с этими вложенными проектами, но в любом случае они игнорируются sbt-idea. Очевидно, что мне нужно, чтобы вложенные подпроекты включались рекурсивно в главный проект.

Подводя итог: я хотел бы собрать модули, которые могут уже иметь подпроекты в один большой проект IDEA с отслеживаемыми зависимостями для удобного редактирования. Как мне это сделать? Спасибо!

Ответ 1

Похоже, что ограничение sbt заключается в том, что подпроекты должны жить в подкаталогах главного проекта (т.е. файл ( "../foo" ) не допускается). Это не совсем то, что я хочу (что, если модуль - например, "utils" или "commons" package - используется в двух разных мастер-проектах?), Но я могу жить с ним.

С sbt 13.5 и intellij 13.x вы можете указать зависимость между проектами с относительным путем, используя Build.scala. Скажем, у вас есть два проекта: основной проект commons и еще один проект foo, оба проживающие в общем каталоге code/

  • создать Build.scala под кодом /foo/project/
  • поместите этот фрагмент кода. 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)
    }
    
  • Создайте проект IntelliJ через sbt sbt gen-idea

Ответ 2

Подход с многопроектной сборкой является правильным. У вас может быть вложенное дерево подпроектов произвольной длины, но вы не можете иметь модуль, принадлежащий нескольким родительским проектам. Это имеет смысл, и в Maven бывает то же самое.

Причина в том, что было бы сложно иметь один и тот же модуль в нескольких проектах и ​​синхронизировать источники. Обычный рабочий процесс следующий:

  • У вас есть проект, к которому принадлежит модуль, где вы изменяете источник модуля.
  • Вы публикуете модуль в своем локальном репозитории
  • В других проектах, где вам нужен модуль, вы объявляете его как libraryDependency

Если вы хотите загрузить модуль, который не относится к текущему проекту внутри Idea, это, однако, возможно, поскольку вы можете добавить это как внешний модуль в рабочую область:

  • SBT-IDEA создает файлы .iml для вашего проекта и импортирует их в рабочей области
  • Вы можете добавить other.iml других проектов в рабочую область
  • Если вы изменяете внешние SBT-модули, которые вы вручную добавили в рабочую область, вы должны переиздать их, чтобы получить изменения visibile в "основном" проекте, который видит, что эти внешние модули являются "libraryDependency"