我为 Raspberry Pi Zero 交叉编译了程序,但由于某种原因我崩溃了。程序很简单,只是打印字符串到
std::cout
:
#include <iostream>
int main(int argc, char const *argv[])
{
std::cout << "Hello!" << std::endl;
return 0;
}
我使用 Docker 和 CMake 构建程序:
FROM debian:bookworm
ENV GNU_HOST=arm-linux-gnueabihf
ENV C_COMPILER_ARM_LINUX=$GNU_HOST-gcc
ENV CXX_COMPILER_ARM_LINUX=$GNU_HOST-g++
ENV CROSS_INSTALL_PREFIX=/usr/$GNU_HOST
ENV CROSS_TOOLCHAIN=/arm.toolchain.cmake
RUN echo "set(CMAKE_SYSTEM_NAME Linux)" >> $CROSS_TOOLCHAIN && \
echo "set(CMAKE_SYSTEM_PROCESSOR arm)" >> $CROSS_TOOLCHAIN && \
echo "set(CMAKE_C_COMPILER /usr/bin/$C_COMPILER_ARM_LINUX)" >> $CROSS_TOOLCHAIN && \
echo "set(CMAKE_CXX_COMPILER /usr/bin/$CXX_COMPILER_ARM_LINUX)" >> $CROSS_TOOLCHAIN && \
echo "set(CMAKE_PREFIX_PATH $CROSS_INSTALL_PREFIX)" >> $CROSS_TOOLCHAIN
RUN apt-get update && \
apt-get --no-install-recommends install -y autoconf \
automake \
build-essential \
ca-certificates \
curl \
# C/C++ cross compilers
gcc-$GNU_HOST \
g++-$GNU_HOST \
git \
gnupg \
libssl-dev \
openssh-client \
pkg-config \
software-properties-common \
wget \
cmake && \
rm -rf /var/lib/apt/lists/*
这是 C++ 编译器版本:
/usr/bin/arm-linux-gnueabihf-g++ --version
arm-linux-gnueabihf-g++ (Debian 12.2.0-14) 12.2.0
这里是有关二进制文件的信息。
pi@raspberrypi:~$ file camera-bot
camera-bot: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=f45663f061217dc844ca45f314e2af084df83869, for GNU/Linux 3.2.0, with debug_info, not stripped
pi@raspberrypi:~$ objdump -j .interp -s ./camera-bot
./camera-bot: file format elf32-littlearm
Contents of section .interp:
0154 2f6c6962 2f6c642d 6c696e75 782d6172 /lib/ld-linux-ar
0164 6d68662e 736f2e33 00 mhf.so.3.
pi@raspberrypi:~$
pi@raspberrypi:~$ ldd camera-bot
/usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so => /usr/lib/arm-linux-gnueabihf/libarmmem-v6l.so (0xb6ee0000)
libstdc++.so.6 => /lib/arm-linux-gnueabihf/libstdc++.so.6 (0xb6d00000)
libgcc_s.so.1 => /lib/arm-linux-gnueabihf/libgcc_s.so.1 (0xb6cc0000)
libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6b47000)
libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0xb6b00000)
/lib/ld-linux-armhf.so.3 (0xb6f23000)
pi@raspberrypi:~$ g++ --version
g++ (Raspbian 12.2.0-14+rpi1) 12.2.0
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
pi@raspberrypi:~$ gdb camera-bot
GNU gdb (Raspbian 13.1-3) 13.1
Reading symbols from camera-bot...
(gdb) b main
Breakpoint 1 at 0x892: file /workspaces/RaspberryCamera/src/main.cpp, line 19.
(gdb) run
Starting program: /home/pi/camera-bot
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x0044f952 in ?? ()
(gdb) bt
#0 0x0044f952 in ?? ()
#1 0x0040079e in _start ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
更新#1
即使我对 C++ 标准库进行静态链接,也会崩溃:
Reading symbols from camera-bot...
(gdb) b main
Breakpoint 1 at 0x889a: file /workspaces/RaspberryCamera/src/main.cpp, line 19.
(gdb) run
Starting program: /home/pi/camera-bot
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x0045795c in bool std::has_facet<std::collate<wchar_t> >(std::locale const&) ()
(gdb) bt
#0 0x0045795c in bool std::has_facet<std::collate<wchar_t> >(std::locale const&) ()
#1 0xbefff6e2 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
我发现用于交叉编译的 Docker 镜像
debian:bookworm
具有专为 ARMv8 构建的 /usr/bin/arm-linux-gnueabihf
编译器,但 Raspberry Pi Zero 需要 ARMv6。还有一些其他 ARM 相关选项,对于设备编译器和 Docker 映像编译器来说是不同的。我猜这就是崩溃的原因。
因此,我将 Docker 映像更改为由
tttapa创建的
ghcr.io/tttapa/docker-arm-cross-toolchain:armv6-rpi-linux-gnueabihf
,并在我的 CMakeLists.txt 中启用了 C++ 标准库的静态链接。
# Dockerfile.dev
FROM ghcr.io/tttapa/docker-arm-cross-toolchain:armv6-rpi-linux-gnueabihf
USER root
RUN apt-get update && \
apt-get --no-install-recommends install -y autoconf \
automake \
build-essential \
ca-certificates \
curl \
gnupg \
libssl-dev \
openssh-client \
pkg-config \
software-properties-common \
wget \
cmake && \
rm -rf /var/lib/apt/lists/*
完成此步骤后,我可以在 Raspberry Pi Zero 上运行交叉编译的二进制文件,而不会发生任何崩溃。
附注我不知道这是否应该被接受,因为我没有在我的问题中提供来自 Docker 映像和设备的 GCC 的完整版本信息(包括构建选项)。也许这个答案将为面临同样崩溃的人节省一些时间。