跳转至

构建系统设计

项目提供两个构建入口:scripts/build.sh(Linux 构建,build.sh + CMake 混合架构)与 scripts/build_ohos.sh(OHOS 构建,基于 OpenHarmony 标准构建体系)。本文说明两者的内部设计。

概述

两种构建形态

同一份代码支持两种构建形态,在 repo init 时通过 groups 选择(详见目录结构):

形态 构建入口 构建体系 说明
Linux 构建 scripts/build.sh CMake 产出 Linux 应用与 BSP 镜像,不含 OpenHarmony 社区代码(repo init -g linux
OHOS 构建 scripts/build_ohos.sh OpenHarmony 标准构建(GN) 依赖 ohos/ 社区代码与 ohos_adapt/ 适配层,产出 OHOS 镜像(默认 group 全量下载)

Linux 构建分层

Linux 构建系统由六层组成,每层有明确的边界和职责:

位置 职责
构建入口 scripts/build.sh 加载配置、预处理、启动编译构建
SDK 层 sdk/ SDK 处理、BSP/MPP 编译
第三方层 open_source/ 各库自带编译构建文件,由 Kconfig 控制
组件层 components/ adapter / hiai / network / media
应用层 apps/<BOARD>/ references / samples / solutions,每个应用带 app.defconfig配置文件
配置层 **/Kconfig + configs/ menuconfig菜单配置,kconfig2*.py转换Kconfig符号为编译构建工具变量
flowchart TD
    A["app.defconfig → .config"] --> B["kconfig2*.py → .config.cmake"]
    B --> C[CMake configure] 
    C --> D["SDK: BSP + MPP 编译"]
    C --> E["第三方库 → 组件 → 应用"]
    D --> F["SDK"]
    E --> G["_build/bin/ + lib/ + third_party/"]

build.sh 只做调度:加载 defconfig、触发 SDK 准备、调用编译构建工具。

配置数据流

配置单向流动,不可逆转:

Kconfig(选项声明与依赖关系)
    ↓  menuconfig
.config(配置源头)
    ↓  kconfig2*.py
.config.cmake
构建

.config.config.cmake 新时,build.sh 自动重新转换。禁止手动编辑 .config.cmake——它是派生文件,下次转换会覆盖。

CMake 侧加载顺序:

configs/config.cmake
  1. 加载 .config.cmake 
  2. include configs/sdk.cmake — SDK 版本号与路径

SDK 版本由 CONFIG_SDK_VERSION(Kconfig → .configsdk/build.cmake)统一决定。

变量命名规则:

前缀 作用域 示例
ENABLE_OS_* open_source/ 第三方库 ENABLE_OS_OPENSSL
ENABLE_SDK_OS_* open_source/ SDK 补充包(仅 prepare 阶段读取) ENABLE_SDK_OS_LINUX
ENABLE_COMP_* components/ 组件 ENABLE_COMP_ADAPTER
ENABLE_DRV_* components/adapter/ 驱动 ENABLE_DRV_LCD_ST7789V
ENABLE_SDK_BUILD_* SDK 构建选项 ENABLE_SDK_BUILD_BSP

架构分层

open_source 层

open_source/ 下的源码包由根 CMakeLists.txt 统一驱动,通过 ENABLE_OS_* 开关按需引入。各库自带 CMakeLists.txt,独立完成解压、patch、ExternalProject 编译。

构建方式 CMake 导入目标
openssl ./Configure third_party::openssl
curl autoconf ./configure third_party::curl
libdrm meson + ninja third_party::libdrm
lvgl CMake third_party::lvgl
cjson 源码内联
mqtt Makefile + patch third_party::mqtt

应用自动发现

apps/<BOARD>/ 下子目录中有 .c.cpp 源文件即自动创建 CMake 目标,无需修改任何 CMakeLists.txt。三类应用按目的区分:

目录 定位
samples/ 组件能力的单点功能案例
references/ 准产品的核心功能案例
solutions/ 产品的完整功能案例

构建操作

构建

# 默认构建(从 .target 读取上次的目标)
bash scripts/build.sh build

# 指定目标应用
bash scripts/build.sh build --target cv610_ev_board samples framework_media

# 指定并行数
bash scripts/build.sh build -j 8

# 清理重建
bash scripts/build.sh distclean 
bash scripts/build.sh build

--target 的三个参数对应 apps/<BOARD>/<APP_TYPE>/<APP_NAME>/ 路径,会自动加载该目录下的 app.defconfig 并写入 .target 文件。不指定 --target 时从 .target 读取上次的目标。

# 交互式配置
bash scripts/build.sh menuconfig --target cv610_ev_board samples framework_media

交互式菜单按模块层级组织,方向键移动、空格切换开关,保存退出后 .config.config.cmake 自动更新。

构建产物

构建产物位于 _build/

_build/
├── bin/            # 应用可执行文件
├── lib/            # 组件静态库
├── third_party/    # 第三方库
├── sdk/            # SDK 安装目录
└── install/        # 烧录镜像(CONFIG_BUILD_INSTALL=y 时生成)
产物 说明
bin/ 应用可执行文件,最终烧录到板端的主体
lib/ 组件静态库(adapter/hiai/media/network),中间产物
third_party/ 第三方库编译结果,被组件和应用链接
sdk/ SDK 解压与编译产物(uImage、u-boot、rootfs、.ko)
install/ CONFIG_BUILD_INSTALL=y 时生成,含打包好的烧录镜像

SDK 编译

SDK 编译分为 BSP(内核/uboot/rootfs)和 MPP(驱动模块)两部分,由 sdk/build.cmake 触发。

BSP 与 MPP

SDK 编译在 build 时触发,分为两部分:

部分 产物 检测条件
BSP uImage、uboot、rootfs SDK包发布目录下uImage 存在则跳过
MPP .ko 内核模块 每次强制重新编译

相关 Kconfig 开关:

符号 默认 作用
SDK_BUILD_BSP y 编译 BSP。关闭后跳过内核/uboot/rootfs 编译,SDK_BSP_DEBUG 也随之禁用,应用层仍可正常编译
SDK_BSP_DEBUG y y=开发模式(UART 控制台/telnetd/tftp),n=发布模式
SDK_BUILD_MPP n 编译 MPP 驱动(SDK 预编译 .ko 通常可直接用)

BSP 使用

编译时机与跳过逻辑

BSP 编译产物为 uImage(内核镜像)、u-boot、rootfs。build.cmake 在 SDK 包发布目录下递归检测 uImage,存在则跳过 BSP 编译:

  • 首次构建:SDK 解压后无 uImage,自动触发 BSP 编译(含 kernel、u-boot、rootfs,耗时较长)
  • 后续构建:uImage 已存在,跳过 BSP,仅做 CMake 层增量编译
  • 强制重建 BSPbash scripts/build.sh distclean 删除构建目录,下次构建重新编译全部(含 BSP)

跳过 BSP 编译

关闭 CONFIG_SDK_BUILD_BSP 可跳过 BSP,但会同时禁用 depends on SDK_BUILD_BSP 的驱动选项(如 sensor、LCD 等需随内核编译的 out-of-tree 驱动)。仅在已有预编译镜像、仅需编译应用层时使用。

补充

  • 应用 Patch:应用可通过自身目录下的 patch/apply_patches.sh 修改 SDK 源码(u-boot、linux 内核等),详见下文 Patch 机制
  • 内核模块选项:应用可通过 bsp_make_opts 文件向内核/uboot 编译传递自定义选项,由 build.cmake 自动读取
  • 部分源码不开源,使用预编译的二进制文件如wifi驱动。

Patch 机制

板仓公共patch在apps/<board>/bsp/patch/目录下,会优先于应用patch执行。

部分应用需修改 SDK 源码(u-boot、linux、BSP Makefile、DTS、GSL 等)以实现自定义功能或优化性能。build.cmake 在 BSP 编译前从 .target 文件推导目标应用,拼出 apps/<board>/<type>/<name>/patch/ 路径,执行 apply_patches.sh

完整流程

bash scripts/build.sh build 内部执行顺序:

  1. --target → 写入 .target,定位 app.defconfig(应用的 Kconfig 默认配置,优先级最低,会被 menuconfig 修改和后续 --target 覆盖)
  2. 扫描目标应用目录下的 Kconfig → 生成 Kconfig.apps
  3. kconfiglib 加载 defconfig(读 Kconfig + Kconfig.apps)→ 写入 .config
  4. prepare:SDK 解压 + open_source 预拷贝(幂等)
  5. .config 转换成 .config.cmake
  6. SDK patch → BSP 编译→ MPP 编译
  7. CMake configure(cmake -B _build
  8. CMake build(第三方库 → 组件 → 应用)

OHOS 构建

OHOS 构建由 scripts/build_ohos.sh 驱动:在 OpenHarmony 标准构建(ohos/build.sh,GN 体系)的外层完成 SDK 准备、补丁应用、配置转换与产物后处理,最终产出 OHOS 镜像。

前置条件

  • 代码需以 OHOS 形态下载:repo init 使用默认 group(含 ohos/ 社区代码与 ohos_adapt/ 适配层,详见目录结构)。
  • sdk/Hi3516CV610/ SDK 已随 repo sync 落地(hisupport SDK需将 Hi3516CV610_SDK_V1.0.2.0.tgz 放入 sdk/,脚本自动解压)。

命令用法

./scripts/build_ohos.sh --target <BOARD> <APP_TYPE> <APP_NAME> [--sdk-type hispark|hisupport] [--shell busybox|toybox] [ohos-args...]

# 示例
bash scripts/build_ohos.sh --target cv610_ev_board references factory_demo/ws73_lcd --sdk-type hispark --shell busybox --product-name=ipcamera_hispark_hi3516cv610_linux --ccache --no-prebuilt-sdk
选项 说明
--target BOARD APP_TYPE APP_NAME 指定目标应用,定位 app.defconfig,与 Linux 构建一致
--sdk-type SDK 类型:hispark/ hisupport
--shell rootfs shell:busybox(默认)/ toybox
其余参数 原样透传给 OpenHarmony build.sh(如 --product-name--gn-args build_xts=true --cccache 等);--product-name 默认 ipcamera_hispark_hi3516cv610_linux

构建流程

build_ohos.sh 内部按阶段依次执行:

阶段 内容
prepare LFS 拉取;SDK 解压/变体补丁;应用 ohos_adapt/patch/ 下的 OHOS 补丁(按 SDK 类型区分 2D_/2B_ 变体,marker 幂等,切换 SDK 类型时自动反打旧补丁);拷贝 device/soc/vendor overlay;解压交叉编译工具链;应用案例 oh_product/ overlay
app BSP 与 Linux 构建的 Patch 机制同构:两级补丁(板级 apps/<board>/bsp/patch/ + 案例 patch/apply_patches.sh);通过 bsp_make_opts 只读通道派生 APP_DEFCONFIG/APP_NAND_ENV/UBI_SIZE 等变量;以案例 defconfig 覆盖 OHOS 内核 defconfig(首次备份原版,幂等)
SDK 编译 编译 busybox、u-boot(含案例 env nand_env.bin 覆盖,marker 记录 env 来源,案例切换时强制重建)
OHOS 构建 生成 sdk_config.gni(SDK 类型/路径/工具链);由 scripts/ohos/defconfig_to_gni.pyapp.defconfig 转换为 app.gni(应用配置进入 GN 体系);调用 ohos/build.sh 完成 OpenHarmony 标准构建
后处理 busybox 模式下将 busybox 安装进 rootfs(替换 toybox 链接与二进制)并重新生成 rootfs 镜像;rootfs 产物名与烧录表(nand_burn_table.xml)对齐

配置转换

OHOS 构建复用 Linux 构建的 app.defconfig,通过转换脚本进入 GN 体系,不在 GN 侧重复维护配置:

app.defconfig ──(defconfig_to_gni.py)──▶ app.gni(应用配置)
SDK 类型/路径 ──(build_ohos.sh 生成)──▶ sdk_config.gni(SDK 参数)

与 Linux 构建的差异

差异点 Linux 构建 OHOS 构建
构建体系 CMake OpenHarmony GN
配置流向 app.defconfig.config.config.cmake app.defconfigapp.gni / sdk_config.gni
OHOS 代码 不需要(-g linux 下载) 必需(默认 group 下载)
内核/uboot sdk/build.cmake 编译 BSP build_ohos.sh 编译 u-boot,内核由 OHOS 标准构建编译
rootfs CMake 打包 OpenHarmony 标准构建 + busybox 后处理

命令参考

build.sh 常用命令格式与选项速查,设计原理见上文各节。

命令格式

bash scripts/build.sh [子命令] [选项]

子命令可省略,默认值为 build

子命令

子命令 说明
build 配置并编译
menuconfig 启动 Kconfig TUI 交互式配置

build 选项

--target BOARD APP_TYPE APP_NAME

指定目标应用,自动加载案例的配置。

参数 说明 示例
BOARD apps/ 下的板卡目录 cv610_ev_board
APP_TYPE 应用分类 references / samples / solutions
APP_NAME 应用名称 capture_picture

解析配置的路径:apps/<BOARD>/<APP_TYPE>/<APP_NAME>/app.defconfig

支持选项:

选项 说明
--jobs N 并行编译数,默认取 CPU 核心数
-DKEY=VALUE 传递的变量,如 -DAPP_VARIANT=FINGERTIP。可重复使用
# 从 Kconfig 默认值启动配置
bash scripts/build.sh menuconfig

# 加载 app.defconfig 作为初始配置后启动
bash scripts/build.sh menuconfig --target cv610_ev_board samples framework_media

menuconfig 子命令启动 TUI,退出TUI后自动将 .config 转换为 .config.cmake