沙滩星空的博客沙滩星空的博客

Go语言ldflags编译参数的用法

缘起

在Github上,发现一些Go语言开源项目,构建时使用 go build -ldflags 语法。
通常将编译命令,写入 build.shMakefile 文件中。如下所示:

  • 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

未经允许不得转载:沙滩星空的博客 » Go语言ldflags编译参数的用法

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址