# Go Build Flags


## ldflags
ldflags用于将标志传递给编译器链接器（ld）。
- -s: 去掉符号表信息，减小可执行文件的大小。
- -w: 去掉DWARF调试信息，减小可执行文件的大小。
- -X: 设置字符串变量，用于编译时注入程序版本等信息。例如，-X main.version=1.0.0
- -H: 设置堆的大小。例如，-H=0 表示禁用堆。
- -extldflags: 用于将标志传递给链接器。

### 在构建时设置一个环境变量

一个非常方便的构建标志，允许你在构建时从命令行设置一个变量。看下面的例子。

```go
package main

import (
    "fmt"
)

var who string

func main() {
    fmt.Printf("Hello, %s\n", who)
}
```

使用默认值我们得到以下结果。

```bash
$ go run main.go
Hello,


```

通过添加`-X`链接器标志，我们可以在编译时改变`who`。这只是一个愚蠢的例子，但这对于在编译时更新二进制文件的版本信息很有用。

```bash
$ go run -ldflags "-X main.who=Kira" main.go
Hello, Kira
```

`symbol table`可以使用`go tool nm`命令查看。只需将可执行文件、对象文件或存档的名称传递给它。让你自己更轻松，只需在输出中寻找你的变量即可。

```bash
$ go tool nm main | grep who
  555bf0 D main.who
```

### 缩小你的Go二进制

go的版本为`1.15.6`，有原来的`2M`压缩成了`1.4M`。

我们可以用以下标志省略`symbol table`、调试信息和DWARF表。可以用以下标志省略： `-s -w`

```bash
$ go version
go version go1.15.6 linux/amd64

$ go build -ldflags "-s -w" -o main-s-w
$ ls -alh
总用量 3.4M
drwxrwxr-x 2 kira kira  116 Jan 13 15:24 .
drwxrwxrwx 7 kira kira  114 Jan 12 12:20 ..
-rwxrwxr-x 1 kira kira 2.0M Jan 13 15:21 main
-rw-rw-r-- 1 kira kira  103 Jan 13 15:17 main.go
-rwxrwxr-x 1 kira kira 1.4M Jan 13 15:24 main-s-w

```

最好的可执行文件打包器之一是[UPX](https://upx.github.io/)。它使用起来非常简单。我用`-9`运行它，以速度为代价获得最大的压缩。

```bash
$ go build
$ go build -ldflags "-s -w" -o main-s-w
$ upx -9 -o main-s-w-upx main-s-w
                       Ultimate Packer for eXecutables
                          Copyright (C) 1996 - 2018
UPX 3.95        Markus Oberhumer, Laszlo Molnar & John Reiser   Aug 26th 2018

        File size         Ratio      Format      Name
   --------------------   ------   -----------   -----------
   1400832 ->    558868   39.90%   linux/amd64   main-s-w-upx

Packed 1 file.

$ ls -alh
总用量 3.9M
drwxrwxr-x 2 kira kira   89 Jan 13 15:35 .
drwxrwxrwx 7 kira kira  114 Jan 12 12:20 ..
-rw-rw-r-- 1 kira kira  140 Jan 13 15:34 main.go
-rwxrwxr-x 1 kira kira 2.0M Jan 13 15:35 main
-rwxrwxr-x 1 kira kira 1.4M Jan 13 15:35 main-s-w
-rwxrwxr-x 1 kira kira 546K Jan 13 15:35 main-s-w-upx

```

### 没有控制台窗口的Windows可执行文件

我觉得当我运行一个exe时，打开一个控制台窗口很不美观，而且我不需要看到任何输出。

只要在你的链接器标志中添加`"-H=windowsgui"`。控制台窗口消失了。欢迎你。

```bash
C:\Users\Luke\go\src\hello>go build -ldflags "-X main.who=Universe -H=windowsgui -s -w"
```



## gcflags

- -N: 禁用优化。使用这个标记编译程序时，将禁用所有优化，这对于调试程序非常有用。
- -l: 关闭内联编译器。通过这种方式可以控制内联编译器的行为，但是要注意关闭内联编译器可能会导致性能问题。
- -m: 打印内存分配的信息，包括在哪里发生了内存分配以及分配的类型。
- -B: 设置最大的过程编译器的字节数。
- -S: 将汇编代码打印到标准输出中。这对于调试优化程序非常有用，可以让开发人员更好地理解程序中发生了什么。

```bash
# 查看选项
go tool compile -help
```

### 使用案例

- `go build -gcflags="-N -l"`： 禁止优化，禁止内联
- `go build -gcflags="-m -l"`:  观察内存逃逸

---

[Compile packages and dependencies](https://pkg.go.dev/cmd/go#hdr-Compile_packages_and_dependencies)

