Плагин sbt динамически загружать определенный пользователем код?

Я работаю над плагином sbt, который генерирует модели Scala на основе базы данных с помощью генератора кода Slick

Я бы, конечно, хотел, чтобы пользователи переопределяли генератор кода, поэтому мой плагин должен поддерживать это:

  • В любом случае, я могу динамически загружать класс Scala с указанием пути к нему в ключах плагина build.sbt? Например, в родительском build.sbt пользователя она предоставит что-то вроде codegen.override=com.company.project.CustomCodegenerator который выглядит так

  • Связанные с выше; пользовательский codegen может использовать некоторые другие библиотеки, поэтому простой динамической загрузки классов может быть недостаточно. В любом случае плагин sbt может наследовать зависимости проекта, используя этот плагин?

Вот полное обсуждение этого: https://github.com/papauschek/play-slick-evolutions-plugin/issues/1

1 ответ

В конце дня вам нужно запустить некоторый код для генерации исходных файлов Scala.

Генерация файлов

Как вы знаете, sbt имеет хук для генерации исходных файлов, который называется sourceGenerators, который задокументирован в Генерация файлов. Вы как автор плагина должны предоставить задачу, которая генерирует Seq[File] под (sourceManaged in Compile).value / "garfield" используя генератор кода Slick в качестве реализации по умолчанию. Давайте назовем это generateModel, Ваш плагин может иметь следующие настройки:

sourceGenerators in Compile += generateModel.taskValue,
generateModel := defaultGenerateModel.value,
defaultGenerateModel := { ... }

Если ваш пользователь сборки хочет перемонтировать generateModelОн или она могли бы сделать это так:

generateModel := {
  val file = (sourceManaged in Compile).value / "garfield" / "Foo.scala"
  IO.write(file, """case class Foo() {}""")
  Seq(file)
}

Если генерация кода содержится в плагине sbt, как описано выше, вам не нужно делать какие-либо динамические вещи. поскольку play-slick-evolutions-codegen-plugin зависит от slick-codegen, это не должно быть проблемой.

Динамическая загрузка кода пользователя

Поскольку вопрос заключается непосредственно в динамической загрузке кода пользователя, я бы также добавил несколько указателей на это.

  • Одним из способов является использование sbt.Run API из существующей конфигурации. Это эквивалентно звонку run Задача с некоторым настроенным параметром. Если вы генерируете код для Compile конфигурация, использование бегуна для любой конфигурации, которая зависит от него, не будет хорошей идеей.
  • Другой подобный способ заключается в использовании sbt.Fork API. Форкинг позволяет запускать код вне плагина.

Учитывая, что sbt будет автоматически упорядочивать задачи на основе их зависимостей и выполнять несколько задач параллельно, динамическое выполнение кода чревато неожиданными опасностями.

Другие вопросы по тегам