2012-01-21 18 views
18

Quiero un programa que estoy construyendo para poder informar su propia versión en tiempo de ejecución (por ejemplo, scala myprog.jar --version). Tradicionalmente en un proyecto maven, utilizaba el filtrado de recursos (pom.xml -> file.properties -> read value en tiempo de ejecución). Sé que hay sbt-filter-plugin para emular esta funcionalidad, pero tengo curiosidad de saber si hay una forma más estándar/preferida/inteligente de hacerlo en SBT.SBT incluyendo el número de versión en un programa

tl; dr ¿cómo puedo leer el número de versión definido en build.sbt en tiempo de ejecución?

+0

La forma idiomática correcta para hacer esto hoy en día es a través de sbt-buildinfo https://github.com/sbt/sbt-buildinfo/. –

Respuesta

19

actualización ...

https://github.com/ritschwumm/xsbt-reflect (mencionado anteriormente) es obsoleto, pero no es esta herramienta fresca liberación SBT que puede gestionar automáticamente las versiones y más: https://github.com/sbt/sbt-release.

Alternativamente, si desea una solución rápida puede obtener la versión del manifiesto de la siguiente manera:

val version: String = getClass.getPackage.getImplementationVersion 

Este valor será igual a version configuración de su proyecto que se establece ya sea en build.sbt o Build.scala.

otra actualización ...

Buildinfo SBT plugin puede generar una clase con el número de versión basado en 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) 
} 

Consulte la documentación sobre cómo habilitar aquí: https://github.com/sbt/sbt-buildinfo/.

+2

Desafortunadamente, esto me da un 'nulo'. sbt 0.13.8, JDK 8, Scala 2.11.7 – akauppi

+0

¿Ha configurado 'versión' correctamente en SBT? –

+0

Sí, se muestra en el nombre del archivo jar de salida, etc. Pero el proyecto no está haciendo Maven pom, es un ejecutable independiente. Supongo que esta es la razón por la que no obtendría estas versiones de implementación/especificación, etc. Cualquier puntero es bienvenido. No soy de Java, así que me siento un poco sobreendeudado. :) – akauppi

7

Utilice el complemento xsbt-reflect. Generará un archivo fuente que contiene, entre otras cosas, el número de versión del proyecto.

+0

Gracias, parece una muy buena solución –

+0

Funcionó como un amuleto, gracias de nuevo. –

1

Terminé haciendo el sistema de compilación (utilizo un Makefile en la parte superior de sbt) prepare un archivo src/main/resources/version.txt para que Scala lo lea.

En el Makefile:

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

En Scala:

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

Esto funciona para mí.

Es curioso que una característica tan necesaria (creo) no esté fácilmente disponible en Scala. Un muy simple sbt plugin solo para esto sería bienvenido.

+0

Está fácilmente disponible en vainilla sbt, ver mi respuesta. – Tvaroh

0

En general, sin ningún tipo de plugins, puede hacer algo como esto:

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 

Y luego ver con foo.bar.BuildInfo.Version constante lo que quiera.

O más 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 

Ejemplo:

settings(generateBuildInfo("foo.bar")) 

Incluso puede cambiar esto a pasar propiedades de objeto como una Map[String, String] y generar el objeto adecuadamente.

Cuestiones relacionadas