Go Wiki: Gccgo交叉編譯
引言
如果您想在標準Go編譯器gc不支援的平臺上執行Go程式,您可以構建一個針對您期望的目標平臺的GCC編譯器版本,因為GCC支援的平臺要多得多。這是可能的,因為有一個名為gccgo的GCC的Go前端。
詳細資訊
定義
- 構建 (Build) 這是您正在構建交叉編譯器的計算機。
- 主機 (Host) 構建完成後將執行交叉編譯器的計算機。這通常與構建計算機相同。
- 目標 (Target) 這是目標系統,您希望交叉編譯的程式在該系統上執行。
有關更多定義和複雜交叉編譯情況,請參閱Wikipedia文章。
Go工具和gccgo
稍後您需要Go工具的原始碼,所以最好解除安裝您從包管理器安裝的版本以避免混淆(完全可選)。同時構建並安裝針對主機(host)的gccgo(是的,您需要一個不僅為目標而且也為主機編譯的gccgo)。
構建交叉編譯器
構建
首先,您必須構建您的交叉編譯版本的GCC。這是一個複雜的過程,因為它需要幾個階段的引導(bootstrapping),因為GCC和libc實現之間存在相互依賴關係。Jim Blandy撰寫了一篇非常好的教程,介紹瞭如何使用eglibc(也可與glibc一起使用)構建GCC交叉工具鏈,併發布在eglibc的郵件列表中,標題為patches Cross-building instructions。在構建完整GCC的最後階段,只需使用–enable-languages=c,c++,go配置指令碼(請參閱官方Go文件)。
您可以將ewxb_gcc_cross-compiler_builder指令碼作為起點。不要期望該指令碼能夠立即正常工作,而是將其作為構建x-toolchain可能採取的步驟的提示。
如果您足夠幸運,並且想要一個不是最新的GCC版本(您可能希望擁有最新的Go功能),您可以使用交叉編譯器構建工具來簡化配置,例如crosstool-NG,它允許您透過一個簡單的TUI選單配置GCC。
較新版本的crosstool-NG可以透過啟用CT_EXPERIMENTAL和CT_CC_SUPPORT_GOLANG來構建Go語言。這將自動將go新增到--enable-languages。
符號連結
現在您應該有一個bin目錄,其中包含諸如“<target>-gcc”、“<target>-gnu-gccgo”等檔案。因為go構建工具不允許您指定要使用的編譯器的檔名(僅靜態支援字串‘gc’和‘gccgo’),它會在您的$PATH環境變數中查詢第一個名為‘gccgo’和‘gcc’的檔案。因此,當您想使用交叉編譯器而不是系統上的普通gcc二進位制檔案時,您必須透過將其設定為$PATH中的第一個目錄來新增此目錄作為覆蓋。由於go工具查詢名為gccgo的二進位制檔案,您將必須建立一些符號連結,以便它能找到所需的工具。
$ cd path/to/cross-comp-gcc/bin
$ ln -s <arch>-<os>-gnu-gcc gcc
$ ln -s <arch>-<os>-gnu-gccgo gccgo
$ ln -s <arch>-<os>-gnu-ar ar
$ export PATH="path/to/crosscomp-gcc/bin:$PATH" # Do this whenever you want to use the cross-compilers targeting your target instead of the system default targeting host.
等等。
將$TARGET設定為目標體系結構,$PREFIX設定為構建檔案的目標路徑,您可以使用以下命令建立符號連結:
##!/usr/bin/env bash
cd $PREFIX/bin
for file in $(find . -type f); do
tool_name=$(echo $file | sed -e "s/${TARGET}-\(.*\)$/\1/")
ln -sf "$file" "$tool_name"
done
Test
當交叉編譯器構建完成後,您應該測試它是否正常工作,包括一個簡單的C程式和一個簡單的Go程式。
$ gccgo -Wall -o helloworld helloworld.go
$ file helloworld # verify that the architecture of the binary is the desired target and not a binary that can run on your host machine.
$ <upload-command-to-target> helloworld
$ <ssh/telnet etc. to target and test run>
注意事項
如果您沒有為您目標編譯Go庫(libgo)的共享物件,您可能希望像gc一樣靜態編譯Go程式,以包含執行程式所需的所有內容。透過將-static開關新增到gccgo來完成此操作。如果您不確定生成的ELF檔案是如何連結的,請使用readelf -d <elf>或objdump -T <elf>進行檢查。
構建一個支援交叉gccgo的Go工具版本
假設
- 假設您已按照從原始碼安裝Go上的說明進行操作,您應該在$GOROOT中有一個已簽出的Go原始碼版本。
- 環境變數$GOROOT已設定。
- 環境變數$GOARCH和$GOOS代表**目標**體系結構和作業系統。在想要交叉編譯時,找出它們並將其設定為這些值。
構建
您可以使用go build -compiler gccgo <go-package,files>指定構建時使用的編譯器。但這還不夠。如果您設定的$GOARCH和$GOOS是gc不支援的,但gccgo支援的,那麼您必須構建一個特殊的Go工具版本,該版本能夠理解這些額外的體系結構。如果您使用go工具編譯另一個版本的go工具,並指定使用針對主機的gccgo,則生成的go工具將能夠編譯所有gccgo支援的體系結構的程式。
$ cd ~/tmp
$ hg clone ~/src/go # [0]
$ cd go/src/cmd/go
$ go build -o xgo -compiler gccgo . # [1] [2] [3]
$ cp xgo ~/bin/ # Or any directory that is in your $PATH
[0] 將Go原始碼克隆到$GOROOT目錄之外的目錄。這是必需的,因為我們將要編譯的cmd/go檔案被特殊處理。[1] 這裡必須使用**主機**的gccgo,而不是交叉編譯的gccgo。確保您的$PATH設定正確。[2] 將生成一個名為xgo的二進位制檔案,以區別於現有的go二進位制檔案。將其命名為合適的名稱,例如,如果您的目標是MIPS,則命名為mgo。[3] 編譯步驟(go build)可能會因一些編譯錯誤而失敗,因為gccgo落後於go專案(至少在go mercurial tip 7f2863716967時是這樣)。透過註釋掉錯誤或採取更聰明的辦法來修復這些錯誤,然後重新編譯。
交叉編譯Go程式。
將您的$PATH設定為能夠找到_xgo_和交叉編譯版本的_gccgo,並將$GOARCH設定正確,您現在就可以使用go工具(命名為xgo)進行交叉編譯了。
$ export PATH="path/to/xgo/:path/to/crosscomp-gccgo/:$PATH"
$ export GOARCH="<you-target's-arch>"
$ export GOOS="<you-target's-OS>"
$ xgo build -compiler gccgo <go-package/files>
待辦事項
使用xgo時,匯入“C”的Go程式似乎不起作用。目前受Go issue#7398的限制。
此Wiki頁面受到“[golang-nuts] MIPS交叉編譯的簡化?”@ https://groups.google.com/forum/#!topic/golang-nuts/PgyS2yoO2jM中學到的經驗的啟發。
此內容是 Go Wiki 的一部分。