我最近买了一个树莓派。我已经配置好了,并在桌面上安装了arm的交叉编译器(amd64)。我编译了一个简单的“hello world”程序,然后使用.登录我的 Pi 后,我运行并得到正常响应:scp ./hello [email protected]:~/hello
ls -l hello
-rwxr-xr-x 1 david david 6774 Nov 16 18:08 hello
但是当我尝试执行它时,我得到以下信息:
david@raspberry-pi:~$ ./hello
-bash: ./hello: No such file or directory
david@raspberry-pi:~$ file hello
hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0x6a926b4968b3e1a2118eeb6e656db3d21c73cf10, not stripped
david@raspberry-pi:~$ ldd hello
not a dynamic executable
答案1
如果ldd
说它不是动态可执行文件,那么它是为错误的目标编译的。
显然你已经交叉编译了它,正如file
所说的是一个 32 位 ARM 可执行文件。但是,“ARM”架构不止一种,因此您的工具链可能配置不正确。
如果您使用的是 crosstool-NG,请查看.config
的值CT_ARCH_ARCH
。对于树莓派,它应该是“armv6j” 1——或者至少,这对我有用。还有其他细节,但我思考这应该足够了。不幸的是,如果错误,您现在必须重建。
IMO 让交叉编译器工具链工作可能是乏味和令人沮丧的,但是,假设主机不是一个重要因素(它不应该是),在这种情况下它是可以完成的。 Crosstool-ng 使用 TLI 配置器,因此如果您最终不得不尝试多个构建,请每次写下您的选择,以便知道哪些有效。
1我相信armv7是一个更常见的架构(很多手机等),所以如果您只是使用您认为是通用ARM交叉编译器的东西,这可能就是问题所在。这些数字令人困惑,例如,圆周率的处理器是ARM11,但是(根据该页),ARM11 系列处理器使用 ARMv6 架构 - 即 ARM11 是 ARMv6 的实现。
答案2
如何识别问题?
file cross_compiled_executable
包含类似以下内容:
interpreter /lib/ld-uClibc.so.0
问题是目标上不存在该文件。
如何解决问题?
使用正确的编译器,可以:
- 创建磁盘映像的人必须为您提供交叉编译器或确切地告诉您如何构建它,例如交叉工具-ng。如何获取 RPI在这里被问到。
- 编译你自己的图像和交叉编译器,例如构建根。这是一个通用的 QEMU 示例。构建根有 RPI 支持。
在目标上使用本机编译器。但通常目标比您的主机慢得多,并且空间有限,因此您可能不想这样做。
您还可以使用 QEMU 等功能模拟器来构建,然后仅在较慢的平台(例如 gem5 或较慢的主板)上运行程序。
仅仅破解interpreter
可能是不够的,特别是/proc
如果您尝试使用-static
(目标内核可能太旧并且不包含所需的接口)。唯一可靠的解决方案是使用正确的工具链。
答案3
首先使用--static
选项编译你的程序,然后测试它。如果它作为静态工作那么在树莓派上
cat "programname" | grep "lib*"
/lib/ld-linux.so.3
libc6.so
然后检查所有库是否存在
我已经这样解决了。我已经/lib/ld-linux-armhf-so.3
但没有在这之间为我/lib/ld-linux.so.3
工作ln -s
答案4
目标系统上的库与编译可执行文件的主机系统上的库不同。
如果您使用 make,则应该在 CFLAGS 和 LDGLAGS 中包含 --static 选项。如果您使用直接 gcc,请使用 --static 选项,这样可执行文件是可移植的。