今天原本准备在QT210开发板上跑个hello world。没想到用arm-none-linux-gnueabi-gcc hello.c编译运行后,出现sh: not found,初看起来应该和动态库有关,于是开始了一段长达8小时的艰辛之旅,期间获益不少,记录如下。
首先,这款开发板预装的是android的环境,安卓环境的libc和gnu的libc有很多不同,编译过程区别也很大,我简单看了android平台下的makefile,一般代码的编译过程:
arm-eabi-4.4.3/bin/arm-eabi-g++ -c -fno-exceptions -Wno-multichar -msoft-float -fpic -ffunction-sections -funwind-tables -fstack-protector -Wa,--noexecstack -Werror=format-security -fno-short-enums -march=armv7-a -mfloat-abi=softfp -mfpu=neon -Wno-psabi -mthumb-interwork -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -DNDEBUG -g -Wstrict-aliasing=2 -finline-functions -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -DNDEBUG -UDEBUG -fvisibility-inlines-hidden -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith -Wsign-promo -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -DNDEBUG -UDEBUG -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -fno-rtti -MD-o hello.o hello.c
链接:
arm-eabi-4.4.3/bin/arm-eabi-g++ -nostdlib -Bdynamic -Wl,-T,build/core/armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -ohello-Lout/target/product/generic/obj/lib -Wl,-rpath-link=out/target/product/generic/obj/lib -Wl,-z,noexecstack -Wl,--fix-cortex-a8 -Wl,--no-undefined hello.o
简单分析一下:在链接时,指定了链接器/system/bin/linker ,还指定链接过程的搜索路径out/target/product/generic/obj/lib,用-Wl,-T排除了默认的链接方法,直接使用build/core/armelf.x 链接脚本,可见android的编译方法和普通的gnu toolchain在链接时有些不同。
如果按以上方法编译helloworld,不免感觉杀鸡用牛刀。于是决定直接舍弃android平台,重启炉灶:
1. 拷贝gnu toolchain的libc.so, ld-linux.so, libdl.so, libpthread.so到开发板/data/mylib目录下,建好符号链接文件。
2. 重新编译hello.c:
arm-none-linux-gnueabi-gcc -Wl,-rpath=/data/mylib -static-libgcc -Wl,-dynamic-linker=/data/mylib/ld-linux.so.3 -o hello hello.c
-Wl,-rpath=/data/mylib 指定运行时搜索动态库的路径;
-Wl,-dynamic-linker=/data/mylib/ld-linux.so.3 指定运行时的链接器。
以上两项可以用readelf -a hello 查看program interpreter,Library rpath:两个字段。
3. 运行OK.
最后出现not found问题的原因总结如下:
1. 找不到动态库,一般是libc库;
2. c库不兼容,android的c库和用gnu toolchain里的c库不相容。
3. 连接器没指定路径。程序在板子上跑需要指定连接器路径。
4. 最后,有些朋友出现not found问题,还可能是eabi的版本不同造成,toolchain的版本和开发板上内核的版本不兼容。