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_EXPERIMENTALCT_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 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

交叉编译 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 的一部分。