Подтвердить что ты не робот

SBT, включая номер версии в программе

Мне нужна программа, которую я создаю, чтобы иметь возможность сообщать о своей версии во время выполнения (например, scala myprog.jar --version). Традиционно в проекте maven я использовал фильтрацию ресурсов (pom.xml → file.properties → значение чтения во время выполнения). Я знаю там sbt-filter-plugin, чтобы эмулировать эту функциональность, но мне любопытно, есть ли более стандартный/предпочтительный/умный способ сделать это в SBT.

tl; dr как я могу прочитать номер версии, определенный в build.sbt во время выполнения?

4b9b3361

Ответ 1

Обновление...

https://github.com/ritschwumm/xsbt-reflect (упомянутый выше) устарел, но есть этот классный инструмент выпуска SBT, который может автоматически управлять версиями и более: https://github.com/sbt/sbt-release.

В качестве альтернативы, если вы хотите быстро исправить, вы можете получить версию из манифеста следующим образом:

val version: String = getClass.getPackage.getImplementationVersion

Это значение будет равно version в вашем проекте, который вы устанавливаете либо в build.sbt, либо Build.scala.

Другое обновление...

Buildinfo SBT-плагин может генерировать класс с номером версии на основе build.sbt:

/** This object was generated by sbt-buildinfo. */
case object BuildInfo {
  /** The value is "helloworld". */
  val name: String = "helloworld"
  /** The value is "0.1-SNAPSHOT". */
  val version: String = "0.1-SNAPSHOT"
  /** The value is "2.10.3". */
  val scalaVersion: String = "2.10.3"
  /** The value is "0.13.2". */
  val sbtVersion: String = "0.13.2"
  override val toString: String = "name: %s, version: %s, scalaVersion: %s, sbtVersion: %s" format (name, version, scalaVersion, sbtVersion)
}

Смотрите документы о том, как включить его здесь: https://github.com/sbt/sbt-buildinfo/.

Ответ 2

Используйте плагин xsbt-reflect. Он будет генерировать исходный файл, который содержит, помимо прочего, номер версии проекта.

Ответ 3

Я закончил создание системы сборки (я использую Makefile поверх sbt), чтобы подготовить файл src/main/resources/version.txt для Scala для чтения.

В Makefile:

$(RESOURCES_VERSION): build.sbt
    grep "^version := " $< | cut -f2 -d\" > [email protected]

В Scala:

val version: String = {
  val src = Source.fromURL( getClass.getResource("/version.txt") )
  src.getLines.next   // just take the first line 
}

Это работает для меня.

Любопытно, что такая необходимая функция (я думаю) нелегко доступна в Scala. Очень простой плагин sbt для этого был бы рад.

Ответ 4

В общем, без каких-либо плагинов вы можете сделать что-то вроде этого:

sourceGenerators in Compile += Def.task {
  val file = (sourceManaged in Compile).value / "foo" / "bar" / "BuildInfo.scala"

  IO.write(
    file,
    s"""package foo.bar
       |object BuildInfo {
       |  val Version = "${version.value}"
       |}""".stripMargin
  )

  Seq(file)
}.taskValue

И затем с константой foo.bar.BuildInfo.Version, которая вам нравится.

Или более общий:

def generateBuildInfo(packageName: String,
                      objectName: String = "BuildInfo"): Setting[_] =
  sourceGenerators in Compile += Def.task {
    val file =
      packageName
        .split('.')
        .foldLeft((sourceManaged in Compile).value)(_ / _) / s"$objectName.scala"

    IO.write(
      file,
      s"""package $packageName
         |object $objectName {
         |  val Version = "${version.value}"
         |}""".stripMargin
    )

    Seq(file)
  }.taskValue

Пример:

settings(generateBuildInfo("foo.bar"))

Вы можете даже изменить это, чтобы передать свойства объекта как Map[String, String] и соответствующим образом сгенерировать объект.