build_all() 完整编译流程
build_all()
├── [可选] build_recovery ← 只有 RK_ENABLE_RECOVERY=y 才执行
├── build_sysdrv ← uboot + 内核 + 根文件系统 + busybox + 驱动模块
├── build_media ← Rockchip 媒体库(rockit、mpi、isp、rga 等)
├── build_app ← 用户态应用程序(rkipc 等)
├── build_firmware ← 打包所有镜像
└── finish_build
第一步:build_sysdrv — 系统驱动层
# build.sh 第 541 行
function build_sysdrv(){
make -C ${SDK_SYSDRV_DIR} # → sysdrv/Makefile 的 all 目标
}
sysdrv/ 的 Makefile all 目标:
all: uboot kernel rootfs env
它依次调用 4 个子步骤:
1.1 make uboot — 编译 uboot
# sysdrv/Makefile 第 82-92 行
uboot: prepare
make -C u-boot rv1106_defconfig # 配置 uboot
./u-boot/make.sh --spl-new # 编译 uboot + SPL
cp uboot.img output/image/
cp idblock.img output/image/ # 一级引导
cp download.bin output/image/ # 下载模式固件
产出文件:
output/out/sysdrv_out/ → 最终复制到 output/image/
├── uboot.img ← uboot 主镜像
├── idblock.img ← 一级引导(SPL + ddr init + 安全启动)
└── download.bin ← 烧录模式固件(loader)
1.2 make kernel — 编译内核
# sysdrv/Makefile 第 100-140 行
kernel: prepare
make -C kernel ARCH=arm rv1106_defconfig # 配置内核(含 fragment 合并)
make -C kernel ARCH=arm zImage dtbs -jN # 编译内核本身
make -C kernel ARCH=arm boot.img # 打包 boot.img(含内核 + dtb + resource)
cp boot.img output/image/
cp vmlinux output/bin/ # 带调试信息的完整内核
cp *.dtb output/bin/
关键点: 这里用的就是 make 命令,但通过 .config + rv1106-evb.config(fragment)合并生成最终配置。它不只是简单地执行 make,还做了:
- fragment 合并:
rv1106_defconfig+rv1106-evb.config→ 最终.config - 编译驱动模块(
make modules) - 调用
update_dtb_bootargs.sh修改设备树中的启动参数(root=/dev/xxx) - 打包 FIT 格式的
boot.img
产出文件:
output/image/
├── boot.img ← FIT 格式,内含 zImage + dtb + resource
output/out/sysdrv_out/
├── vmlinux ← 完整内核(带调试符号)
├── rv1106g-evb1-v11.dtb
└── kernel_drv_ko/ ← 内核驱动模块 .ko 文件
1.3 make rootfs — 构建根文件系统
# 这步最复杂,依赖链:rootfs_prepare → pctools → busybox → boardtools → drv → strip
rootfs: rootfs_prepare pctools busybox boardtools drv
子步骤详情:
| 子步骤 | 做的事 | 产出 |
|---|---|---|
rootfs_prepare | 解压 rootfs 脚本模板 + 拷贝工具链运行时库(libc, libm, libpthread 等) 到 rootfs_*/ | 基础根文件系统骨架 |
pctools | 编译 PC 端工具(mkenvimage、mk-fitimage.sh、mkfs.ubifs 等) | output/out/sysdrv_out/pc/ |
busybox | 编译 busybox(busybox-1.27.2),生成 _install/bin/busybox 及所有 symlink | 提供 sh, ls, cp, mv 等基础命令 |
boardtools | 编译板端工具(来自 sysdrv/tools/board/) | 一些板级小工具 |
drv | make modules_install → 提取所有 .ko 到 kernel_drv_ko/ | 内核模块拷贝 |
strip | 如果是 RELEASE 模式,strip 掉调试符号 | 缩小根文件系统体积 |
最后根据存储介质打包根文件系统镜像:
- spi_nand →
rootfs_ubi→mkfs_ubi.sh→rootfs_base.img(UBIFS 格式) - emmc →
rootfs_ext4→mkfs_ext4.sh→rootfs_base.img(ext4 格式) - spi_nor →
rootfs_jffs2→mkfs_jffs2.sh→rootfs_base.img(JFFS2 格式)
产出文件:
output/out/sysdrv_out/
├── rootfs_glibc_rv1106/ ← 根文件系统目录(未打包)
├── rootfs_glibc_rv1106.tar ← 根文件系统 tar 包
├── pc/ ← PC 端工具
├── bin/ ← 板端工具 + 调试文件
└── kernel_drv_ko/ ← 内核驱动模块
第二步:build_media — 媒体库
# build.sh 第 523 行
function build_media(){
make -C ${SDK_MEDIA_DIR} # → media/Makefile
}
# media/Makefile
all: media_libs
make -C ./samples # 编译 media 示例程序
cp -rfa ... 到 output/out/media_out/ # 拷贝全部产出
media_libs:
# 遍历所有子目录编译:
# rockit/ — Rockchip 多媒体处理框架
# isp3.x/ — 图像信号处理库
# rv1106/ — 芯片级库(mpp、rga 等)
# 等等
产出文件(到 output/out/media_out/):
media_out/
├── lib/ ← 所有 .so(librockit.so, libmpi.so, libisp.so, librga.so, libmpp.so...)
├── include/ ← 头文件(rockit 等 API 头)
├── bin/ ← 示例程序
├── share/isp_iqfiles/ ← 各传感器 IQ 调优文件(*.bin)
├── usr/ ← 额外资源
└── root/ ← 需要放到根文件系统 / 下的文件
这是给 app 层提供依赖 — build_app 会链接 media_out 下的 .so 和头文件。
第三步:build_app — 用户态应用程序
# build.sh 第 461 行
function build_app(){
check_config RK_APP_TYPE || return 0 # RK_APP_TYPE 为空则跳过
build_meta --export --media_dir ... # 导出 meta 头文件
make -C ${SDK_APP_DIR} # → project/app/Makefile
}
会被跳过的条件: RK_APP_TYPE 未设置或为空 → 不编译
# project/app/Makefile
all:
# 遍历所有子目录(rkipc/、ipcweb/、uvc_app_tiny/ 等)
# 每个子目录根据 RK_APP_TYPE 决定是否编译
make -C component/rkadk/ # 条件编译
make -C component/lvgl/ # 条件编译
make -C rkipc/ # RK_APP_TYPE=RKIPC_RV1106 时编译
make -C uvc_app_tiny/ # RK_APP_TYPE=UVC_TINY 时编译
# ...
# 最后把所有产出拷贝到 out/
MAROC_COPY_PKG_TO_APP_OUTPUT # → project/app/out/
产出文件(到 project/app/out/):
app/out/
├── bin/rkipc ← 主程序(IP Camera 守护进程)
├── lib/ ← .so(librkfsmk.so, libwpa_client.so 以及第三方库)
└── share/ ← 配置文件(*.ini)、字体、测试音频
第四步:build_firmware — 打包固件镜像
# build.sh 第 1943 行
function build_firmware(){
build_env # 生成 env.img(uboot 环境变量分区)
build_meta # 生成 meta 分区(摄像头参数、IQ 文件等)
__PACKAGE_ROOTFS # 解压 rootfs.tar → 合并 app_out/media_out 内容
__PACKAGE_OEM # 打包 OEM 分区(/oem,放 app 和 media 的 bin/lib/share)
__PACKAGE_USERDATA # 打包空 userdata 分区
build_mkimg rootfs ... # 制作 rootfs 分区镜像(UBIFS/ext4/JFFS2)
build_mkimg oem ... # 制作 OEM 分区镜像
build_mkimg userdata ... # 制作 userdata 分区镜像
build_updateimg # 打包 update.img(统一烧录镜像)
}
最终固件产出(到 output/image/):
output/image/
├── uboot.img ← uboot 镜像
├── idblock.img ← 一级引导
├── download.bin ← 烧录 loader
├── boot.img ← 内核 + dtb + resource
├── rootfs.img ← 根文件系统(UBIFS/ext4/JFFS2)
├── oem.img ← OEM 分区(app + media 的 bin/lib/share + IQ 文件)
├── userdata.img ← 空 userdata 分区
├── env.img ← uboot 环境变量(分区表、启动参数)
├── misc.img ← misc 分区(恢复模式标记)
└── update.img ← 统一烧录包(包含以上所有)
编译流程全局图
.BoardConfig.mk ← 您在这里配置芯片、分区、APP_TYPE 等
│
build.sh all
│
┌──────────────┼──────────────┐
│ │ │
build_sysdrv build_media build_app
│ │ │
┌────┼────┐ media/ 下 app/ 下各子目录
│ │ │ 各库源码 根据 RK_APP_TYPE 选择编译
uboot kernel rootfs
│ │ │ │ │
│ │ │ media_out/ app/out/
│ │ │ (.so + .h) (rkipc + .so + .ini)
│ │ │ │ │
└────┼────┼─────────┼──────────────┘
│ │ │ │
│ │ build_firmware │
│ │ __PACKAGE_ROOTFS ◄──┘
│ │ __PACKAGE_OEM ◄──┘(合并到 oem 分区)
│ │ │
│ │ output/image/
│ │ ├── boot.img
│ │ ├── rootfs.img
│ │ ├── oem.img
│ │ └── update.img
│ │
┌────┘ └──────────────────────────┐
│ │
uboot 阶段编译 kernel 阶段编译
只是 make + 脚本拷贝 不只是 make:
- fragment 合并配置
- 修改 dtb 启动参数
- 打包 FIT boot.img
- 编译驱动模块