Go Build 参数详解

go build 是用于构建 Go 程序的命令。它有许多参数和选项,可以控制编译过程。以下是一些常用参数及其详解:

基本使用

1
go build [build flags] [packages]

go build 默认在当前目录中查找 main 包并生成可执行文件。

常用参数和选项

  1. -o 输出文件名

    1
    go build -o outputfile

    指定生成的可执行文件的名称。如果不指定,默认生成一个与所在目录或包名相同的可执行文件。

  2. -a

    1
    go build -a

    强制重新构建所有依赖的包,即使它们已经是最新的。

  3. -n

    1
    go build -n

    打印出需要执行的编译命令,但不实际执行它们(build 动作)。这对于调试编译过程非常有用。

  4. -v

    1
    go build -v

    显示正在构建的包的名称。

  5. -x

    1
    go build -x

    打印所有运行的命令。

  6. -race

    1
    go build -race

    启用数据竞争检测。仅适用于 64 位架构的 Linux、macOS 和 Windows 系统。

  7. -ldflags

    1
    go build -ldflags="-s -w"

    传递给连接器的标志。常见的标志有 -s(省略符号表)和 -w(省略调试信息)。

  8. -tags

    1
    go build -tags="tag1 tag2"

    设置编译标签,用于选择性地包括或排除代码。

  9. -gcflags

    1
    go build -gcflags="all=-N -l"

    传递给编译器的标志。例如 -N 禁用优化,-l 禁用内联。

  10. -mod

    1
    go build -mod=mod

    指定使用哪种模块下载模式(readonlyvendor)。

  11. -trimpath

    1
    go build --trimpath=$GOPATH

    删除编译包含的固定路径信息,报错信息打印时只会包含文件的相对路径。

  12. -modfile

    1
    go build --modfile=xxx.mod

    指定使用的modfile文件,但go.mod文件依然是需要的,用于确认编译包的根目录,gosum依然是需要的,如传入的xx.mod, 则需要或对应生成为 xx.sum

  13. -p

    1
    go build -p 8

    开多少核cpu来并行编译,默认为本机CPU核数。

  14. -work

    1
    go build -work=./temp

    打印临时工作目录的名称,并在退出时不删除它。

部分命令详解

ldflags

-ldflags 基本语法

-ldflags 参数用于向 Go 语言的链接器传递特定的标志。这个参数可以用来控制生成的可执行文件的属性,比如嵌入版本信息、移除符号表和调试信息等。

1
go build -ldflags="flag1 flag2 ..."

常用的 -ldflags 标志

  1. -s-w

    • -s: 移除符号表,可以减小生成的二进制文件的大小。
    • -w: 移除调试信息,可以进一步减小二进制文件的大小。
    • 合并使用 -s -w 通常会显著减小二进制文件的大小。
    1
    go build -ldflags="-s -w"
  2. -X importpath.name=value

    • 用于设置包内变量的值。这通常用于设置编译时的变量,例如版本号、构建时间等。
    • importpath 是变量所在包的导入路径,name 是变量名,value 是要设置的值。
    1
    go build -ldflags="-X 'main.version=1.0.0' -X 'main.buildTime=$(date)'"
  3. -linkmode

    • 指定链接模式。常用的值有 internalexternal。默认为 internal
    • internal: 默认的链接模式,使用 Go 自身的链接器。
    • external: 使用外部链接器(例如 gcc)。
    1
    go build -ldflags="-linkmode=external"
  4. -extld

    • 指定外部链接器。如果使用 -linkmode=external,可以使用此标志指定具体的链接器。
    1
    go build -ldflags="-linkmode=external -extld=gcc"
  5. -extldflags

    • 传递特定标志给外部链接器。例如,可以使用这个标志传递优化参数或其他链接选项。
    1
    go build -ldflags="-linkmode=external -extldflags='-static'"

示例

  1. 移除符号表和调试信息

    1
    go build -ldflags="-s -w"
  2. 设置编译时变量

    1
    go build -ldflags="-X 'main.version=1.2.3' -X 'main.commitHash=abcdefg'"
  3. 使用外部链接器并传递标志

    1
    go build -ldflags="-linkmode=external -extldflags='-static'"

