2012-01-21 18 views
18

Chcę, aby program, który buduję, mógł zgłaszać własną wersję w czasie wykonywania (na przykład scala myprog.jar --version). Tradycyjnie w projekcie maven używam filtrowania zasobów (pom.xml -> file.properties -> read value w czasie wykonywania). Wiem, że jest sbt-filter-plugin, aby emulować tę funkcjonalność, ale jestem ciekawy, czy istnieje bardziej standardowy/preferowany/sprytny sposób robienia tego w SBT.SBT z numerem wersji w programie

tl; dr jak mogę odczytać numer wersji zdefiniowany w build.sbt w czasie wykonywania?

+0

Właściwym, idiomatycznym sposobem, aby to zrobić w dzisiejszych czasach jest via sbt-buildinfo https://github.com/sbt/sbt-buildinfo/. –

Odpowiedz

19

Aktualizacja ...

https://github.com/ritschwumm/xsbt-reflect (wymienione powyżej) jest przestarzała, ale nie jest to fajne narzędzie uwolnienie SBT, który może automatycznie zarządzać wersjami i nie tylko: https://github.com/sbt/sbt-release.

Ewentualnie, jeśli chcesz szybko naprawić można dostać wersję z manifestu tak:

val version: String = getClass.getPackage.getImplementationVersion 

Ta wartość będzie równa version ustawienia w projekcie, które można ustawić zarówno w build.sbt lub Build.scala.

Kolejna aktualizacja ...

Buildinfo SBT Wtyczka może wygenerować klasę z numerem wersji opartej na 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) 
} 

Zobacz docs na jak włączyć go tutaj: https://github.com/sbt/sbt-buildinfo/.

+2

Niestety, daje to "null" dla mnie. sbt 0.13.8, JDK 8, Scala 2.11.7 – akauppi

+0

Czy ustawiłeś 'version' poprawnie w SBT? –

+0

Tak, wyświetla się w wyjściowej nazwie pliku jar i tak dalej. Ale projekt nie tworzy żadnego Maven pom, jest to samodzielny plik wykonywalny. Zakładam, że to jest powód, dla którego nie dostałbym tych wersji implementacji/specyfikacji itp. Wszelkie wskazówki są mile widziane - nie pochodzę z Java, więc te odczucia są dla mnie zbyt przesadzone. :) – akauppi

7

Użyj wtyczki xsbt-reflect. Wygeneruje plik źródłowy zawierający między innymi numer wersji projektu.

+0

Dzięki, wygląda na bardzo dobre rozwiązanie –

+0

Pracowałem jak czar, dzięki jeszcze raz. –

1

Skończyłem, tworząc system kompilacji (używam Makefile na szczycie sbt) przygotować plik src/main/resources/version.txt dla Scala do odczytu.

W Makefile:

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

W Scala:

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

Działa to dla mnie.

Ciekawe, że taka potrzebna funkcja (jak sądzę) nie jest łatwo dostępna w Scali. Bardzo prosta wtyczka sbt tylko byłaby mile widziana.

+0

Jest łatwo dostępny w wanilii sbt, zobacz moją odpowiedź. – Tvaroh

0

Generalnie bez żadnych wtyczek, można zrobić coś takiego:

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 

A potem zrobić z foo.bar.BuildInfo.Version stałej cokolwiek chcesz.

lub bardziej ogólnie:

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 

przykład:

settings(generateBuildInfo("foo.bar")) 

Można również zmienić przejść właściwości obiektu jako Map[String, String] i generowania obiektu odpowiednio.

Powiązane problemy