第二章 开发环境搭建:Ubuntu交叉编译环境、SDK下载与解压、Buildroot与Yocto构建系统选择

好,咱们直接进入正题。搭建开发环境这件事,说难不难,说简单吧,我第一次搞的时候也踩了不少坑。你想想看,瑞芯微的芯片那么多,每个平台的SDK结构还不完全一样,要是环境没搭对,后面编译起来全是泪。

这一章,我就带你一步步把环境捋顺。咱们的目标很明确:让你的电脑能编译出能在RK芯片上跑的程序

2.1 Ubuntu交叉编译环境搭建

为什么非要用Ubuntu?说白了,瑞芯微官方提供的工具链和SDK,都是在Ubuntu上验证过的。我个人习惯用Ubuntu 18.04或20.04 LTS,这两个版本最稳。你非要用22.04也行,但有些老SDK的依赖包可能会报错,到时候别来找我哭(笑)。

2.1.1 安装基础依赖包

拿到一台新装的Ubuntu,第一件事就是装包。别偷懒,少了哪个后面编译都会卡住。我一般直接跑下面这条命令,把常用的全装上:

sudo apt-get update
sudo apt-get install -y \
    build-essential \
    git \
    repo \
    wget \
    curl \
    python3 \
    python3-pip \
    libssl-dev \
    libncurses5-dev \
    u-boot-tools \
    device-tree-compiler \
    flex \
    bison \
    gawk \
    texinfo \
    gettext \
    zlib1g-dev \
    libglib2.0-dev \
    libpixman-1-dev \
    libtool \
    autoconf \
    automake \
    cmake \
    meson \
    ninja-build \
    pkg-config \
    libudev-dev \
    libusb-1.0-0-dev
小提示: 如果你用的是Ubuntu 20.04,记得把 python 软链接到 python3。有些老脚本写死了 #!/usr/bin/env python,找不到就会报错。我当初就被这个坑过,查了半天。

2.1.2 安装交叉编译工具链

瑞芯微官方推荐用 gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu 这个版本。为什么是10.3?因为Buildroot和Yocto的某些组件对GCC版本有要求,太新或太旧都可能出问题。

下载解压的步骤很简单:

# 下载工具链
wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz

# 解压到 /opt 目录
sudo tar -xf gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz -C /opt/

# 配置环境变量(建议写到 ~/.bashrc 里)
export PATH=/opt/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin:$PATH
export CROSS_COMPILE=aarch64-none-linux-gnu-
export ARCH=arm64
注意: 环境变量一定要配对。我见过有人把 CROSS_COMPILE 写成了 aarch64-linux-gnu-,结果编译出来的程序在板子上跑不起来。检查一下:aarch64-none-linux-gnu-gcc --version 能正常输出版本号才算成功。

2.2 SDK下载与解压

瑞芯微的SDK通常通过 repo 工具来管理。repo是Google为Android开发的一套Git仓库管理工具,瑞芯微把它拿来管理BSP(板级支持包)了。我第一次用repo的时候也觉得麻烦,但用习惯了会发现,它确实能帮你省掉很多手动拉分支的活。

2.2.1 初始化repo环境

# 安装repo工具
sudo apt-get install -y repo

# 创建一个工作目录,比如 ~/rk3588_sdk
mkdir ~/rk3588_sdk
cd ~/rk3588_sdk

# 初始化repo(这里以RK3588为例)
repo init -u https://github.com/rockchip-linux/manifests -b master -m rk3588_linux.xml

# 同步代码(这一步会下载所有子仓库,时间比较长)
repo sync -c --no-tags -j4

这里有个关键点:-j4 表示用4个线程并行下载。如果你的网络带宽够大,可以改成 -j8 甚至 -j16。但别贪心,线程太多反而容易因为网络抖动导致失败。我一般用 -j4,稳。

2.2.2 解压与目录结构

同步完成后,你会看到类似这样的目录结构:

