Go Wiki:GccgoCrossCompilation
简介
如果您想在标准 Go 编译器 gc 不支持的平台上运行 Go 程序,您可以构建一个 GCC 编译器版本,该版本针对您所需的平台,因为 GCC 支持更多平台。这是可能的,因为有一个名为 gccgo 的 GCC Go 前端。
详细信息
定义
- 构建 这是您构建交叉编译器所在的计算机。
- 主机 构建后将运行交叉编译器的计算机。这通常与构建相同。
- 目标 这是目标系统,您希望交叉编译的程序在该系统上运行。
可以在 维基百科文章 中找到更多定义和复杂的交叉情况。
Go 工具和 gccgo
稍后,您将需要 Go 工具的源代码,因此最好卸载您从包管理器安装的版本,以避免混淆(尽管完全是可选的)。还要构建并安装针对主机的 gccgo(没错,您需要一个不仅针对目标编译的 gcco,还需要一个针对主机的 gcco)。
构建交叉编译器
构建
首先,您必须构建 GCC 的交叉编译版本。这是一个复杂的过程,因为它需要几个阶段的引导,因为 GCC 和 libc 实现之间存在相互依赖关系。Jim Blandy 撰写了一篇非常精细的教程,介绍如何使用 eglic 构建 GCC 交叉工具链(也适用于 glibc),并将其发布在 eglibc 的邮件列表中 补丁交叉构建说明。在构建完整 GCC 的最后阶段,只需使用 –enable-languages=c,c++,go 配置脚本(请参阅 Go 官方文档)。
您可以使用 ewxb_gcc_cross-compiler_builder 脚本作为起点。不要指望该脚本开箱即用,而应将其视为在构建 x 工具链时可能采取的步骤的提示。
如果您足够幸运,并且想要一个不是最新版本的 GCC(您可能希望拥有最新的 Go 功能),则可以使用交叉编译器构建器来简化配置,例如 crosstool-NG,它允许您使用简单的 TUI 菜单配置 GCC。
通过启用 CT_EXPERIMENTAL
和 CT_CC_SUPPORT_GOLANG
,较新版本的 crosstool-NG 可以构建 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
测试
当交叉编译器构建好后,您应该测试一下它是否可用,既可以测试一个简单的 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 程序,以包含运行程序所需的所有内容。通过向 gccgo 添加 -static 开关来执行此操作。如果您不确定生成的 ELF 文件是如何链接的,请使用 readelf -d <elf>
或 objdump -T <elf>
检查它。
构建一个支持交叉 gccgo 的 Go 工具版本
假设
- 假设您已按照 从源代码安装 Go 中的说明进行操作,您应该在 $GOROOT 中签出 Go 源代码版本。
- 已设置环境变量 $GOROOT。
- 环境变量 $GOARCH 和 $GOOS 表示目标架构和操作系统。找出这些内容并在您想要交叉编译时将它们设置为这些值。
构建
您可以使用 go build -compiler gccgo <go-package,files>
指定在使用 go 工具构建时要使用的编译器。但这还不够。如果您已将 $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>
待办事项
导入“C”的 Go 程序似乎无法使用 xgo 运行。目前受 Go 问题 #7398 阻碍
此 Wiki 页面受到 “[golang-nuts] MIPS 交叉编译的简化?”中吸取的教训的启发 @ https://groups.google.com/forum/#!topic/golang-nuts/PgyS2yoO2jM
此内容是 Go Wiki 的一部分。