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

82

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

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

Используйте многопроектные сборки sbt (также известные как подпроекты) , где 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 с отслеживаемыми зависимостями между подпроектами. Однако есть два предостережения:

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

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

Дэвид Соргель
источник
2
Попробуйте настроить метапроект, который будет ссылаться на другие как на внешние ссылки проекта ( github.com/harrah/xsbt/wiki/Full-Configuration ). Я сам не пробовал это с sbt-idea, так что это скорее комментарий, чем ответ.
retronym
Спасибо за идею, но, к сожалению, sbt-idea полностью игнорирует внешние ссылки.
Дэвид Сёргель
Возможно, это поможет в следующей версии sbt-idea: github.com/mpeltonen/sbt-idea/commit/9f17cc8 github.com/mpeltonen/sbt-idea/commit/4b4adf75
retronym
Круто, поэтому я установил svn-idea из последних исходников git, чтобы внести эти изменения, затем очистил проекты и снова запустил sbt-idea. Были некоторые странные проблемы с разрешением зависимостей, которые я не полностью понимаю, но каким-то образом у меня получился рабочий проект! Мне пришлось вручную установить исходные каталоги в IDEA для подпроектов; и, оглядываясь назад, я не уверен, что не смог бы сделать это в первую очередь со стандартной sbt-idea 11.1. В любом случае, спасибо ... Думаю, я могу перестать брить этого яка сейчас.
Дэвид Сёргель
Написав этот последний комментарий, я обнаружил, что у меня все-таки не было рабочего проекта (опять же, проблемы с подпроектами). Я просто разделил их на первоклассные проекты, так что теперь мой главный проект имеет только один уровень подпроектов ниже. Конечно, я мог это сделать только потому, что это был весь мой собственный код.
David Soergel

Ответы:

7

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

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

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

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

  • SBT-IDEA генерирует файлы .iml для вашего проекта, и вы импортируете их в рабочую область.
  • Вы можете добавить other.iml других проектов в рабочую область
  • Если вы изменяете внешние модули SBT, которые вы вручную добавили в рабочую область, вы должны повторно опубликовать их, чтобы изменения были видны в «основном» проекте, который видит, что эти внешние модули являются «libraryDependency»
Эдмондо1984
источник
Спасибо за вклад. Однако проблема в том, что это не так, что «у вас может быть вложенное дерево подпроектов произвольной длины». Я согласен, что это должно работать с sbt, но sbt-idea, очевидно, не включает подпроекты в итоговый файл проекта IDEA.
Дэвид Сёргель
Это ограничение исходит от идеи?
Edmondo1984
Нет, я определенно сделал иерархию проектов IDEA на несколько уровней глубиной.
Дэвид Сёргель
7

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

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

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

user2829759
источник
позволит ли это редактировать исходный код "commons" путем ссылки на "foo"?
Tjunkie,
Да, позволяет. И он работает на моей установке sbt 0.13.7 и intellij 14.0.3
user2829759 02