咱們都知道在不涉及 CGO 的時候,Go 的交叉編譯很是簡單,只須要設置對應的 GOOS 和 GOARCH 便可,但當涉及到 CGO 時,問題就變得有點複雜了,由於你須要指定特定的 GCC。linux
例如,想在 Ubuntu 上交叉編譯一個帶有 CGO 的動態庫,目標 CPU 架構爲 arm,咱們該如何操做呢?bash
示例代碼架構
# shared.go package main import "C" //export Sum func Sum(a, b int) int { return a + b } func main(){}
這個代碼使用到了 CGO,而後暴露一個 Sum 方法,實現兩個整數相加。ide
由於經過設置 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'。ui
正如一開始我提到,交叉編譯 CGO 須要選擇特定的 arm 交叉編譯工具,而 Ubuntu 上編譯 32 位的 arm 可使用 gcc-arm-linux-gnueabihf,安裝命令以下:操作系統
sudo apt-get update sudo apt-get install gcc-arm-linux-gnueabihf
安裝完成後,指定 CC 從新編譯:code
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 版本。component
share.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=7b23579ddcbebdfc8f4b68512859661a45d66996, not stripped
交叉編譯的時候,不只要針對平臺選擇 GCC,並且還要根據操做系統的位數來選,因此 64 位須要選擇不一樣的 GCC,這裏推薦 gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu.tar.xz。ip
安裝命令:
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 的選擇又與當前系統以及目標架構有關: