当通过ldflags选项传递w标志到go命令时,它是什么意思?

45

背景:

go 1.2,ubuntu 12.10

目标:

减小编译后二进制文件的大小

当前在我的构建过程中,我运行 "go install" 命令来生成二进制文件。 然后我从某个地方读到,如果我传入 -w 标志,它会使二进制文件缩小。 我尝试通过将其传递给 -ldflags 选项来使用它,并且我的二进制文件减小了1MB。

  1. 这个 -w 标志在任何地方有文档记录吗?它实际上是做什么用的?
  2. 然后我发现了 strip -s <binary> 命令,并在 -w 的基础上运行该命令,又获得了750KB的减小!结果二进制文件可以正常运行。在任何情况下剥离(strip)都会导致问题吗?
4个回答

78
如果使用 -ldflags '-w -s'进行编译,则可以得到最小的二进制文件。其中 -w 关闭了DWARF调试信息,因此您将无法使用 gdb 在二进制文件上查看特定函数或设置断点或获取堆栈跟踪,因为所有元数据 gdb 需要的元数据都不会包括在内。您也将无法使用其他依赖于该信息的工具,例如 pprof 分析工具。 -s 关闭了Go符号表的生成,因此您将无法使用 go tool nm 列出二进制文件中的符号。 strip-s 就像是将 -s 传递给 -ldflags 一样,但它没有剥离那么多。在进行 strip-s 后, go tool nm 可能仍然有效,但我并不能完全确定。这些选项都不应影响实际程序的执行。它们只影响您能否使用其他工具对程序进行调试或分析。

请注意,如果您运行的是1.2之前的版本,则剥离符号可能会导致程序出现异常。我不记得确切地是在1.2中进行了哪些更改来解决这个问题,但某些操作(例如使用运行时包查询函数指针名称)以前会因为符号已被剥离而使程序崩溃。 - joshlf

22

你可以从go tool link获得帮助

$ go tool link
  ...
  -s    disable symbol table
  -w    disable DWARF generation

16

go help build命令显示:

-ldflags 'flag list'
    arguments to pass on each 5l, 6l, or 8l linker invocation. 

因此,我们可以调用 go tool 6l 来查看它的所有选项。其中之一是

-w  disable DWARF generation 

顺便提一下,5l 代表 ARM 架构 ($GOARCH = arm),6l 代表 x86-64 架构 ($GOARCH = amd64),而 8l 则是 x86 架构 ($GOARCH = 386)。

如果你真的想查看原始的 DWARF 信息,你应该在 OS X 上使用 dwarfdump -a,在 Linux 上使用 objdump -wg。注意!输出将会非常长。


什么将数字映射到架构?为什么5l是ARM,6l是x86-64,8l是x86? - Omar Darwish

0

我担心这可能会在使用Go 1.2的gc工具套件编译的程序中引起问题-请参阅this discussion

总的来说,虽然Go像C一样编译成机器代码,但它比C更高级。例如,它内置了详细的panic()堆栈跟踪,这取决于调试信息。 gc生成的二进制文件的大小确实可以更小,并且在开发Go 1.3时可能会解决此问题,但是在今天的大多数环境中,编译程序的大小并不是一个值得过度关注的大问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接