交叉编译Go程序

栏目: Go · 发布时间: 5年前

内容简介:有几个Go的程序需要放在树莓派上跑,由于树莓派的性能是在太差、编译工具版本又低,想想还是在其他设备上编译好可执行文件直接拿来用方便,毕竟无需依赖的静态编译是Go的亮点嘛。Go对交叉编译的支持是极好的:对于没有使用CGO的程序,只需要通过设置$CGO_ENABLED、$GOOS、$GOARCH参数即可轻松地实现跨平台编译;对于使用CGO的程序,大部分情况可以通过配置$CC参数使用自行准备的交叉编译工具进行编译。

有几个 Go 的程序需要放在树莓派上跑,由于树莓派的性能是在太差、编译 工具 版本又低,想想还是在其他设备上编译好可执行文件直接拿来用方便,毕竟无需依赖的静态编译是Go的亮点嘛。

Go对交叉编译的支持是极好的:对于没有使用CGO的程序,只需要通过设置$CGO_ENABLED、$GOOS、$GOARCH参数即可轻松地实现跨平台编译;对于使用CGO的程序,大部分情况可以通过配置$CC参数使用自行准备的交叉编译工具进行编译。

交叉编译Go程序

下面以macOS为例,简单记录一下过程中踩的坑吧

不使用CGO的交叉编译

I. 一般做法

在macOS编译 Linux 和Windows的arm可执行程序:

CGO_ENABLED=0 GOOS=linux GOARCH=arm go build main.go
    CGO_ENABLED=0 GOOS=windows GOARCH=arm go build main.go

其中:

  • $CGO_ENABLED:0表示关闭CGO
  • $GOOS:目标平台(编译后要运行的目标平台)的操作系统(darwin、freebsd、linux、windows)
  • $GOARCH:目标平台(编译后要运行的目标平台)的体系架构(386、amd64、arm)分别对应(32位、64位、ARM平台)的架构

树莓派属于ARM平台,对于编译给ARM使用的Go程序,需要根据实际情况配置$GOARM,这是用来控制CPU的浮点协处理器的参数。$GOARM默认是6,对于不支持VFP使用软件运算的老版本ARM平台要设置成5,支持VFPv1的设置成6,支持VFPv3的设置成7,详细说明如下:

GOARM=5: use software floating point; when CPU doesn't have VFP co-processor
GOARM=6: use VFPv1 only; default if cross compiling; usually ARM11 or better cores (VFPv2 or better is also supported)
GOARM=7: use VFPv3; usually Cortex-A cores

综上,给跑着linux的老版本树莓派编译Go程序的命令为:

CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=5 go build main.go

II. 关于协处理器

协处理器是协助CPU完成其无法执行或执行效率、效果低下的处理工作而开发和应用的处理器。

这种CPU无法执行的专项工作有很多,比如设备间的信号传输、接入设备的管理等;执行效率、效果低下的有图形处理、声频处理等。为了进行这些专项处理,各种辅助处理器就诞生了。现在的计算机构架(x86、amd64)中,整数运算器与浮点运算器已经集成在一起,一般来讲因此浮点处理器内建于CPU中的协处理器,不算是辅助处理器,不过ARM架构因为低功耗的原因是个例外。

ARM架构中的VFP coprocessor是典型的协处理器,它提供浮点数基本运算(加、减、乘、除、开方、比较、取反)以及向量(vectors)功能,一般来讲,VFP可以同时支持最多8组单精度4组双精度浮点数的运算。

简单地说,使用协处理器可以能好地协助CPU发挥出性能,可以粗暴地认为是一种硬件加速。

使用CGO的交叉编译

III. 什么是CGO

C语言经过数十年发展,各个方面的开源代码、闭源库已经非常丰富。这对于一门现代编程语言而言,如何用好现成的C代码就显得极为重要,CGO就是一个令人惊异的技术,它允许Go与C的类库交互操作,让Go能够使用 C语言 积累的各种资源。

CGO作为Go中使用C语言代码的一种方式,在获得好处的同时就必定得有付出,这是亘古不变之理:由于CGO相当于使用了C语言,所以编译使用CGO部分的代码就必须按C语言路子来,而C语言原生的跨平台支持相对Go来说可是差远了,使得使用CGO后要编译跨平台的可执行文件就麻烦多了。

目前解决CGO跨平台编译问题的思路有:

IV. 用目标平台的工具链进行交叉编译

以树莓派的ARM平台为例,用ARM GNU Linux工具链,编译使用了CGO的Go项目。

macOS的文件系统默认是大小写不敏感的,而交叉编译工具链是基于大小写敏感的文件系统的,所以应当新建一个大小写敏感的磁盘镜像用于安放ARM GNU Linux工具链。打开Disk Utility,然后 File>New Image>Blank Image,然后在弹出窗口中设置名称为armx(名称自定),大小大于512MB,格式为Mac OS Extended的映像。

交叉编译Go程序

下载 或者 按说明 自行编译ARM GNU Linux工具链。

假设工具链包已经在~/Download目录中,解压缩工具链到到新建的磁盘镜像中:

tar -zxv -C /Volumes/armx/ --strip-components 1 -f ~/Download/ARMx-2009q3-67.tar.bz2

交叉编译Go程序

现在,你就已经能够直接使用ARM工具链了,比如要编译main.c程序,可以在终端执行:

/Volumes/Armx/bin/arm-none-linux-gnueabi-gcc main.c -o main

就可以获得一个名为main的可执行程序,这个程序在macOS是不能运行的,只能在ARM平台设备上的Linux系统中才能执行。

好了,现在开始编译用了CGO的Go程序给树莓派用吧:

CGO_ENABLED=1 GOOS=linux GOARCH=arm CC=/Volumes/Armx/bin/arm-none-linux-gnueabi-gcc GOARM=5 go build -x main.go

其中$CC参数指定的是ARM工具链位置,如果不出意外的话,编译完成后就可以得到可以在树莓派上运行的Go程序了。

交叉编译Go程序

如果使用Beego提供的bee工具进行编译和打包,效果也是一样的的。

CGO_ENABLED=1 GOOS=linux GOARCH=arm CC=/Volumes/Armx/bin/arm-none-linux-gnueabi-gcc GOARM=5 ~/go/bin/bee pack main.go

交叉编译Go程序

交叉编译过程中如果出现错误,多半是因为使用CGO部分的代码,在不同的平台存在不兼容的问题,需要根据错误提示逐项解决。

V. 用原生代码重写CGO实现的功能

这一小节是废话,用原生Go代码重写之后问题划归成了第一类,也就不存在CGO的问题了。


以上所述就是小编给大家介绍的《交叉编译Go程序》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

重新理解创业

重新理解创业

周航 / 中信出版集团 / 2018-10-20 / 58.00

易到用车创始人/顺为资本投资合伙人周航,首度复盘20年创业经历,全方位坦陈创业得与失。这不是一本创业成功手册,却是思想的一次出走。 20年创业经历的咀嚼与反思,从战略、品牌、竞争,到流量、领导力、团队管理等,多角度多维度的重新认知,如李开复所言,“都是真刀真枪打出来的经验,值得每一位创业者多读几遍,吸收内化”。 雷军、李开复、徐小平作序,梁建章、张志东、曾鸣推荐。一起来看看 《重新理解创业》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具