Der Vorteil bei der Programmiersprache Go ist, dass eine .go-Quelldatei direkt mit einem einfachen
go run <dateiname.go>
ausgeführt werden kann. Damit kann man in einfacher Weise prüfen ob der Quellcode während des Compilevorgangs Fehlerfrei durchlaufen würde.
Will man nun eine lauffähige Binärdatei erhalten, verwendet man:
go build <dateiname.go>
Je nach Anzahl und Größe des Umfangs des Codes und der eingebundenen Bibliotheken und Pakete kann die fertigen Binärdatei recht groß werden.
Damit sind ~10MB für ein kleines Tool möglich. Das rührt natürlich daher, dass die fertige Binärdatei statisch alle Bibliothken gelinkt und somit inkludiert hat.
Tunning?
Es gibt ein paar Wege um eine Binärdatei zu „schrumpfen“.
Der erste Weg wäre direkt beim Go-Compiler. Hier kann man mithilfe entsprechender Compiler-Flags ein paar MB sparen.
go build -ldflags="-s -w" <dateiname.go>
macht aus einer 7,9 MB großen Binärdatei (ohne Compiler-Flags) recht schlanke 2,8MB (mit Compiler-Flags).
-s —> Omit the symbol table and debug information.
-w —> Omit the DWARF symbol table.
Geht es noch kleiner?
Es gibt noch die Möglichkeit die Binärdatei direkt zu packen. Hierfür bietet sich upx an.
UPX (Ultimate Packer for eXecutables, engl. für Ultimativer Packer für ausführbare Dateien) ist ein freies (GNU General Public License) Packprogramm für ausführbare Dateien, das eine Reihe von Formaten unterstützt.
UPX eignet sich besonders zur Komprimierung von Unix-ELF (32- und 64-Bit), DOS-EXE (16- und 32-Bit), Windows-PE (EXE und DLL) oder auch TOS-Dateien. Im Unterschied zu den mittels weitverbreiteter Komprimierungsverfahren (wie ZIP und RAR) komprimierten Dateien lassen sich mit UPX komprimierte Dateien normal (also ohne vorige Entpackung) ausführen.
Wikipedia
Wenn man hier also noch nach dem Compilen mit den ldflags noch mit upx die Binärdatei komprimiert beträgt die finale Größe noch ca. 930 KB.
Von ca. 8MB auf knapp 930KB…
upx -f --brute <dateiname>
Allerdings kann es vorkommen, dass die mit upx gepackten Binärdateien vereinzelt „Segmentation Fault“ beim ausführen werfen. Das ist mir bisher recht selten passiert, aber es passiert.
Hier mal noch ein kleines Bash-Script welches die angesprochenen Methoden verwendet:
#! /bin/sh
FILE=$1
gofmt -w $1
go build -race -o ${FILE%%.*}_full "$1"
GOOS=linux go build -ldflags="-s -w" -o ${FILE%%.*} "$1"
upx -f --brute ${FILE%%.*}
ls -lh ${FILE%%.*}*
Eine Ausgabe sieht entsprechend so aus:
--> ~/gobuild.sh main.go
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2013
UPX 3.91 Markus Oberhumer, Laszlo Molnar & John Reiser Sep 30th 2013
File size Ratio Format Name
-------------------- ------ ----------- -----------
2935976 -> 951680 32.41% linux/ElfAMD main
Packed 1 file.
-rwxrwxr-x 1 rasputin rasputin 930K Nov 20 13:02 main
-rwxrwxr-x 1 rasputin rasputin 8,0M Nov 20 13:02 main_full
-rw-rw-r-- 1 rasputin rasputin 1,4K Nov 20 11:37 main.go
Wobei die „dateiname“_full Datei die komplett unkomprimierte Binärdatei ist.
Das Script findet sich auch auf Github