缘起
在Github上,发现一些Go语言开源项目,构建时使用 go build -ldflags
语法。
通常将编译命令,写入 build.sh
或 Makefile
文件中。如下所示:
- build.sh
#!/bin/bash
set -e
APP_NAME=$1
APP_VERSION=v$(cat version)
BUILD_VERSION=$(git log -1 --oneline)
BUILD_TIME=$(date "+%FT%T%z")
GIT_REVISION=$(git rev-parse --short HEAD)
GIT_BRANCH=$(git name-rev --name-only HEAD)
GO_VERSION=$(go version)
go build -ldflags " \
-X 'main.AppName=${APP_NAME}' \
-X 'main.AppVersion=${APP_VERSION}' \
-X 'main.BuildVersion=${BUILD_VERSION//\'/_}' \
-X 'main.BuildTime=${BUILD_TIME}' \
-X 'main.GitRevision=${GIT_REVISION}' \
-X 'main.GitBranch=${GIT_BRANCH}' \
-X 'main.GoVersion=${GO_VERSION}' \
" -o $APP_NAME
- Makefile
PROJECT_NAME:=zinx_server
VERSION:=v1
.PHONY: image run build clean
build:
bash build.sh ${PROJECT_NAME}
image:
docker build -t ${PROJECT_NAME}:${VERSION} .
run:
docker run -itd \
-p 8999:8999 \
${PROJECT_NAME}:${VERSION}
clean:
rm -rf ${PROJECT_NAME}
-ldflags 参数
-ldflags
参数的参数:-w
:去掉调试信息;-s
:去掉符号表;-X
:注入变量, 编译时赋值- 使用范围: go install, go build, go run, go test
-w 和 -s
go build -ldflags "-w -s" -mod vendor -race -v -o main main.go
如果使用这两个将会看不见文件名、行号, 对于调试不利. gdb看不到源码
-X 参数,注入变量
package main
import "fmt"
var Version = "0.0.1"
func main() {
fmt.Println(Version)
}
可以设置变量默认值,并修改变量
# 不注入变量
$ go build -o main main.go
$ ./main
0.0.1
# 注入变量
$ go build -ldflags "-X main.Version=0.0.9" -o main main.go
$ ./main
0.0.9
-ldflags
的 -X
参数, 可用于 任何软件包
,而不仅是main
包。
但是,必须指定 完整导入路径
,而不仅仅是软件 包名称
。如下所示:
go build -ldflags "-X 'app/config.Version=0.0.1' -X 'app/config.BuildTime=$(date)'"
有时您可能需要探索自己未在ldflags中编写的特定应用程序提供了什么功能,可以使用go tool随附的nm列出所有ldflags来实现此目的
$ go build -o app
$ go tool nm ./app
其他编译参数
去除开发路径信息:
CGO_ENABLED=0
# -w:去掉调试信息; -s:去掉符号表;
# win 使用 chdir 代替 PWD
CGO_ENABLED=0 go build -ldflags "-w -s \
-X 'main.AppVersion=v1.0.1' \
-X 'main.GoVersion=go version go1.19.4 windows/amd64'" \
-gcflags="all=-trimpath=${PWD}" \
-asmflags="all=-trimpath=${PWD}" \
-o v2raypool.exe .
or
go build -gcflags=-trimpath=$GOPATH -asmflags=-trimpath=$GOPATH -ldflags "-w -s"
参考:
https://stackoverflow.com/questions/45279385/remove-file-paths-from-text-directives-in-go-binaries
https://blog.csdn.net/kunyus/article/details/93467916
结论
正确使用 ldflags
, 可以在构建(编译)时,将有价值的信息注入二进制文件。
可以控制功能标志,环境信息,版本信息等,而无需对源代码进行更改。
将 ldflags
添加到当前的构建工作流中,可以最大限度地利用Go自带的二进制分发格式的好处。
go ldflags设置 https://www.cnblogs.com/bergus/articles/go-ldflags-she-zhi.html
Go:编译构建时 ldflags 变量注入 https://blog.csdn.net/test1280/article/details/123550802
关于go:如何在Golang构建中使用-ldflags -X设置软件包变量 https://www.codenong.com/47509272/
ldflags_使用ldflags设置Go应用程序的版本信息 https://blog.csdn.net/cukw6666/article/details/107986023