ldflags 与 CLI 版本信息 Go主题月

cli 的程序猿们应该都有一个烦恼吧,如何把版本信息写入程序以及最终生成的可执行的二进制文件,达到 cli -vcli --version 就可以显示版本信息的效果呢?

手动写入 或者 使用构建脚本 是我之前一直的做法,但今天我发现了另一个好办法,那就是使用 -ldflags 设置变量值。

手动写入

这种方式我就不多说了,就是每次构建发布之前手动把版本号等信息写入配置文件或代码中,非常容易遗忘或出错!

使用构建脚本

一般我的项目里都会有一个 Makefile 文件,通过 make 可以帮我们整合构建、测试等操作需要的步骤,之后只需要使用 make buildmake test 就可以进行构建或测试了,下面是简单的一个 Makefile

1
2
3
4
5
6
7
Makefile复制代码.PHONY build test

build:
go build -o cli main.go

test:
go test .

这时,我会在 Makefile 里写下面的内容进行设置版本信息:

1
2
3
4
Makefile复制代码VERSION = $(shell git tag --sort=committerdate | tail -n 1)

version:
sed -i "s/version = \".*\"/version = \"$(VERSION)\"/g" pkg/cmd/version.go

pkg/cmd/version.go 里有这么一段代码:

1
go复制代码const version = "dev"

-ldflags 上场

-ldflags 可以帮我们设置变量值,我们只需要在 Go 源码文件中定义好变量即可。

比如在 main.go 文件里定义三个版本信息相关的变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
go复制代码package main

var (
version string
commit string
date string
)

func main() {
args := os.Args
if len(args) == 2 && (args[1] == "--version" || args[1] == "-v") {
fmt.Printf("Release version: %s\n", version)
fmt.Printf("Git commit: %s\n", commit)
fmt.Printf("Build date: %s\n", date)
return
}

...
}

然后 Makefile 构建脚本这样写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Makefile复制代码NAME := cli
CGO_ENABLED = 0
BUILD_GOOS = $(shell go env GOOS)
GO := go
BUILD_TARGET = build
COMMIT := $(shell git rev-parse --short HEAD)
VERSION := dev-$(shell git describe --tags $(shell git rev-list --tags --max-count=1))
BUILD_FLAGS = -ldflags "-X main.version=$(VERSION) \
-X main.commit=$(COMMIT) \
-X main.date=$(shell date +'%Y-%m-%d')"
MAIN_SRC_FILE = main.go

.PHONY: build

build: pre-build
GO111MODULE=on CGO_ENABLED=$(CGO_ENABLED) GOOS=$(BUILD_GOOS) GOARCH=amd64 $(GO) $(BUILD_TARGET) $(BUILD_FLAGS) -o bin/$(BUILD_GOOS)/$(NAME) $(MAIN_SRC_FILE)
chmod +x bin/$(BUILD_GOOS)/$(NAME)
rm -rf $(NAME) && ln -s bin/$(BUILD_GOOS)/$(NAME) $(NAME)

这样便可以把我们要的版本信息写进最终生成的二进制文件中,而且不会修改源代码,nice 呀!

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%