Patrice Ferlet
Patrice Ferlet
Créateur de ce blog.
Publié le juin 21, 2015 Temps de lecture: 3 min

Me suivre sur Mastodon

Assigner une variable lors de la compilation en Go

Je viens de faire une release de mon outil idok et je me suis posé cette fameuse question: comment faire pour assigner la version dans mon binaire sans avoir à modifier le code source ? Et bien c’est simple comme tout mais il faut le savoir. Voilà la méthode.

Prenons un exemple de programme dont vous avez assigné une valeur de version et qui l’affiche:

package main

import (
    "fmt"
)

const VERSION="heuuuu"

func main(){
    fmt.Println(VERSION)
}

Le résultat est logiquement:

$ go run main.go
heuuu

Très bien… sauf que là c’est “en dur” et qu’à chaque release je dois penser à monter la version dans le source. Un peu de recherche et je comprends qu’on peut modifier les drapeaux “ld”. En gros, on peut “modifier les variables au moment de l’édition de lien”.

Attention, on ne parle pas de “ld”, l’éditeur de lien GNU, mais de celui de Go !, voir https://golang.org/cmd/ld/ et on voit une ligne très intéressante:

-X symbol value

Set the value of a string variable. The symbol name should be of the form importpath.name, as displayed in the symbol table printed by “go tool nm”.

Et c’est la variable “main.VERSION” qu’on va changer, c’est à dire “la variable VERSION dans le package main”. On va utiliser le drapeau “X” de la librairie “ld”

Cela dit vous devez penser à utiliser une variable et non une constante. Donc on modifie le programme en :

package main

import (
    "fmt"
)

// on met une variable
var VERSION="heuuuu"

func main(){
    fmt.Println(VERSION)
}

Et on va tenter:

$ go run main.go
heuuu
$ go run -ldflags '-X main.VERSION 0.0.1' main.go
0.0.1
$ go run -ldflags '-X main.VERSION alpha1' main.go
alpha1

Du coup, tout devient plus simple. On peut utiliser un Makefile qui utilise, par exemple, git pour avoir le tag en cours:

VERSION:=$(shell git describe --tags)
OPTS:=-ldflags '-X main.VERSION $(VERSION)'

build:
    go build $(OPTS) main.go
    

Reste alors à changer “main.go” pour ajouter la possibilité d’avoir une option -version:

package main

import (
    "flag"
    "fmt"
    "os"
)

// on met une variable - UNDEF 
var VERSION="UNDEF"

func main(){
    v := flag.Bool("version", false, "get the current version:"+ VERSION )
    flag.Parse()
    
    if *version {
        fmt.Println(VERSION)
        os.Exit(0)
    }
    
    fmt.Println("No version flag set...")
}

Et donc:

$ git tag 0.0.1
$ make
$ ./main -version
0.0.1
$ git tag 0.0.2
$ make
$ ./main -version
0.0.2

Quand je vous disais que c’était simple…

Juste une petite note, je n’ai pas trouvé comment assigner autre chose qu’une chaine de caractères… si vous avez la solution, merci de me prévenir que je modifie le billet.

comments powered by Disqus