拓冰建站拓冰建站
首页 / 资讯中心 / 正文

香橙派RK3588交叉编译hello实战:验证aarch64工具链完整可用

1. 为什么一个hello程序值得单独写一篇交叉编译教程很多人看到交叉编译hello这个标题第一反应是不就是编译个hello world吗有什么好讲的。但如果你真的在香橙派RK3588这类ARM开发板上从零走过一遍完整流程就会明白——hello world从来不是目的它是验证整条工具链是否打通的探针。就像电工在检修复杂线路之前会先拿测电笔点一下确认有电没电。hello程序就是那支测电笔。我在折腾香橙派5RK3588跑yolov5s这条路上交叉编译环境搭建是最容易卡住新手的环节。原因很简单网上大部分教程要么默认你已经有完整的交叉编译工具链要么直接跳到编译内核、编译Qt这种大工程中间怎么确认工具链真的能用这一步被跳过了。结果就是后面编译大项目报了一堆莫名其妙的错误你根本不知道是工具链本身有问题还是项目配置有问题。这篇内容要解决的核心问题就一个在x86_64的Ubuntu主机上用交叉编译工具链生成一个能在香橙派RK3588aarch64架构上运行的hello可执行文件并通过实际运行验证工具链完整可用。适合谁看适合刚拿到香橙派5、准备跑yolov5s或者部署其他AI应用但对交叉编译只有模糊概念的朋友。也适合之前编译过但总是报错、想搞清楚每一步到底在干什么的人。整个流程涉及几个关键角色宿主机你的x86电脑跑Ubuntu、目标机香橙派RK3588跑Ubuntu 20.04或22.04、交叉编译工具链运行在x86上但生成aarch64代码的编译器套件。三者关系搞清楚了后面编译什么项目都是同一套逻辑。2. 交叉编译到底在干什么为什么不能直接在板子上编译2.1 从在哪儿编译和在哪儿运行说起交叉编译这个概念用一句话解释就是在A平台上编译出能在B平台上运行的程序。这里的A叫宿主机hostB叫目标机target。你平时在电脑上写C代码gcc一敲生成的可执行文件直接在本机跑这叫本地编译native compilation。交叉编译则是gcc换成了aarch64-linux-gnu-gcc生成的程序在x86上跑不了但拷到ARM板子上就能跑。为什么非要这么折腾直接在香橙派上编译不行吗行但体验很差。香橙派RK3588虽然性能在ARM开发板里算强的8核4个A76大核4个A55小核但跟你的x86台式机或笔记本比起来编译大型项目时差距还是明显的。举个实际例子编译一个中等规模的C项目x86上可能2分钟搞定RK3588上可能要15到20分钟。如果是编译内核或者OpenCV这种差距会拉大到几个小时。而且开发板上存储空间有限编译过程产生的中间文件很容易把eMMC或SD卡塞满——热词里就有人提到rk3588刚烧写的ubuntu20.04磁盘就没空间了这往往就是直接在板子上编译导致的。交叉编译的另一个好处是工具链统一。团队协作时大家用同一套交叉编译工具链生成的二进制行为一致不会出现你编译的能跑我编译的跑不了这种问题。2.2 工具链里到底装了些什么一套完整的交叉编译工具链核心组件包括binutils包含链接器ld、汇编器as、目标文件工具objcopy/objdump等。链接器负责把多个.o文件拼成最终可执行文件这是交叉编译里最容易出问题的环节。gcc/g编译器本体负责把C/C源码翻译成目标架构的汇编再汇编成机器码。glibc或musl目标平台的C标准库。你的hello程序调用的printf最终实现在这里。交叉编译时链接的是目标平台的libc不是宿主机的。gdb可选交叉调试器可以在宿主机上调试目标机运行的程序。sysroot目标平台的根文件系统镜像包含头文件和库文件。编译器通过--sysroot参数找到目标平台的头文件和库。香橙派官方和Rockchip SDK通常会提供预编译好的工具链命名类似gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu或者aarch64-linux-gnu-gcc。前者是ARM官方发布的GNU工具链后者是Ubuntu apt源里可以直接装的。两者都能用区别在于版本和默认配置。2.3 为什么hello是验证工具链的最佳选择hello程序足够简单不依赖任何第三方库只用到libc的printf和exit。如果hello能编译、能运行说明工具链的编译器、链接器、libc都是匹配的。如果hello都跑不起来那问题一定出在工具链本身或者环境配置上跟你的项目代码无关。这就是最小可验证单元的思路——先用最简单的东西排除变量再逐步增加复杂度。我个人的习惯是拿到一块新板子或者一套新工具链第一件事永远是编译hello并跑通。这一步过了后面编译yolov5s的推理程序、OpenCV、FFmpeg才有意义。否则就是在流沙上盖楼。3. 环境准备宿主机、目标机与工具链的选型3.1 宿主机环境的选择与确认宿主机推荐Ubuntu 20.04或22.0464位x86。这两个版本是Rockchip SDK和大多数教程的默认环境兼容性最好。如果你用的是Windows建议装WSL2或者直接装双系统不要用Cygwin或MinGW去折腾交叉编译坑太多。确认宿主机架构uname -m输出应该是x86_64。如果是aarch64说明你已经在ARM机器上了那就不需要交叉编译直接本地编译即可。确认宿主机能正常联网因为要下载工具链。检查磁盘空间工具链解压后通常占1到3GB留出至少10GB余量比较稳妥。3.2 目标机香橙派RK3588的系统确认香橙派5或5 Pro出厂通常预装Ubuntu 20.04或22.04。上电后通过串口或SSH登录确认系统信息uname -m cat /etc/os-releaseuname -m应该输出aarch64这确认了目标架构。/etc/os-release能看到具体的Ubuntu版本。这一步很关键因为交叉编译工具链的glibc版本必须与目标机兼容。如果目标机是Ubuntu 20.04glibc 2.31而你用的工具链是基于glibc 2.35的编译出来的程序在板子上可能报GLIBC_2.35 not found。提示工具链的glibc版本应该小于等于目标机的glibc版本。版本关系是向下兼容——高版本glibc编译的程序不能在低版本glibc的系统上运行反过来则可以。查看目标机glibc版本ldd --version3.3 交叉编译工具链的获取与选型对比获取工具链有三条路各有优劣来源优点缺点适用场景Ubuntu apt源gcc-aarch64-linux-gnu安装简单一条命令搞定版本较旧可能缺一些库快速验证简单项目ARM官方GNU工具链版本新组件全文档好需要手动下载解压配置正式项目开发Rockchip SDK自带工具链与RK3588最匹配需要下载完整SDK体积大编译内核、驱动对于hello验证这个阶段我建议先用apt源的工具链快速跑通确认流程没问题后再换成ARM官方工具链做正式开发。这样能最快建立信心也不容易一上来就被复杂的环境配置劝退。apt方式安装sudo apt update sudo apt install gcc-aarch64-linux-gnu g-aarch64-linux-gnu安装完成后验证aarch64-linux-gnu-gcc --version如果能看到版本信息说明安装成功。这个工具链的默认sysroot在/usr/aarch64-linux-gnu头文件和库都在那里。ARM官方工具链的下载地址在ARM开发者网站选择aarch64-none-linux-gnu版本。下载后解压到/opt目录sudo tar -xjf gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.bz2 -C /opt然后把bin目录加入PATHexport PATH/opt/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin:$PATH注意这个export只对当前终端有效。要永久生效需要写进~/.bashrc或~/.profile。我建议写进~/.bashrc然后source ~/.bashrc。4. 手把手实操从写代码到板子上跑起来4.1 编写hello.c与Makefile先建一个工作目录mkdir -p ~/rk3588_cross/hello cd ~/rk3588_cross/hello写一个最基础的hello.c#include stdio.h int main(void) { printf(Hello from RK3588 cross compile!\n); printf(Compiled on x86_64, running on aarch64.\n); return 0; }这个程序故意加了两行输出第二行用来确认它确实是在ARM板子上跑的而不是在宿主机上误跑了。接下来写Makefile。虽然直接敲命令也能编译但用Makefile更规范后面扩展也方便CROSS_COMPILE ? aarch64-linux-gnu- CC : $(CROSS_COMPILE)gcc CFLAGS : -Wall -O2 TARGET : hello SRCS : hello.c all: $(TARGET) $(TARGET): $(SRCS) $(CC) $(CFLAGS) -o $ $^ clean: rm -f $(TARGET) .PHONY: all clean这里CROSS_COMPILE用了?意思是如果环境变量里已经定义了就用环境变量否则用默认值。这样后面换工具链只需要改一个变量不用动Makefile。4.2 编译与文件类型验证执行编译make如果一切正常目录下会出现一个名为hello的可执行文件。这时候最关键的一步来了——验证它到底是什么架构。很多人编译完直接拷到板子上跑不起来才发现编译错了白白浪费时间。用file命令查看file hello正确输出应该是hello: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, ...关键信息是ARM aarch64。如果显示的是x86-64说明你用的还是宿主机的gcc交叉编译没生效。这时候检查Makefile里的CROSS_COMPILE变量或者直接which aarch64-linux-gnu-gcc确认工具链在PATH里。再用readelf确认一下aarch64-linux-gnu-readelf -h hello | grep Machine输出应该是Machine: AArch64。4.3 传输到香橙派并运行传输方式有几种选最顺手的scp方式推荐简单直接scp hello orangepi192.168.1.100:/home/orangepi/把IP换成你香橙派的实际地址。orangepi是默认用户名密码通常也是orangepi或者你设置的那个。U盘方式如果网络不通用U盘拷过去也行。注意U盘格式FAT32对可执行文件权限支持不好建议用ext4或者直接tar打包。NFS挂载开发阶段最方便宿主机开NFS服务板子上mount过来改完代码直接编译直接跑不用来回拷。但配置稍麻烦新手可以先跳过。传到板子上后先加执行权限chmod x hello然后运行./hello如果看到Hello from RK3588 cross compile! Compiled on x86_64, running on aarch64.恭喜交叉编译工具链完全打通了。4.4 静态编译与动态编译的取舍上面的例子是动态链接的依赖目标机的ld-linux-aarch64.so.1和libc。如果目标机系统精简过或者glibc版本不匹配可能会报错。这时候可以试试静态编译aarch64-linux-gnu-gcc -static -o hello_static hello.c静态编译把libc也打包进可执行文件体积会大很多hello从十几KB变成几百KB甚至上MB但好处是不依赖目标机的库拷过去就能跑。缺点是如果程序里用了dlopen或者NSS比如getaddrinfo静态编译可能有问题。我的建议是验证阶段用动态编译确认工具链和系统库匹配如果目标机环境不确定或者要分发给别人用考虑静态编译。对于yolov5s这种依赖OpenCV、FFmpeg的项目基本只能动态编译因为静态链接这些库太复杂了。5. 常见报错与排查思路5.1 编译阶段常见问题问题一aarch64-linux-gnu-gcc: command not found工具链没装或者不在PATH里。先which aarch64-linux-gnu-gcc确认如果没有重新apt安装或者检查PATH配置。如果是ARM官方工具链确认解压路径和PATH里的路径一致。问题二fatal error: stdio.h: No such file or directory这是sysroot配置问题。apt安装的工具链通常自动配置好了sysroot如果报这个错可能是工具链安装不完整。试试sudo apt install libc6-dev-arm64-cross。如果是手动下载的工具链检查--sysroot参数是否指向了正确的目录。问题三链接时报cannot find -lc找不到目标平台的libc。同样是sysroot问题。确认工具链目录下有aarch64-linux-gnu/libc目录里面应该有libc.so和libc.a。5.2 运行阶段常见问题问题一No such file or directory但文件明明存在这是最经典的坑。在板子上运行./hello报这个错但ls -l hello能看到文件。原因通常是动态链接器路径不对。用readelf -l hello | grep interpreter看看指定的解释器路径然后在板子上确认这个路径下的文件是否存在。如果工具链指定的解释器是/lib/ld-linux-aarch64.so.1但板子上实际在/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1就会报这个错。解决办法是编译时指定正确的动态链接器或者做个软链接。问题二GLIBC_2.xx not found工具链的glibc版本高于目标机。解决办法是换用与目标机glibc版本匹配的工具链或者升级目标机的系统。查看目标机支持的glibc版本strings /lib/aarch64-linux-gnu/libc.so.6 | grep GLIBC_。问题三Permission denied忘了chmod x。这个最简单但也最容易忘。5.3 排查速查表现象可能原因排查命令解决方向编译报找不到头文件sysroot配置错误aarch64-linux-gnu-gcc -print-sysroot检查工具链安装补装libc6-dev-arm64-crossfile显示x86-64用了宿主机gccwhich aarch64-linux-gnu-gcc检查PATH和Makefile的CROSS_COMPILE运行报No such file动态链接器路径不对readelf -l hello | grep interpreter软链接或指定正确解释器运行报GLIBC版本工具链glibc过高ldd --version板子上换工具链或升级系统链接报cannot find -lxxx缺少目标平台库find / -name libxxx*安装对应的arm64库或指定-L路径实操心得遇到报错先别急着搜先用file、readelf、ldd这三个命令把可执行文件解剖一遍。大部分交叉编译问题都能从这三个命令的输出里找到线索。我踩过的坑里至少一半是因为没做文件类型验证就直接拷到板子上跑。6. 从hello延伸到yolov5s部署的工具链准备hello跑通之后这套工具链就可以用来编译更复杂的项目了。但yolov5s部署涉及的东西比hello多得多这里提前说一下需要额外准备什么。首先是OpenCV的交叉编译。yolov5s的推理结果需要画框、写文字这些都依赖OpenCV。交叉编译OpenCV是个大工程需要先交叉编译它的依赖比如libjpeg、libpng、zlib然后配置CMake的toolchain file。这个过程比hello复杂几个数量级但底层逻辑是一样的——都是指定交叉编译器、sysroot、目标架构。其次是RKNN SDK。RK3588的NPU推理要用Rockchip的RKNN Runtime。官方SDK里通常包含预编译好的aarch64库直接链接即可不需要自己交叉编译。但要注意SDK的版本和板子上NPU驱动的版本匹配。最后是CMake的交叉编译配置。大型项目基本都用CMake需要写一个toolchain fileset(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g) set(CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)这个文件保存为aarch64-toolchain.cmake配置时用cmake -DCMAKE_TOOLCHAIN_FILEaarch64-toolchain.cmake ..。hello阶段手动敲gcc命令没问题但到了OpenCV和yolov5s这个级别CMake几乎是必须的。我个人在实际操作中的体会是交叉编译最难的不是命令本身而是版本匹配。工具链的glibc版本、目标机的系统版本、第三方库的版本三者必须协调。hello程序因为只依赖libc所以最容易验证。一旦hello跑通了说明工具链和系统的基本匹配没问题后面再遇到问题大概率是具体某个库的配置问题而不是工具链本身的问题。这个排查思路能帮你省下大量时间。另外分享一个小技巧在板子上建一个/home/orangepi/cross_test目录专门放交叉编译的测试程序。每次换工具链或者改配置先编译一个hello丢进去跑确认没问题再编译大项目。这个习惯让我避免了很多次编译了两小时拷过去跑不起来的尴尬。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门