交叉编译准备
背景
在嵌入式 Linux 开发中,往往会出现两个名词,宿主机以及目标机;而实际上我们程序运行的地方是目标机,但是编译出程序的地方却不是目标机而是宿主机,这里有很多中原因了;大致上分为三种:第一种是目标机高度裁剪,连 gcc 都没有,也就没有能力编译;第二种而是目标机性能比较低,编译所耗费的时间比较多;第三种则是目标机虽然能力很强,比如服务器。但是耐不住没有图形化,所以还是交叉编译。
总而言之,就是不方便,所以才有宿主机帮忙编译;所以反过来说宿主机一定是好用的,也就是为什么宿主机铺天盖地就是一堆 debian 或者 ubuntu,反正程序不在这里跑,图形化是很大的优势,图形化所带来的开销又可以不用考虑。
前提
在你的宿主机上已经有交叉编译工具链,而且起码你也得有一个目标机,可能也就是一块板子。
依赖安装
这里默认你的交叉编译工具链是 32 位的,而我们的虚拟机一般都是 64 位的,所以得安装一些库,毕竟 ubuntu 本身是没有帮助我们安装 32 位的库的。
sudo apt install lib32z1-dev
sudo apt install lib32z1 lib32ncurses5
sudo apt install lib32stdc++6
sudo apt install gcc-multilib
共享文件夹
不知道你知不知道 window 下的共享文件夹,或者 NAS ,这里就是要实现类似的功能,也就是在目标机以及宿主机上共享一个文件夹,通过网络的方式实现,当然目标机和宿主机得在同一个局域网内,不然是做不了;这里使用的方案是 NFS(network file system)。
当然共享文件夹虽说是贡献,但是肯定有一个真实的物理存储,也就是虽然目标机和宿主机在行为上像是在操作同一个文件夹,但是实际上来说肯定是有有一方在物理上存储了这些文件,这一方通常是宿主机,也不绝对,比如服务器,可能就是目标机来提供物理存储了。
建议创建一个工具目录,作为以后挂载的目录,也就是你想共享的文件夹。
sudo apt install nfs-kernel-server
sudo bash -c 'echo "/home/haorui/haorui *(rw,sync,no_subtree_check,no_root_squash)" >> /etc/exports'
service nfs-kernel-server restart
showmount -e
然后你需要确保宿主机以及目标机的网络是互通的,也就是 ping 双方的 IP 地址都是通过的,使用 ifconfig 查询自己的 IP 地址。
基本上对于局域网内的宿主机以及目标机并且宿主机是虚拟机,如果要达到上面的效果,只能选择插网线并且使用桥接模式。
然后登录目标机:
cd /var
mkdir share
mount -t nfs -o nolock 172.20.92.71:/home/haorui/haorui /var/share/
左边上下的两个终端分别打印了宿主机的 IP 以及共享目录,而右边的目录则是目标机挂载宿主机的共享目录;也就是说这三个终端运行在不同的地方,左边两个运行在宿主机上,右边一个运行在录播机上。
远程调试
在本地写程序的时候,我们可以很方便的使用 gdb 进行断点调试;在交叉编译的时候,其实我们也可以这么做,这就是远程调试,不过它不仅仅需要 gdb ,还需要一个 gdb server。
写在最前面这是需要注意的, 为了实现远程调试, 我们需要 gdb 以及 gdb server,其中 gdb 是运行在宿主机的, gdb server 是运行在目标机上的,你可以简单地把它们理解为成一种C/S模式,即 gdb 作为客户端, gdb server 作为服务器。
gdb 相关
由于后期要开启 pretty printer 功能,也就是为了看到 STL 容器的内容,甚至是 Boost 容器的内容,我们需要 gdb 有 py 的功能,你可以简单把 pretty printer 和 gdb 的关系看成 VScode 里的插件与 VScode 的关系;这种功能在 gdb 7 之后才有,我们推荐的 gdb 版本大致上是 7.4 或者 9.2 。
gdb 这种东西挺奇怪的,其实我编译过很多个版本,7,8,9,10,11我都编译过,7和8的编译方式是一致的,9突然改变了,10和11也是一致的,但也和9不同的,所以你选择其他的版本的话,你就自己去编吧,看我的没用。
下载 gdb
cd ~/package/compress/
wget https://ftp.gnu.org/gnu/gdb/gdb-9.2.tar.gz
tar zxvf gdb-9.2.tar.gz -C ../
安装 gdb
sudo apt-get install texinfo
sudo apt install libexpat1-dev
mkdir build
cd build/
/home/haorui/package/gdb-9.2/configure --target=arm-linux --program-prefix=arm-hisiv600-linux- --prefix=/home/haorui/tools/arm-hisiv600-linux-gdb -with-python=/usr/bin/python3.8
make -j8
make install
make clean
cd ..
rm -rf build
安装 gdb server
./configure --host=arm-hisiv600-linux --program-prefix=arm-hisiv600-linux- --prefix=/home/haorui/tools/arm-hisiv600-linux-gdbserver
make
make install
make clean
测试 gdb
如下测试一下即可:
需要看看 gdb 的 pretty-printer 的功能是否具备,当然你看到 1 of 1 printers enabled ,其实跟没有开启一样,当然这就是之后要去解决的问题;但是这项功能有没有又是另一回事。
如图这是当初编译的 gdb , 7.11.1 版本,使用 python 2.x 编译,压根就没有 pretty-printer 功能。
重要已知问题
在 ubunut 18.04 下,使用 gdb 进行远程调试会出现以下错误,
Reading /lib/ld-linux.so.3 from remote target...
Reading symbols from target:/lib/ld-linux.so.3...
Remote 'g' packet reply is too long (expected 168 bytes, got 328 bytes): 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0fdffbe00000000c0fafcb6100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
网上对这个问题的修复大致上是这样的,这里这里把网友的解决方案贴出来,以此为戒:
将:
if (buf_len > 2 * rsa->sizeof_g_packet)
error (_("Remote 'g' packet reply is too long: %s"), rs->buf);
修改为:
if (buf_len > 2 * rsa->sizeof_g_packet) {
rsa->sizeof_g_packet = buf_len ;
for (i = 0; i < gdbarch_num_regs (gdbarch); i++) {
if (rsa->regs->pnum == -1)
continue;
if (rsa->regs->offset >= rsa->sizeof_g_packet)
rsa->regs->in_g_packet = 0;
else
rsa->regs->in_g_packet = 1;
}
}
这个修改方案你说行不通也不是,但凡是修改源码都是最后面的事情了,这一上来就打个抗生素不太好,建议还是跟踪一下错误;首先这个问题不是必现,也就是有人的机器上会出现,有人不会,那么说明程序本身应该是没有太大的问题的,可能是依赖。
我去找了一下,发现是 gdb 编译的时候缺少一个可选的依赖库,expat(一个XML的解析器),所以就安装一下咯,在 ubunutu 下sudo apt install libexpat1-dev 这样就可以了。
总而言之,不要随意修改源代码,尤其在你不知道修改的是什么的情况下;这一个问题来来回回几十个回复都是像上面这样修改,其实并不太好;我相信第一个修复者是有认真分析的,但是后来的人可能都只是照搬而已。
已知问题汇总
- 使用 python 3.9 安装 gdb 会失败,原因是接口发生更替,编译得过去,但是会出现段错误
- 使用 python 2.x 安装 gdb ,可能导致 gdb 部分功能不完全开启
- gdb 和 gdbserver 是成对使用的,不会混合使用, gdb 和 gdbserver 是 C/S 模式,通信的信令在不同的版本间可能有所不同;当然也不是不能混用,毕竟只是有可能不同
|