Версія автоматичного складання версії


193

Чи можна автоматично збільшувати незначний номер версії щоразу, коли компілюється програма Go?

Я хотів би встановити номер версії всередині своєї програми з розділом для автоматичного підвищення:

$ myapp -version
MyApp version 0.5.132

Будучи рівним 0,5 номеру версії, яку я встановив, і 132 - значення, яке автоматично збільшується кожного разу, коли двійковий компілюється.

Чи можливо це в Go?

Відповіді:


337

У лінкері Go ( посилання інструменту go ) є можливість встановити значення неініціалізованої змінної рядка:

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

значення. Зауважте, що до Go 1.5 ця опція брала два окремі аргументи. Тепер потрібно один аргумент, розділений на перший знак =.

У рамках процесу збирання ви можете встановити змінну рядка версії, використовуючи цю функцію. Ви можете передати це через goінструмент, використовуючи -ldflags. Наприклад, з урахуванням наступного вихідного файлу:

package main

import "fmt"

var xyz string

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

Тоді:

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

Щоб встановити main.minversionдату та час побудови під час будівництва:

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

Якщо ви компілюєте без ініціалізації main.minversionтаким чином, він буде містити порожній рядок.


4
Чи збереже це значення у двійкове, якщо я використовую go bouildзамість go run?
Себастьян Гриньолі

6
go build -ldflags "-X main.minversion `date -u +.%Y%m%d%.H%M%S`" service.go
Себастьян Гриньолі

4
goxc робить це для вас :), за замовчуванням він компілює з -ldflags "-Xmain.VERSION xxx -Xmain.BUILD_DATE CurrentDateInISO8601", але ви можете налаштувати ці імена змінних, якщо вам це подобається. Дивіться github.com/laher/goxc ... (відмова: я писав goxc)
laher

7
робочий приклад з новим синтаксисом 1.5 для додавання змінної go build -ldflags "-X 'main.buildtime=$(date -u '+%Y-%m-%d %H:%M:%S')'"
buildtime

26
зауважте, що потрібна повна назва пакета. go build -ldflags "-X pkg.version=123"не працюватиме, поки go build -ldflags "-X path/to/pkg.version=123"працювати, як очікувалося. сподіваюся, що це допомагає.
csyangchen

27

Крім того, я хотів би опублікувати невеликий приклад, як використовувати git та 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

Файл make створить два виконуваних файли. Один виконує функцію один, інший буде приймати функцію два як основний запис:

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]()

}

Тоді просто запустіть:

make

Ти отримаєш:

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

5
Або простіше: просто зробіть два основних в двох різних каталогах. Це рішення, схоже, серйозно переосмислене.
долмен

26

У мене виникли проблеми з використанням -ldflagsпараметра під час створення мого змішаного проекту програми та бібліотеки, тому я в кінцевому підсумку використовував ціль Makefile, щоб генерувати вихідний файл Go, що містить версію мого додатка та дату складання:

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)

У своєму init()методі я роблю це:

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()
}

Якщо ви хотіли атомно зростаюче число збірки замість дати складання, однак, ймовірно, вам потрібно буде створити локальний файл, який містив би номер останньої збірки. Ваш Makefile буде читати вміст файлу в змінну, збільшувати його, вставляти його у version.goфайл замість дати та записувати новий номер збірки назад у файл.


2
Приємне рішення. І все-таки я думаю, що я знайшов причину для проблем -ldflags. Якщо файл, що містить змінну, що оновлюється на -X, не торкається, то компіляція не запускається, і у вас є стара версія у двійковій. Моє рішення було торкнутися невеликого файлу, що містить лише змінну, яка скидається через -ldflags "-X ..."
Войцех Качмарек

20

Використовуйте ldflagsдля встановлення змінних уmain пакеті:

З файлом main.go:

package main

import "fmt"

var (
    version string
    build   string
)

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

Потім запустіть:

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

Побудувати:

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

Використовуйте ldflagsдля встановлення змінної в anon-main пакеті:

З файлом config.go:

package config

import "fmt"

var (
    Version string
)

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

Вам також знадобиться файл main.go:

package main

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

func main() {
    config.LogVersion()
}

Створіть свій двійковий файл спочатку:

go build -o mybinary main.go 

Знайдіть повний шлях імені змінної, який ви хочете встановити:

go tool nm <path_to_binary> | grep Version

Запустіть і складіть бінарний файл ще раз, але з 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     

Натхненний https://github.com/golang/go/wiki/GcToolchainTricks#including-build-information-in-the-executable


Також якщо ви користуєтесь, goreleaserпрочитайте це https://goreleaser.com/#using-the-main-version :

Мудрий GoReleaser за замовчуванням встановлює три ldflags:

main.version: Поточний тег Git
main.commit: Поточний git фіксація SHA
main.date: Дата згідно RFC3339


Якщо ви хочете побачити це в дії: https://github.com/hoto/fuzzy-repo-finder/blob/master/pkg/config/config.go


12

використовувати мульти -ldflags:

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

12

У ОС Windows задано програму нижче

package main

import "fmt"

var (
    version string
    date    string
)

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

Ви можете будувати, використовуючи

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%"

Формат дати передбачає, що ваше середовище echo %date%є Fri 07/22/2016і echo %time%є16:21:52.88

Тоді вихід буде: version=0.0.1, date=2016-07-22T16:21:52

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.