แอปพลิเคชันสร้างเวอร์ชันอัตโนมัติ


193

เป็นไปได้ไหมที่จะเพิ่มหมายเลขรุ่นรองโดยอัตโนมัติทุกครั้งที่มีการรวบรวมแอพ

ฉันต้องการตั้งหมายเลขเวอร์ชันในโปรแกรมของฉันโดยมีส่วน autoincrementing อยู่:

$ myapp -version
MyApp version 0.5.132

เป็น 0.5 หมายเลขรุ่นที่ฉันตั้งไว้และ 132 ค่าที่เพิ่มขึ้นโดยอัตโนมัติในแต่ละครั้งที่รวบรวมไบนารี

เป็นไปได้ใน Go?

คำตอบ:


337

ตัวเชื่อมโยงไป (ตัวเชื่อมโยงไปที่เครื่องมือ ) มีตัวเลือกเพื่อตั้งค่าของตัวแปรสตริงที่ไม่ได้กำหนดค่าเริ่มต้น:

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

ความคุ้มค่า โปรดทราบว่าก่อนที่จะไป 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?
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 ทำสิ่งนี้เพื่อคุณ :) โดยค่าเริ่มต้นจะคอมไพล์ด้วย -ldflags "-Xmain.VERSION xxx -Xmain.BUILD_DATE CurrentDateInISO8601" แต่คุณสามารถกำหนดชื่อตัวแปรเหล่านั้นได้หากต้องการ ดูgithub.com/laher/goxc ... (ข้อจำกัดความรับผิดชอบ: ฉันเขียน goxc)
laher

7
ตัวอย่างการทำงานกับ 1.5 ไวยากรณ์ใหม่สำหรับการเพิ่มตัวแปร buildtimego build -ldflags "-X 'main.buildtime=$(date -u '+%Y-%m-%d %H:%M:%S')'"
xorpaul

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
หรือง่ายกว่า: สร้างสองหลักในสองไดเรกทอรีที่แตกต่างกัน การแก้ปัญหานี้ดูเหมือนจะถูก overengineered อย่างจริงจัง
dolmen

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 ... "
Wojciech Kaczmarek

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#including-build-information-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

บน 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.