SBT, включая номер версии в программе
Мне нужна программа, которую я создаю, чтобы иметь возможность сообщать о своей версии во время выполнения (например, scala myprog.jar --version
). Традиционно в проекте maven я использовал фильтрацию ресурсов (pom.xml → file.properties → значение чтения во время выполнения). Я знаю там sbt-filter-plugin, чтобы эмулировать эту функциональность, но мне любопытно, есть ли более стандартный/предпочтительный/умный способ сделать это в SBT.
tl; dr как я могу прочитать номер версии, определенный в build.sbt
во время выполнения?
Ответы
Ответ 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]
и соответствующим образом сгенерировать объект.