记一次难忘的编译经历

继续之前写UI的故事。

这些天完善了一下之前用qt quick 1.1写的UI,不再满足于乡村英伦风般的动画的我,准备在界面中加入能生成二维码的功能。

然而对于二维码我并没有任何的认识,好在已经有人造完了轮子,三两下我便找到了这个库相应的类的实现。在qt的这个官方文档的指导下,我迅速的就抄出来了一个qml的模块。又三两下调整了一下anchors和大小,心想大功告成。

然后欣喜的在ubuntu里跑了一下,果然一切都像我预想的一样,堪称完美。(顺便自我满足了半个小时)

半个小时之后,逐渐回过味儿的我才想起来这个东西是要运行在那块破开发板上的。于是开始移植。

小手一点build&run,这个时候才被编译器提醒开发板上没有依赖库libqrencode。

这个时候我才想起来需要编译一个适用于开发板的库。(顺便插播,板子的处理器是S3C2440A,armv4t架构)

而之前我也忘了什么时候在stackoverflow上看得什么问题,下了一个arm-linux-gnueabi-gcc;现在就有了两个编译器,一个是从apt下载的arm-linux-gnueabi-gcc,一个是从淘宝卖家那里搞到的arm-linux-gcc(暂且这么叫吧)。

然后就没动脑子的用这个从apt下载家伙编译了ARM能用的zlib、libpng12和libqrencode,个中艰辛在此不表,以后再叙。

再赶紧把qt工程中的pro文件修改一下,在开发板中的配置开发环境的脚本中添加LD_LIBRARY_PATH变量。把编译好的库文件挪到开发板上。

小手再一抖,结果蹦出来了个从来没见过的错误『illegal instruction』。

事实证明我直觉还是有些准,第一时间我就想到了指令集的问题上去(其实是错误都写脸上了)。

于是跑到可执行文件的输出目录,用file命令看看,结果没错啊,是ARM的。

ELF 32-bit LSB  executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, not stripped

然后又readelf -a看看,末尾写的也确实是v4T架构。

Displaying notes found at file offset 0x00000188 with length 0x00000020:
Owner Data size Description
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
OS: Linux, ABI: 2.6.32
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "4T"
Tag_CPU_arch: v4T
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-1
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_enum_size: int

接着就想起来了之前没有把新编译好的库添加进去之前,实际上是没有出过『illegal instruction』的问题的。所以qt creator里选择的淘宝卖家自带的arm-linux-gcc的编译环境没有问题。

而一切问题都是出在在脚本中设置了LD_LIBRARY_PATH变量之后。我试着将export LD_LIBRARY_PATH一行去掉,果然『illegal instruction』的问题消失了,只剩下了找不到库的问题(明摆的嘛)。

明白问题出在库上之后,开始顺藤摸瓜。这三个库的源文件肯定是没有问题的,有问题只能是编译器的问题。于是试着用arm-linux-gnueabi-gcc(apt-get下的那个)编译了一个helloworld,传到开发板上,果然有『illegal instruction』的问题。然而用arm-linux-gcc(淘宝得到)编译,就没有任何问题。用readelf -a发现用arm-linux-gnueabi-gcc编译出来的是v5t架构。

Displaying notes found at file offset 0x00000188 with length 0x00000024:
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Build ID: 2695a06d3c4b95dec91472aefbdebf734fe95bb5
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "5T"
Tag_CPU_arch: v5T
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-1
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_rounding: Needed
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_align_preserved: 8-byte, except leaf SP
Tag_ABI_enum_size: int

然后鬼使神差的用readelf -d看了一下输出的可执行文件用到的动态库。只有一个libc.so.6。

恍然大悟,估计就是这个库有问题!

locate libc.so.6,发现对应着两个编译器,果然有两个libc。

/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/sys-root/lib/libc.so.6
/usr/arm-linux-gnueabi/lib/libc.so.6

再用arm-linux-gnueabi-objdump -f看看这两个libc对应的都是什么架构。

果然/usr/arm-linux-gnueabi/lib/libc.so.6的架构是armv5t。

/usr/arm-linux-gnueabi/lib/libc.so.6: file format elf32-littlearm
architecture: armv5t, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0001840c

而/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/sys-root/lib/libc.so.6的架构是armv4t。

/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/sys-root/lib/libc.so.6: file format elf32-littlearm
architecture: armv4t, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x000151dc

自己还是要提升姿势水平啊!

自己还是要提升姿势水平啊!

一切真相大白,都是libc的锅。应该是需要-rpath指定库的目录。还是乖乖的用回淘宝上给的编译器吧...