Aplikasi pembuatan versi otomatis

193

Apakah mungkin untuk menambah nomor versi minor secara otomatis setiap kali aplikasi Go dikompilasi?

Saya ingin menetapkan nomor versi di dalam program saya, dengan bagian penambahan otomatis:

$ myapp -version
MyApp version 0.5.132

Menjadi 0,5 nomor versi yang saya atur, dan 132 nilai yang bertambah secara otomatis setiap kali biner dikompilasi.

Apakah ini mungkin di Go?

Sebastián Grignoli
sumber

Jawaban:

337

Go linker ( tautan alat go ) memiliki opsi untuk mengatur nilai variabel string yang tidak diinisialisasi:

-X importpath.name=value
  Set the value of the string variable in importpath named name to

nilai. Perhatikan bahwa sebelum Go 1.5 opsi ini mengambil dua argumen terpisah. Sekarang dibutuhkan satu pemisahan argumen pada tanda = pertama.

Sebagai bagian dari proses build Anda, Anda bisa mengatur variabel string versi menggunakan ini. Anda dapat melewati ini melalui goalat menggunakan -ldflags. Misalnya, diberikan file sumber berikut:

package main

import "fmt"

var xyz string

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

Kemudian:

$ go run -ldflags "-X main.xyz=abc" main.go
abc

Untuk menetapkan main.minversiontanggal dan waktu saat membangun:

go build -ldflags "-X main.minversion=`date -u +.%Y%m%d.%H%M%S`" service.go

Jika Anda mengkompilasi tanpa menginisialisasi main.minversiondengan cara ini, itu akan berisi string kosong.

axw
sumber
4
Akan nilai yang akan disimpan ke dalam biner jika saya menggunakan go bouildbukan go run?
Sebastián Grignoli
6
go build -ldflags "-X main.minversion `date -u +.%Y%m%d%.H%M%S`" service.go
Sebastián Grignoli
4
goxc melakukan ini untuk Anda :) secara default ia mengkompilasi dengan -ldflags "-Xmain.VERSION xxx -Xmain.BUILD_DATE CurrentDateInISO8601", tetapi Anda dapat mengkonfigurasi nama-nama variabel tersebut jika Anda mau. Lihat github.com/laher/goxc ... (penafian: Saya menulis goxc)
laher
7
contoh kerja dengan sintaks 1,5 baru untuk menambahkan variabel go build -ldflags "-X 'main.buildtime=$(date -u '+%Y-%m-%d %H:%M:%S')'"
buildtime
26
perhatikan bahwa nama paket lengkap diperlukan. go build -ldflags "-X pkg.version=123"tidak akan bekerja sambil go build -ldflags "-X path/to/pkg.version=123"bekerja seperti yang diharapkan. semoga membantu.
csyangchen
27

Selain itu saya ingin memposting contoh kecil cara menggunakan git dan makefile:

--- Makefile ----

# This how we want to name the binary output
BINARY=gomake

# These are the values we want to pass for VERSION and BUILD
# git tag 1.0.1
# git commit -am "One more change after the tags"
VERSION=`git describe --tags`
BUILD=`date +%FT%T%z`

# Setup the -ldflags option for go build here, interpolate the variable values
LDFLAGS_f1=-ldflags "-w -s -X main.Version=${VERSION} -X main.Build=${BUILD} -X main.Entry=f1"
LDFLAGS_f2=-ldflags "-w -s -X main.Version=${VERSION} -X main.Build=${BUILD} -X main.Entry=f2"

# Builds the project
build:
    go build ${LDFLAGS_f1} -o ${BINARY}_f1
    go build ${LDFLAGS_f2} -o ${BINARY}_f2

# Installs our project: copies binaries
install:
    go install ${LDFLAGS_f1}

# Cleans our project: deletes binaries
clean:
    if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi

.PHONY: clean install

File make akan membuat dua file executable. Satu menjalankan fungsi satu, yang lain akan mengambil fungsi dua sebagai entri utama:

package main

import (
        "fmt"
)

var (

        Version string
        Build   string
        Entry   string

        funcs = map[string]func() {
                "f1":functionOne,"f2":functionTwo,
        }

)

func functionOne() {
    fmt.Println("This is function one")
}

func functionTwo() {
    fmt.Println("This is function two")
}

func main() {

        fmt.Println("Version: ", Version)
        fmt.Println("Build Time: ", Build)

    funcs[Entry]()

}

Kemudian jalankan:

make

Kamu akan mendapatkan:

mab@h2470988:~/projects/go/gomake/3/gomake$ ls -al
total 2020
drwxrwxr-x 3 mab mab    4096 Sep  7 22:41 .
drwxrwxr-x 3 mab mab    4096 Aug 16 10:00 ..
drwxrwxr-x 8 mab mab    4096 Aug 17 16:40 .git
-rwxrwxr-x 1 mab mab 1023488 Sep  7 22:41 gomake_f1
-rwxrwxr-x 1 mab mab 1023488 Sep  7 22:41 gomake_f2
-rw-rw-r-- 1 mab mab     399 Aug 16 10:21 main.go
-rw-rw-r-- 1 mab mab     810 Sep  7 22:41 Makefile
mab@h2470988:~/projects/go/gomake/3/gomake$ ./gomake_f1
Version:  1.0.1-1-gfb51187
Build Time:  2016-09-07T22:41:38+0200
This is function one
mab@h2470988:~/projects/go/gomake/3/gomake$ ./gomake_f2
Version:  1.0.1-1-gfb51187
Build Time:  2016-09-07T22:41:39+0200
This is function two
Maciej A. Bednarz
sumber
5
Atau lebih sederhana: cukup buat dua main di dua direktori berbeda. Solusi ini tampaknya sangat direkayasa.
dolmen
26

