I want a program I'm building to be able to report its own version at runtime (e.g. scala myprog.jar --version
). Traditionally in a maven project, I'd use resource filtering (pom.xml -> file.properties -> read value at runtime). I know there's sbt-filter-plugin to emulate this functionality, but I'm curious if there's a more standard / preferred / clever way of doing this in SBT.
tl;dr how can I read the version number defined in build.sbt
at runtime?
Update...
https://github.com/ritschwumm/xsbt-reflect (mentioned above) is Obsolete, but there is this cool SBT release tool that can automatically manage versions and more: https://github.com/sbt/sbt-release.
Alternatively, if you want a quick fix you can get version from manifest like this:
val version: String = getClass.getPackage.getImplementationVersion
This value will be equal to version
setting in your project which you set either in build.sbt
or Build.scala
.
Another Update ...
Buildinfo SBT plugin can generate a class with version number based on 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)
}
See the docs on how to enable it here: https://github.com/sbt/sbt-buildinfo/.
Use the xsbt-reflect plugin. It will generate a source file that contains, among other things, the project version number.
In general, without any plugins, you can do something like this:
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
And then do with foo.bar.BuildInfo.Version
constant whatever you like.
Or more general:
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
Example:
settings(generateBuildInfo("foo.bar"))
You can even change this to pass object properties as a Map[String, String]
and generate the object appropriately.
I ended up making the build system (I use a Makefile
on top of sbt
) prepare a src/main/resources/version.txt
file for Scala to read.
In the Makefile
:
$(RESOURCES_VERSION): build.sbt
grep "^version := " $< | cut -f2 -d\" > $@
In Scala:
val version: String = {
val src = Source.fromURL( getClass.getResource("/version.txt") )
src.getLines.next // just take the first line
}
This works for me.
It's curious that such a needed feature (I would think) is not easily available in Scala. A very simple sbt
plugin just for this would be welcome.
来源:https://stackoverflow.com/questions/8957025/sbt-including-the-version-number-in-a-program