Wersja automatycznego budowania aplikacji
Czy możliwe jest automatyczne zwiększanie podrzędnego numeru wersji za każdym razem, gdy aplikacja Go jest kompilowana?
Chciałbym ustawić numer wersji w moim programie, z sekcją autoincrementing:
$ myapp -version
MyApp version 0.5.132
Jest 0.5 numerem wersji, który ustawiłem, a 132 wartością, która zwiększa się automatycznie za każdym razem, gdy plik binarny jest kompilowany.
Czy to możliwe w Go?7 answers
Go linker (go tool link) ma możliwość ustawienia wartości niezainicjalizowanej zmiennej łańcuchowej:
-X importpath.name=value Set the value of the string variable in importpath named name to
Wartość. Zauważ, że przed Go 1.5 ta opcja przyjmowała dwa oddzielne argumenty. Teraz wymaga podziału jednego argumentu na pierwszy znak=.
Jako część procesu budowania, możesz ustawić zmienną ciągu wersji używając tego. Możesz to przekazać za pomocą narzędzia go
za pomocą narzędzia -ldflags
. Na przykład, biorąc pod uwagę następujące źródło plik:
package main
import "fmt"
var xyz string
func main() {
fmt.Println(xyz)
}
Potem:
$ go run -ldflags "-X main.xyz=abc" main.go
abc
Aby ustawić main.minversion
na datę i godzinę budowy:
go build -ldflags "-X main.minversion=`date -u +.%Y%m%d.%H%M%S`" service.go
Jeśli skompilujesz bez inicjalizacji main.minversion
w ten sposób, będzie on zawierał pusty łańcuch znaków.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-28 20:10:03
Dodatkowo chciałbym zamieścić mały przykład jak używać git i 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
Plik make utworzy dwa pliki wykonywalne. Jeden wykonuje funkcję jeden, drugi przyjmuje funkcję drugą jako wejście główne:
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]()
}
Następnie po prostu uruchom:
make
Otrzymasz:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-07 20:48:42
Miałem problemy z użyciem parametru -ldflags
podczas budowania mieszanej aplikacji wiersza poleceń i projektu biblioteki, więc skończyło się na użyciu pliku docelowego Makefile do wygenerowania pliku źródłowego go zawierającego wersję mojej aplikacji i datę kompilacji:
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)
W mojej metodzie init()
robię to:
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()
}
Jeśli jednak chcesz zwiększyć liczbę kompilacji atomicznie zamiast daty kompilacji, prawdopodobnie będziesz musiał utworzyć plik lokalny, który zawierał ostatni numer kompilacji. Twój plik Makefile odczytałby plik zawartość do zmiennej, zwiększ ją, Wstaw ją do pliku version.go
zamiast daty i zapisz nowy numer kompilacji z powrotem do pliku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-28 20:26:32
Użyj ldflags
aby ustawić zmienne w main
pakiecie:
Z plikiem main.go
:
package main
import "fmt"
var (
version string
build string
)
func main() {
fmt.Println("version=", version)
fmt.Println("build=", build)
}
Następnie uruchom:
go run \
-ldflags "-X main.version=1.0.0 -X main.build=12082019" \
main.go
Budowa:
go build -o mybinary \
-ldflags "-X main.version=1.0.0 -X 'main.build=$(date)'" \
main.go
Użyj ldflags
aby ustawić zmienną w pakiecie non-main
:
Z plikiem config.go
:
package config
import "fmt"
var (
Version string
)
func LogVersion() {
fmt.Println("version=", Version)
}
Potrzebny będzie również plik main.go
:
package main
import (
"fmt"
"github.com/user/repo/config"
}
func main() {
config.LogVersion()
}
Najpierw Zbuduj swój plik binarny:
go build -o mybinary main.go
Znajdź pełną ścieżkę nazwy zmiennej, którą chcesz ustawić:
go tool nm <path_to_binary> | grep Version
Uruchom i zbuduj plik binarny ponownie, ale z 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
Zainspirowany https://github.com/golang/go/wiki/GcToolchainTricks#including-build-information-in-the-executable
Również jeśli używasz goreleaser
to przeczytaj to https://goreleaser.com/environment/#using-the-mainversion :
Default wise GoReleaser ustawia trzy ldflags:
Main.version: Current Git tag
main.commit: bieżący git commit SHA
main.Data: Data według RFC3339
Jeśli chcesz zobaczyć to w akcji: https://github.com/hoto/fuzzy-repo-finder/blob/master/pkg/config/config.go
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-13 09:04:31
Aby użyć multi -ldflags
:
$ go build -ldflags "-X name1=value1 -X name2=value2" -o path/to/output
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-18 02:29:38
W systemie operacyjnym Windows podany poniżej program
package main
import "fmt"
var (
version string
date string
)
func main() {
fmt.Printf("version=%s, date=%s", version, date)
}
Możesz budować używając
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 daty zakłada, że Twoje środowisko echo %date%
to Fri 07/22/2016
, a echo %time%
to 16:21:52.88
Następnie wyjście będzie: version=0.0.1, date=2016-07-22T16:21:52
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-22 20:28:31
Bazując na innych odpowiedziach, w ostatnich wersjach go można również napisać buildid do sekcji ELF - choć nie jest to tak łatwe do odczytania z poziomu programu.
Piszę tę samą wartość do obu, używając czegoś takiego jak:
BuildInfo:= "BUILD #x, branch @ rev built yymmdd hh:mm:ss"
// note the nested quotes "''" required to get a string with
// spaces passed correctly to the underlying tool
ldFl := fmt.Sprintf("-X 'main.buildId=%s' -s -w '-buildid=%s'", BuildInfo, BuildInfo)
args := []string{
"build",
"-ldflags", ldFl,
"-trimpath",
"-gcflags", "-dwarf=false",
}
buildpath:="path/to/my/cmd"
args=append(args,buildpath)
buildCmd:=exec.Command("go", args...)
Używam tego z mage
, narzędziem do budowania napisanym w go. Nie potrzebujesz dodatkowych FLAG powyżej, ale wybrałem te, aby usunąć jak najwięcej informacji z plików binarnych wydania.
(off topic: Mage wymaga nieco więcej praca z góry niż coś w rodzaju Make, ale jest o wiele łatwiejsze do rozszerzenia/utrzymania niż system budowania oparty na make-plus nie musisz przełączać mentalnych biegów między go a inną składnią.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-15 00:13:23