rk3588_sdk/
├── app/                # 上层应用
├── buildroot/          # Buildroot构建系统
├── device/             # 板级配置
├── docs/               # 文档
├── external/           # 第三方库
├── kernel/             # Linux内核
├── prebuilts/          # 预编译工具
├── rkbin/              # 瑞芯微二进制文件(如ATF、DDR初始化)
├── tools/              # 烧录工具、打包脚本
├── u-boot/             # U-Boot引导程序
└── yocto/              # Yocto构建系统(部分SDK有)
重点: rkbin/ 目录下的文件是瑞芯微提供的闭源二进制,比如ATF(ARM Trusted Firmware)和DDR初始化代码。这些文件不能修改,但必须存在。如果你编译出来的固件启动不了,先检查 rkbin/ 是不是完整。

2.3 Buildroot与Yocto构建系统选择

这个问题我几乎每次培训都会被问到:到底用Buildroot还是Yocto?我的回答是:看你的产品需求

咱们先看看两者的区别:

特性 Buildroot Yocto
构建速度 快(30分钟~1小时) 慢(2~4小时,首次甚至更久)
定制灵活性 中等 高(通过Layer和Recipe)
包管理 无(编译时静态选择) 有(支持RPM/DEB/IPK)
学习曲线 平缓 陡峭
适用场景 嵌入式设备、IoT、简单产品 复杂产品、需要长期维护、多平台

2.3.1 什么时候选Buildroot?

我个人习惯:原型验证阶段,或者产品功能比较固定的时候,用Buildroot。比如你做一个智能摄像头,功能就是采集视频、编码、上传,不需要频繁更新软件包。Buildroot编译一次,烧进去就能跑,省心。

编译命令也很简单:

cd buildroot/
make rockchip_rk3588_defconfig
make -j4

编译完成后,在 output/images/ 目录下会生成 rootfs.ext4boot.img 等镜像文件。直接拿去烧录就行。

避坑指南: 我曾经在Buildroot里加了一个Qt库,结果编译了整整3个小时。后来发现是没开 BR2_PACKAGE_QT5 的某些选项,导致它把整个Qt源码都编译了一遍。所以,用Buildroot时,尽量只选你需要的包,别贪多。

2.3.2 什么时候选Yocto?

Yocto适合那种需要长期维护、频繁更新、或者要支持多种硬件平台的项目。比如你做一款商显主板,客户可能今天要换WiFi模块,明天要加个4G模组。用Yocto的话,你只需要加一个Layer,改几行配置,就能重新生成固件。

Yocto的编译流程稍微复杂一点:

cd yocto/
source oe-init-build-env build-rk3588
bitbake core-image-minimal

第一次编译Yocto,我建议你做好心理准备。它会把整个工具链、交叉编译环境、所有依赖包都从源码编译一遍。我第一次编译RK3588的Yocto,用了将近5个小时。但第二次以后,因为有缓存,就快多了,大概1小时左右。

注意: Yocto对磁盘空间要求很高。一个完整的构建环境,至少需要 100GB 空闲空间。我见过有人用50GB的虚拟机编译Yocto,结果编译到一半磁盘满了,前功尽弃。建议你至少准备 200GB

2.3.3 我的选择建议

如果你还在犹豫,我给你一个简单的判断标准:

  • 团队人数少于3人,产品功能固定 → 选Buildroot
  • 团队人数多于5人,产品需要持续迭代 → 选Yocto
  • 只是学习、做实验 → 选Buildroot,快

嗯,其实没有绝对的对错。我见过有人用Buildroot做出了量产产品,也见过有人用Yocto做原型验证。关键是你熟悉哪个,哪个就能帮你快速出活

2.4 验证环境是否搭建成功

环境搭好了,怎么知道对不对?写一个最简单的Hello World,交叉编译一下,放到板子上跑。

// hello.c
#include <stdio.h>

int main() {
    printf("Hello, RK3588!\n");
    return 0;
}
# 交叉编译
aarch64-none-linux-gnu-gcc -o hello hello.c

# 查看文件信息
file hello
# 输出应该是:ELF 64-bit LSB executable, ARM aarch64, ...

把编译好的 hello 文件通过ADB或SCP传到板子上,运行:

./hello
# 输出:Hello, RK3588!

看到这行输出,恭喜你,环境搭建成功了!

总结一下: 这一章我们做了三件事:装了交叉编译工具链、下载了解压了SDK、了解了Buildroot和Yocto的区别。下一章,咱们就开始真正动手编译一个完整的固件,然后烧到板子上跑起来。

好,今天就到这儿。有什么问题,咱们下节课见。