flyhigh

Use your source, Luke!

Goプログラムのサイズを小さくする

Goで作られるプログラムサイズはそこそこ大きい。配布する場合はやはり小さい方が良い。 そんなときは、リンカの設定を利用するといいようだ。

1
go build -ldflags '-s -w'

Linuxならバイナリサイズが小さくなるはずだ。拙作、comstockでは8MiBから5.2MiBに縮んだ。

何をやっているか?

-ldflagsは、gccなどを使ったことある方はよくご存知だろうが、ldへの引数である。 ldとはgccが使うリンカであり、Goもリンカを持っている。Goのリンカは、例えば、go tool 6l(番号はアーキテクチャ依存)から呼び出せる。伝統的にリンカへのフラグは LDFLAGSであるので、goでは小文字で指定するようになってる。

go buildはリンカへの引数を-ldflagsの後で文字列として渡すことができる。

指定できるリンカフラグは様々で、標準ドキュメントよりもgo 1.4では数が増えているように見える。とりあえず、上で使ったのは以下の2つだ。

1
2
-s    disable symbol table
-w    disable DWARF generation

シンボルテーブルは、シンボルと、シンボルの位置(アドレス)が記述された表である。

1
2
➜  nm `which comstock-cli` | grep Log | grep Printf
000000000007d8c0 t log.(*Logger).Printf

例えば、上はLogger.Printf()の位置を示している。

このシンボルテーブルは外部から参照することがない限り、 不必要だ。 よって、-sを渡して削る。 ちなみに、ビルドしてるのがライブラリだったり、ビルド後に デバッガを使う場合は、シンボルテーブルは必要になるので、削ってはいけない。

DWARFというのは、Linuxの実行可能形式であるELFに付属する デバッグ情報である。 こちらも配布用のプログラムには必要無い。よって-wで削る。 こちらはデバッグしない限り、ライブラリでも削って良い。

darwinではELFではなくMach-Oという実行可能形式を用いるため、DWARFはそもそも生成されない。 シンボルテーブルは削れると思うが、私の環境では削れてなかった。 とりあえずLinuxで縮んだので良しとする。

参考

Command ld (Go document)

Golang application auto build versioning ※直接関係ないが、ldflag利用の一例。