0%

ARM、MIPS交叉编译工具试用小记

最近,研究了一下交叉编译技术。主要涉及的语言包括GoC。其中Go的交叉编译相对来说比较容易,C的交叉编译在环境配置上有一些难度和繁琐。在研究过程中,踩了不少坑,特此记录。

Go语言的交叉编译比较容易,基本上就是参数上设置正确就OK了。静态编译的时候,可执行文件相对比较大,这在MIPS设备中,会有些不适合。因为MIPS设备存储容量比较小,内存也比较小,如果静态编译出来的文件过大,可能无法下载到设备中,更有甚者无法加载可执行文件,这种情况基本上就只能靠C语言来进行交叉编译可执行文件了。Go交叉编译的情况,可以参考链接1所示,我觉得写的不错。对于Go支持的操作系统和具体版本,可以参考Github Go wiki。如关于ARM链接2,关于MIPS链接3.

主要来讲C的交叉编译,毕竟坑多,配置繁琐。

我使用过的交叉编译工具或者环境如下:dockcross,Buildroot,crosstool-NG.

dockcross相对来说简单方便,基于docker,能够满足一般需求。可以参考链接4.

我这里出现的情况是,dockcross解决不了我面临的现实问题。静态编译的可执行文件在设备上运行的时候,提示kernel old错误。这里的原因是dockcross-arm docker采用的linux内核版本太高,其实动态编译得到的可执行程序是能在设备上执行成功的。glibc向下兼容,所以执行成功了。这是我后续测试发现的。动态编译文件还小,如果能够跑起来,其实动态编译就好了。因为内核版本高了,那就找个内核版本和设备差不多的。然而,dockcross构建的docker镜像里,没有符合我要求的。

遇到问题,那就解决问题。找到Buildroot,看着口号是让嵌入式linux环境构建更加容易。我下载了最新版,看了一下说明文档,配置起来果然方便。make menuconfig进行配置,然后make就可以了。make menuconfig选择它支持的kernel版本,有个小坑。虽然配置选项可以选择kernel 2.6.x版本,但是在make的时候,下载kernel的时候会出现404错误。buildroot官方的下载地址已经没有2.6.x版本的内核了,最低版本是3.2.101。如果选择了2.6.x版本的kernel,需要让其到cdn.kernel网站上去下载对应文件,主要是参考cdn.kernel网站上,对应kernel文件名,填入URL of custom kernel tarball中。C运行库有uClibcglibcmusl可以选择。glibc编译出来的静态文件相对较大,uClibc编译出来的静态文件相对较小,优先选择uClibcmusl我暂时还没用到,这里不评价。

crosstool-NG本来想用,后来看到Buildroot解决了我的问题,就把它暂时搁置了。看着crosstool-NG配置和Buildroot大同小异,这里占个位置,后续使用到了,再来填坑。

其实,最后我还用到了qemu-mips-static来加载uClibc。因为我遇到一个很老的MIPS系统,内核版本是2.4.x,这在dockcross构建的环境里面没有,Buildroot高版本已经不支持kernel2.4.x了。使用高版本的kernel进行构建交叉编译工具,最后编译出来的可执行程序在设备上跑不起来,问题如下:

line 1: syntax error: unexpected “(”

我琢磨还是内核版本不兼容导致的。最直接的版本就是安装一个内核版本相同的系统,然后进行交叉编译。说干就干。

尝试安装ubuntu6.06.1redhat 9.0这些古老的linux系统结合buildroot-0.9.27来交叉编译,很不幸老旧的linux发行版不支持包更新了,我只能断了这个念头。无意中我在uClibc官网发现可以挂载编译好的基于Buildroot-0.9.27uClibc来进行交叉编译任务。我真是喜出望外,其实是我没仔细看官网,不然前面安装老旧版本的linux工作就可以免了。uClibc官网的下载地址挂了,用这个地址下载吧。以root_fs_mips为例,来进行挂载。主要命令如下:

1
2
3
4
5
bunzip2 root_fs_mips.bz2
mkdir root_fs_mips
sudo su
mount -o loop root_fs_mips.ext2 root_fs_mips
chroot root_fs_mips /bin/bash -

这里有个小坑,因为本机是linux,在挂载root_fs_mips的时候出现如下错误:

chroot: failed to run command '/bin/bash': Exec format error

原因是系统架构不同导致的错误。解决办法就是借助qemu-mips-staticqemu的安装如下

1
apt install qemu-user-static

最后借助qemu_mips_static挂载root_fs_mips的命令如下:

1
2
cp /usr/bin/qemu-mips-static root_fs_mips/usr/bin
chroot root_fs_mips qemu-mips-static /bin/bash

对于老旧版本的MIPS,这样进行交叉编译待执行程序,就可以解决问题了。