sbt: генерация общих источников в кроссплатформенном проекте - PullRequest
4 голосов
/ 21 апреля 2019

Создавая мой проект на Scala с помощью sbt, я хочу задание, которое будет выполнено до фактической компиляции Scala и сгенерирует файл Version.scala с информацией о версии проекта. Вот задача, с которой я столкнулся:

lazy val generateVersionTask = Def.task {
  // Generate contents of Version.scala
  val contents = s"""package io.kaitai.struct
                    |
                    |object Version {
                    |  val name = "${name.value}"
                    |  val version = "${version.value}"
                    |}
                    |""".stripMargin

  // Update Version.scala file, if needed
  val file = (sourceManaged in Compile).value / "version" / "Version.scala"
  println(s"Version file generated: $file")
  IO.write(file, contents)
  Seq(file)
}

Эта задача, похоже, работает, но проблема в том, как ее подключить, учитывая, что это кросс-проект, нацеленный на Scala / JVM, Scala / JS и т. Д.

Вот так выглядел build.sbt, прежде чем я начал его трогать

lazy val root = project.in(file(".")).
  aggregate(fooJS, fooJVM).
  settings(
    publish := {},
    publishLocal := {}
  )

lazy val foo = crossProject.in(file(".")).
  settings(
    name := "foo",
    version := sys.env.getOrElse("CI_VERSION", "0.1"),
    // ...
  ).
  jvmSettings(/* JVM-specific settings */).
  jsSettings(/* JS-specific settings */)

lazy val fooJVM = foo.jvm
lazy val fooJS = foo.js

и в файловой системе у меня есть:

  • shared / - кросс-платформенный код, общий для сборок JS / JVM
  • jvm / - JVM-специфичный код
  • js / - JS-специфический код

Лучшее, что я придумал, это добавление этой задачи в foo crossProject:

lazy val foo = crossProject.in(file(".")).
  settings(
    name := "foo",
    version := sys.env.getOrElse("CI_VERSION", "0.1"),
    sourceGenerators in Compile += generateVersionTask.taskValue, // <== !
    // ...
  ).
  jvmSettings(/* JVM-specific settings */).
  jsSettings(/* JS-specific settings */)

Это работает, но очень неловко, не совсем совместимо с «разделяемой» кодовой базой. Он генерирует 2 отдельных файла Version.scala для JS и JVM:

sbt:root> compile
Version file generated: /foo/js/target/scala-2.12/src_managed/main/version/Version.scala
Version file generated: /foo/jvm/target/scala-2.12/src_managed/main/version/Version.scala

Естественно, невозможно получить доступ к содержимому этих файлов из shared, и именно здесь я хочу получить к нему доступ.

Пока что я пришел с очень небрежным обходным путем:

  • В одиночном объекте в общем
  • в основных точках входа JVM и JS самое первое, что я делаю, это назначаю эту переменную для соответствия константам, определенным в Version.scala

Кроме того, я попробовал тот же трюк с плагином sbt-buildinfo - результат точно такой же, он генерировал для каждой платформы BuildInfo.scala, который я не могу использовать напрямую из общих источников .

Есть ли лучшие решения?

1 Ответ

2 голосов
/ 22 апреля 2019

Рассмотрим указание sourceManaged на shared/src/main/scala/src_managed директорию и определение области видимости generateVersionTask для проекта root, например

val sharedSourceManaged = Def.setting(
  baseDirectory.value / "shared" / "src" / "main" / "scala" / "src_managed"
)

lazy val root = project.in(file(".")).
  aggregate(fooJS, fooJVM).
  settings(
    publish := {},
    publishLocal := {},
    sourceManaged := sharedSourceManaged.value,
    sourceGenerators in Compile += generateVersionTask.taskValue,
    cleanFiles += sharedSourceManaged.value
  )

Теперь sbt compile должно вывести что-то вроде

Version file generated: /Users/mario/IdeaProjects/scalajs-cross-compile-example/shared/src/main/scala/src_managed/version/Version.scala
...
[info] Compiling 3 Scala sources to /Users/mario/IdeaProjects/scalajs-cross-compile-example/js/target/scala-2.12/classes ...
[info] Compiling 1 Scala source to /Users/mario/IdeaProjects/scalajs-cross-compile-example/target/scala-2.12/classes ...
[info] Compiling 3 Scala sources to /Users/mario/IdeaProjects/scalajs-cross-compile-example/jvm/target/scala-2.12/classes ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...