如何在 Ubuntu 上交叉編譯 ARM 架構的 CGO 程序

我們都知道在不涉及 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

發佈了46 篇原創文章 · 獲贊 6 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章