Saya mengalami masalah dalam menggunakan -ldflagsparameter ketika membangun proyek command-line dan proyek perpustakaan saya, jadi saya akhirnya menggunakan target Makefile untuk menghasilkan file sumber Go yang berisi versi aplikasi saya dan tanggal pembuatan:

BUILD_DATE := `date +%Y-%m-%d\ %H:%M`
VERSIONFILE := cmd/myapp/version.go

gensrc:
    rm -f $(VERSIONFILE)
    @echo "package main" > $(VERSIONFILE)
    @echo "const (" >> $(VERSIONFILE)
    @echo "  VERSION = \"1.0\"" >> $(VERSIONFILE)
    @echo "  BUILD_DATE = \"$(BUILD_DATE)\"" >> $(VERSIONFILE)
    @echo ")" >> $(VERSIONFILE)

Dalam init()metode saya , saya melakukan ini:

flag.Usage = func() {
    fmt.Fprintf(os.Stderr, "%s version %s\n", os.Args[0], VERSION)
    fmt.Fprintf(os.Stderr, "built %s\n", BUILD_DATE)
    fmt.Fprintln(os.Stderr, "usage:")
    flag.PrintDefaults()
}

Namun, jika Anda menginginkan nomor build yang bertambah secara atomis daripada tanggal build, Anda mungkin perlu membuat file lokal yang berisi nomor build terakhir. Makefile Anda akan membaca konten file ke dalam variabel, menambahkannya, memasukkannya ke dalam version.gofile alih-alih tanggal, dan menulis nomor build baru kembali ke file.

pegli
sumber
2
Solusi bagus Namun, saya pikir saya telah menemukan alasan untuk masalah-tag. Jika file yang berisi variabel sedang diperbarui oleh -X tidak tersentuh, maka kompilasi tidak memicu dan Anda memiliki versi lama dalam biner. Solusi saya adalah menyentuh file kecil yang hanya berisi variabel yang diatur ulang melalui -ldflags "-X ..."
Wojciech Kaczmarek
20

Gunakan ldflagsuntuk mengatur variabel dalam mainpaket:

Dengan file main.go:

package main

import "fmt"

var (
    version string
    build   string
)

func main() {
    fmt.Println("version=", version)
    fmt.Println("build=", build)
}

Lalu lari:

go run \
  -ldflags "-X main.version=1.0.0 -X main.build=12082019" \ 
  main.go

Membangun:

go build -o mybinary \
  -ldflags "-X main.version=1.0.0 -X 'main.build=$(date)'" \ 
  main.go

Gunakan ldflagsuntuk mengatur variabel dalam suatu non-mainpaket:

Dengan file config.go:

package config

import "fmt"

var (
    Version string
)

func LogVersion() {
    fmt.Println("version=", Version)
}

Anda juga membutuhkan file main.go:

package main

import (
    "fmt"
    "github.com/user/repo/config"
}

func main() {
    config.LogVersion()
}

Bangun biner Anda terlebih dahulu:

go build -o mybinary main.go 

Temukan path lengkap nama variabel yang ingin Anda atur:

go tool nm <path_to_binary> | grep Version

Jalankan dan bangun biner lagi tetapi dengan ldflags:

go run \
  -ldflags "-X github.com/user/repo/config.Version=1.0.0" \
  main.go --version       


go build -o mybinary \
  -ldflags "-X github.com/user/repo/config.Version=1.0.0" \
  main.go     

Terinspirasi oleh https://github.com/golang/go/wiki/GcToolchainTricks#including-build-information-in-the-executable


Juga jika Anda menggunakan goreleasermaka baca https://goreleaser.com/#using-the-main-version ini :

GoReleaser bijaksana bawaan menetapkan tiga ldflags:

main.version: Current Git tag
main.commit: Current git commit SHA
main.date: Tanggal sesuai RFC3339


Jika Anda ingin melihat ini dalam tindakan: https://github.com/hoto/fuzzy-repo-finder/blob/master/pkg/config/config.go

Andrzej Rehmann
sumber
12

untuk menggunakan multi -ldflags:

$ go build -ldflags "-X name1=value1 -X name2=value2" -o path/to/output
Kimia Zhu
sumber
12

Pada Windows OS diberikan program di bawah ini

package main

import "fmt"

var (
    version string
    date    string
)

func main() {
    fmt.Printf("version=%s, date=%s", version, date)
}

Anda bisa membangun menggunakan

go build -ldflags "-X main.version=0.0.1 -X main.date=%date:~10,4%-%date:~4,2%-%date:~7,2%T%time:~0,2%:%time:~3,2%:%time:~6,2%"

Format tanggal mengasumsikan lingkungan Anda echo %date%adalah Fri 07/22/2016dan echo %time%sekarang16:21:52.88

Maka outputnya adalah: version=0.0.1, date=2016-07-22T16:21:52

Ostati
sumber