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/一些板级小工具
drvmake modules_install → 提取所有 .ko 到 kernel_drv_ko/内核模块拷贝
strip如果是 RELEASE 模式,strip 掉调试符号缩小根文件系统体积

最后根据存储介质打包根文件系统镜像:

  • spi_nand → rootfs_ubimkfs_ubi.shrootfs_base.img(UBIFS 格式)
  • emmc → rootfs_ext4mkfs_ext4.shrootfs_base.img(ext4 格式)
  • spi_nor → rootfs_jffs2mkfs_jffs2.shrootfs_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
                              - 编译驱动模块