交叉编译的应用程序不 运行 on Raspberry Pi

Cross-compiled application does not run on Raspberry Pi

我刚刚开始使用 Buildroot 和 Raspberry Pi (运行ning Raspbian)。但不知何故,我似乎在交叉编译方面做错了什么。该应用程序是用 C 编写的最简单的 Hello World 程序。我是这样做的:

  1. 已下载并安装 buildroot
  2. make raspberrypi2_defconfig
  3. make toolchain

然后我编写了微型应用程序和以下 Makefile:

CROSS_BIN := /home/me/raspi/buildroot-2016.05/output/host/usr/bin
SYSROOT := /home/me/raspi/buildroot-2016.05/output/host/usr/arm-buildroot-linux-uclibcgnueabihf/sysroot
PATH := $(CROSS_BIN):$(PATH)

CC := arm-linux-gcc
CFLAGS := --sysroot=$(SYSROOT)

app: app.c
   $(CC) $(CFLAGS) -o $@ $<

编译应用程序并将其复制到 Raspberry。当我尝试 运行 它时,RPI 抱怨它找不到该文件(尽管它确实存在并且可以执行)。二进制类型对我来说似乎没问题,应该适合 CPU:

pi@raspberrypi:~ $ ./app
-bash: ./app: No such file or directory

pi@raspberrypi:~ $ ls -l app
-rwxr-xr-x 1 pi pi 4916 Jul 10 11:07 app

pi@raspberrypi:~ $ file app
app: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, not stripped

pi@raspberrypi:~ $ lscpu
Architecture:          armv7l
Byte Order:            Little Endian
CPU(s):                4
On-line CPU(s) list:   0-3
Thread(s) per core:    1
Core(s) per socket:    4
Socket(s):             1
Model name:            ARMv7 Processor rev 5 (v7l)
CPU max MHz:           900.0000
CPU min MHz:           600.0000

有人可以告诉我我做错了什么吗?如果我本机编译应用程序并 运行 在开发主机上,它 运行 没有问题。

我的钱在 /lib/ld-uClibc.so.0 上,你的 Rasperry pi 不见了。我说得对吗?

好的,这个库就是你的动态加载器,它负责在运行时加载你的动态库。它会将需要的共享库加载到进程地址space,并对内存设置适当的权限(只读、读写和可执行)。

您的交叉编译器需要一个不存在的加载程序,可能是由于 RPi 上安装的映像与交叉编译环境(您的 sysroot)不匹配。

有几种方法可以修复它,让我们从检查一个有效的二进制文件开始,在此处尝试 file /bin/ls 和 post 动态加载程序。

例如:

$ file /bin/ls
/bin/ls: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=5e052e8de057d379ab51d4af510ad9318fe77b46, stripped

When I tried to run it, RPI complains that it can't find the file (though it's there and executable for sure).

shell 抱怨它找不到文件来执行您的程序,而不是它找不到您的文件。
如果已安装,请使用 strace 命令确定找不到哪个文件。
您很可能遇到动态库问题,例如您使用 uClibc 工具链构建,但您的根文件系统具有 glibc。

两种常见的解决方案:

(A) 使用静态链接构建您的程序(这样它就不再依赖于目标系统已安装的库)。

 $(CC) $(CFLAGS) -o -static $@ $< 

(B) 重建 Buildroot 工具链以匹配已安装在 RPi 上的库。即,构建匹配版本号的 glibc 工具链,而不是 uClibc 工具链。