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

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

編譯 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'。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

編譯 64 位的 arm

交叉編譯的時候,不只要針對平臺選擇 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 的選擇又與當前系統以及目標架構有關:

  1. 交叉編譯目標 CPU 架構(包括 32位 仍是 64位)。
  2. 交叉編譯所在操做系統。
相關文章
相關標籤/搜索