使用 -X 设置编译时变量的完整示例

假设有一个 Go 程序需要在编译时注入版本号和构建时间:

main.go:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
"fmt"
)

var (
version string
buildTime string
)

func main() {
fmt.Printf("Version: %s\n", version)
fmt.Printf("Build Time: %s\n", buildTime)
}

构建命令:

1
go build -ldflags="-X 'main.version=1.0.0' -X 'main.buildTime=$(date)'"

执行生成的可执行文件将输出:

1
2
Version: 1.0.0
Build Time: <当前日期>

通过使用 -ldflags,你可以在构建时自定义许多编译和链接行为,以满足特定的需求。

gcflags

-gcflags 基本语法

-gcflags 参数用于向 Go 语言的编译器传递特定的标志。这个参数可以控制编译器的行为,例如禁用优化、禁用内联、设置特定的编译选项等。

1
go build -gcflags="flags"

常用的 -gcflags 标志

  1. -N

    • 禁用优化。这个选项对于调试代码非常有用,因为优化可能会使得调试器难以跟踪代码的执行。
      1
      go build -gcflags="-N"
  2. -l

    • 禁用内联。内联是编译器优化的一部分,它将函数的代码直接插入调用它的地方。这也可以让调试更容易。
      1
      go build -gcflags="-l"
  3. -m

    • 输出优化的详细信息。这个选项可以帮助理解编译器进行了哪些优化。
      1
      go build -gcflags="-m"
  4. -e

    • 即使有编译错误,继续进行编译。这在希望查看所有编译错误时很有用。
      1
      go build -gcflags="-e"
  5. -S

    • 输出编译的汇编代码。可以帮助了解 Go 代码如何被编译成机器码。
      1
      go build -gcflags="-S"
  6. -B

    • 禁用边界检查。可以使得运行时跳过数组和切片的边界检查,但是可能导致不安全的访问。
      1
      go build -gcflags="-B"

针对特定包设置 -gcflags

可以使用 all= 前缀应用于所有包,也可以对特定包应用不同的标志。

  1. 应用于所有包

    1
    go build -gcflags="all=-N -l"
  2. 应用于特定包

    1
    go build -gcflags="path/to/package=-N -l"

示例

  1. 禁用所有包的优化和内联

    1
    go build -gcflags="all=-N -l"
  2. 输出优化信息

    1
    go build -gcflags="-m"
  3. 输出编译的汇编代码

    1
    go build -gcflags="-S"
  4. 禁用特定包的边界检查

    1
    go build -gcflags="path/to/package=-B"

gcflag传入的方式为:-gcflag="pattern= args,其中pattern代表取值分别为 main,all,std,...,用于指定编译参数作用的范围,args则为对应的编译参数。

  • main: 表示 main 函数所在的顶级包路径;
  • all: 表示 GOPATH 中的所有包。如果在 modules 模式下,则表示主模块和它所有的依赖,包括 test 文件的依赖;
  • std: 表示 Go 标准库中的所有包;
  • ...: ... 是一个通配符,可以匹配任意字符串(包括空字符串)。例如:
    • 例如: net/... 表示 net 模块和它的所有子模块
    • ./... 表示当前主模块和所有子模块
    • 注意: 如果 pattern 中包含了 /...,那么就不会匹配 vendor 目录
      • 例如: ./... 不会匹配 ./vendor 目录。可以使用 ./vendor/... 匹配 vendor 目录和它的子模块。

使用 -gcflags 的完整示例

假设有一个 Go 程序 main.go

1
2
3
4
5
6
7
8
9
package main

import (
"fmt"
)

func main() {
fmt.Println("Hello, World!")
}

你希望在调试过程中禁用优化和内联:

1
go build -gcflags="-N -l"

通过这个命令构建的可执行文件将不会进行优化和内联,使得调试器更容易跟踪代码的执行。

通过使用 -gcflags,你可以灵活地控制编译器的行为,从而更好地调试和优化你的 Go 程序。


Go Build 参数详解
https://randzz.cn/9322d1e0c6ae/go-build-参数详解/
作者
Ezreal Rao
发布于
2024年7月15日
许可协议