我們都知道在不涉及 CGO 的時候,Go 的交叉編譯非常簡單,只需要設置對應的 GOOS 和 GOARCH 即可,但當涉及到 CGO 時,問題就變得有點複雜了,因爲你需要指定特定的 GCC。
例如,想在 Ubuntu 上交叉編譯一個帶有 CGO 的動態庫,目標 CPU 架構爲 arm,我們該如何操作呢?
示例代碼
# shared.go
package main
import "C"
//export Sum
func Sum(a, b int) int {
return a + b
}
func main(){}
這個代碼使用到了 CGO,然後暴露一個 Sum
方法,實現兩個整數相加。
編譯 32 位的 arm
因爲通過設置 CGO_ENABLED=1
開啓 CGO 編譯,執行命令如下:
CGO_ENABLED=1 GOOS=linux GOARCH=arm go build -buildmode=c-shared -o share.so
但不幸,命令報錯: gcc: error: unrecognized command line option '-marm'
。
正如一開始我提到,交叉編譯 CGO 需要選擇特定的 arm 交叉編譯工具,而 Ubuntu 上編譯 32 位的 arm 可以使用 gcc-arm-linux-gnueabihf
,安裝命令如下:
sudo apt-get update
sudo apt-get install gcc-arm-linux-gnueabihf
安裝完成後,指定 CC
重新編譯:
CGO_ENABLED=1 GOOS=linux GOARCH=arm CC=arm-linux-gnueabihf-gcc go build -buildmode=c-shared -o share.so
命令成功運行,此時目錄下已經生成了一個叫做 share.so
的文件,通過 file
命令查看其屬性,可以確認確實爲 arm 32
版本。
share.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=7b23579ddcbebdfc8f4b68512859661a45d66996, not stripped
編譯 64 位的 arm
交叉編譯的時候,不僅要針對平臺選擇 GCC,而且還要根據操作系統的位數來選,所以 64 位需要選擇不同的 GCC,這裏推薦 gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu.tar.xz。
安裝命令:
wget https://releases.linaro.org/components/toolchain/binaries/5.3-2016.02/aarch64-linux-gnu/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu.tar.xz
tar xvf gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu.tar.xz -C /usr/lib/
echo 'export PATH="$PATH:/usr/lib/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu/bin"' >> ~/.bashrc
source ~/.bashrc
安裝完成,重新執行編譯命令:
CGO_ENABLED=1 GOOS=linux GOARCH=arm64 CC=aarch64-linux-gnu-gcc-5.3.1 go build -buildmode=c-shared -o share.so
編譯成功,併產生一個 share.so 文件,同樣我們使用 file share.so
查看其元信息爲:
share.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[sha1]=5b0e7ff7c3af178039a7b934df8ca3e7572ab5b5, not stripped
到目前爲止,我們已經成功在 Ubuntu 系統上交叉編譯出了 CGO 程序的 arm 和 arm64 兩個版本。
總結
當 Go 交叉編譯涉及到 CGO 時,只指定 GOOS 和 GOARCH 是不夠的,還需要通過 CC 參數指定相應的 GCC 版本,而 GCC 的選擇又與當前系統以及目標架構有關:
- 交叉編譯目標 CPU 架構(包括 32位 還是 64位)。
- 交叉編譯所在操作系統。
作者:宋佳洋
51Reboot K8S、Golang 課程試聽預約wechat:17812796384