응용 프로그램 자동 빌드 버전 관리


193

Go 앱이 컴파일 될 때마다 마이너 버전 번호를 자동으로 증가시킬 수 있습니까?

자동 증분 섹션과 함께 프로그램 내부에 버전 번호를 설정하고 싶습니다.

$ myapp -version
MyApp version 0.5.132

내가 설정 한 버전 번호가 0.5이고 132는 바이너리가 컴파일 될 때마다 자동으로 증가하는 값입니다.

Go에서 가능합니까?

답변:


337

Go 링커 ( go tool link )에는 초기화되지 않은 문자열 변수의 값을 설정하는 옵션이 있습니다.

-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됩니까?
세바스티안 그리 gno 리

6
go build -ldflags "-X main.minversion `date -u +.%Y%m%d%.H%M%S`" service.go
세바스티안 그리 gno 리

4
goxc는이를 위해 :) 기본적으로 -ldflags "-Xmain.VERSION xxx -Xmain.BUILD_DATE CurrentDateInISO8601"로 컴파일하지만 원하는 경우 해당 변수 이름을 구성 할 수 있습니다. github.com/laher/goxc ... 참조 (면책 조항 : goxc를 썼습니다)
laher

7
빌드 go build -ldflags "-X 'main.buildtime=$(date -u '+%Y-%m-%d %H:%M:%S')'"
타임

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 파일은 두 개의 실행 파일을 만듭니다. 하나는 기능 하나를 실행하고 다른 하나는 기능 2를 기본 항목으로 사용합니다.

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에 의해 업데이트되는 변수를 포함하는 파일을 건드리지 않으면 컴파일이 트리거되지 않으며 바이너리에 이전 버전이 있습니다. 내 솔루션 "... -X"-ldflags를 통해서만중인 변수 리셋을 포함하는 작은 파일을 터치했다
우치 에크 카츠 마렉

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에서 변수를 설정하는 데 사용하십시오 non-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#include-build-information-in-the-exe에서 영감을 받음


또한 사용하는 경우 https://goreleaser.com/#using-the-main-versiongoreleaser 을 읽으십시오 .

기본 현명한 GoReleaser는 3 개의 ldflag를 설정합니다.

main.version : 현재 Git 태그
main.commit : 현재 git commit 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 OS에서

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.