构建系统指南

本文档详细介绍 ARCS SDK 的构建系统架构、配置方法和使用技巧。

概述

ARCS SDK 采用 CMake + Ninja + Kconfig 三位一体的构建系统:

  • CMake (3.19+):项目配置与构建规则管理

  • Ninja:高效增量编译(也支持 Unix Makefiles)

  • Kconfig:模块化内核配置系统,管理功能开关和参数

构建入口为 SDK 根目录下的 build.sh 脚本,封装了完整的配置、编译、后处理流程。

构建流程

完整的构建流程如下:

build.sh
  │
  ├── 1. 解析命令行参数 (-S, -DBOARD, -C, ...)
  ├── 2. 发现开发工具 (cmake, ninja, 工具链)
  ├── 3. 自动查找 SDK 根目录 (ARCS_BASE)
  │     └── 从 build.sh 所在目录向上逐级搜索
  │         通过标志文件 cmake/listenai-cmake-config.cmake 识别
  │
  ├── 4. CMake 配置阶段
  │     ├── find_package(listenai-cmake) 加载 SDK 构建系统
  │     ├── 板型搜索与加载 (BOARD, BOARD_SEARCH_PATH)
  │     ├── Kconfig 解析 → 生成 autoconf.h
  │     ├── 工具链配置
  │     └── 模块发现与注册
  │
  ├── 5. 编译阶段 (Ninja 并行编译)
  │
  └── 6. 后处理 (ELF → BIN, 添加固件头)

build.sh 参数参考

./build.sh [选项] -S <项目路径> -DBOARD=<板型>

选项

说明

-S <path>

指定项目源码路径(默认为 SDK 根目录)

-DBOARD=<板型>

目标板型(必需),SDK 内置 arcs_miniarcs_evb

-B <path>

指定构建输出目录(默认为 build

-C

清理构建目录后重新构建

-t <target>

指定构建目标(如 menuconfig

-j <N>

并发构建任务数(默认 4)

-r

Release 模式(移除 DEBUG_PATH 信息)

-w

将编译警告视为错误

-v

显示详细的编译命令

-d

调试模式(自动启用 -v,附加 ninja 诊断输出)

-G <type>

指定构建工具(NinjaMakefile,默认 Ninja

-D<var>=<val>

传递 CMake 变量,可多次使用

命令示例

# 基本编译
./build.sh -S samples/helloworld -DBOARD=arcs_mini

# 清理并重新编译
./build.sh -C -S samples/helloworld -DBOARD=arcs_evb

# 运行 menuconfig 配置界面
./build.sh -S samples/helloworld -t menuconfig -DBOARD=arcs_mini

# 使用外部自定义板型
./build.sh -S samples/helloworld -DBOARD=my_board \
    -DBOARD_SEARCH_PATH=/path/to/my_boards

环境变量

build.sh 依赖以下环境变量,均支持自动发现,通常无需手动设置:

环境变量

说明

ARCS_BASE

SDK 根目录路径。脚本从自身所在目录向上逐级搜索,通过标志文件 cmake/listenai-cmake-config.cmake 自动识别 SDK 位置。

LISTENAI_TOOLS_PATH

构建工具路径(含 cmake、ninja 等)。脚本向上查找 listenai-dev-tools/listenai-tools/ 目录自动设置。

NUCLEI_TOOLCHAIN_PATH

GCC 交叉编译工具链路径。脚本向上查找 listenai-dev-tools/gcc/ 目录自动设置。

如果自动发现失败(例如目录结构不符合约定),可手动导出:

export ARCS_BASE=/path/to/arcs-sdk
export LISTENAI_TOOLS_PATH=/path/to/listenai-dev-tools/listenai-tools
export NUCLEI_TOOLCHAIN_PATH=/path/to/listenai-dev-tools/gcc

外部工程集成

build.sh 不要求必须位于 SDK 根目录,支持将 SDK 作为子目录嵌入到独立的应用工程中使用。 SDK 子目录的名称没有限制,脚本通过标志文件 cmake/listenai-cmake-config.cmake 识别 SDK 位置,不依赖目录名。

典型目录结构

my-app/
├── arcs-sdk/              # SDK 作为子目录,目录名可以是任意名称
│   ├── cmake/             # 脚本通过此目录下的标志文件识别 SDK
│   │   └── listenai-cmake-config.cmake
│   ├── build.sh
│   └── ...
├── build.sh               # 从 SDK 复制的构建脚本
├── CMakeLists.txt
├── prj.conf
└── src/
    └── main.c

SDK 自动发现机制

build.sh 通过 find_arcs_base() 函数自动查找 SDK 根目录,查找规则如下:

  1. 已设置 ARCS_BASE — 若环境变量已存在,直接使用,跳过查找

  2. 从脚本所在目录开始,向上逐级搜索

    1. 检查当前目录自身是否为 SDK 根目录(是否存在 cmake/listenai-cmake-config.cmake

    2. 检查当前目录的一级子目录是否包含 SDK

    3. 若未找到,继续向上级目录重复 a、b 步骤

  3. 查找失败 — 报错并提示手动设置 ARCS_BASE

各场景查找示例:

build.sh 位置

查找过程

SDK 根目录(arcs-sdk/build.sh

第 1 轮检查自身目录,直接命中

应用根目录(my-app/build.sh),SDK 是一级子目录

第 1 轮检查自身未命中 → 扫描子目录 → 发现 arcs-sdk/

SDK 子目录(arcs-sdk/scripts/build.sh

第 1 轮未命中 → 向上到 arcs-sdk/ → 第 2 轮检查自身命中

Note

自动查找仅扫描当前目录及其 一级 子目录。如果 SDK 嵌套在更深的层级 (如 deps/arcs-sdk/),需要手动设置 ARCS_BASE 环境变量。

使用示例

# 方式 1:将 build.sh 复制到应用根目录,自动发现 SDK
cd my-app
cp arcs-sdk/build.sh .
./build.sh -S . -DBOARD=arcs_mini

# 方式 2:直接使用 SDK 中的 build.sh,通过 -S 指定应用路径
cd my-app
./arcs-sdk/build.sh -S . -DBOARD=arcs_mini

# 方式 3:SDK 嵌套较深时,手动指定 ARCS_BASE
export ARCS_BASE=/path/to/my-app/deps/arcs-sdk
./build.sh -S . -DBOARD=arcs_mini

应用工程的 CMakeLists.txt 与普通 SDK 项目完全一致,无需额外适配:

cmake_minimum_required(VERSION 3.19)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
find_package(listenai-cmake REQUIRED HINTS $ENV{ARCS_BASE})
project(my_app)
listenai_add_executable(${PROJECT_NAME})
target_sources(${PROJECT_NAME} PRIVATE src/main.c)

项目结构

一个 SDK 项目(示例或应用)的标准目录结构:

my_project/
├── CMakeLists.txt    # 项目构建配置(必需)
├── prj.conf          # 项目 Kconfig 默认配置
├── Kconfig           # 项目级 Kconfig 定义(通常包含 SDK 根 Kconfig)
└── src/
    └── main.c        # 应用入口

CMakeLists.txt 模板

每个项目的 CMakeLists.txt 遵循固定模式:

cmake_minimum_required(VERSION 3.13)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# 加载 SDK 构建系统
find_package(listenai-cmake REQUIRED HINTS $ENV{ARCS_BASE})

# 定义项目名(同时作为输出固件文件名)
project(my_project)

# 创建可执行目标
listenai_add_executable(${PROJECT_NAME})

# 添加源文件
target_sources(${PROJECT_NAME} PRIVATE
    src/main.c
)

find_package(listenai-cmake) 是核心入口,它加载 SDK 的全部构建基础设施:工具链配置、Kconfig 处理、模块发现、链接脚本等。

prj.conf 配置文件

prj.conf 是 Kconfig 的项目级默认配置文件,使用 CONFIG_<symbol>=<value> 格式:

# 启用日志
CONFIG_LOG=y

# 启用 UART0 驱动
CONFIG_LISA_UART_DEVICE=y
CONFIG_LISA_UART0=y

# 设置日志级别
CONFIG_LOG_DEFAULT_LEVEL=3

构建时,Kconfig 系统会合并 prj.conf 与各模块的默认配置,生成最终的 autoconf.h 头文件。

Kconfig 配置

Kconfig 层级

SDK 的 Kconfig 配置按以下层级组织:

Kconfig (SDK 根)
├── system/Kconfig          # 系统配置(含启动配置)
├── soc/Kconfig             # SoC 配置
├── components/Kconfig      # 组件配置 (lisa_os, lisa_log, ...)
├── drivers/Kconfig         # 驱动配置 (uart, spi, i2c, ...)
├── boards/Kconfig          # 板型配置
├── modules/Kconfig         # 第三方模块配置 (FreeRTOS, mbedtls, ...)
└── cmake/Kconfig           # 构建系统配置选项

CMake 扩展 API

SDK 提供了一组 CMake 宏/函数,用于简化项目和库的构建配置。

可执行目标

# 创建可执行目标(自动链接 SDK 运行时库)
listenai_add_executable(my_app)

# 添加源文件(使用标准 CMake target_sources)
target_sources(my_app PRIVATE src/main.c src/app.c)

库目标

# 定义一个命名库
listenai_library_named(my_lib)

# 添加库源文件
listenai_library_sources(
    src/foo.c
    src/bar.c
)

# 条件编译:仅在 CONFIG 启用时包含源文件
listenai_library_sources_ifdef(CONFIG_FEATURE_X
    src/feature_x.c
)

# 添加头文件搜索路径
listenai_include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}/include
)

链接与依赖

# 链接其他库
listenai_link_libraries(some_other_lib)

构建输出

编译成功后,构建产物位于输出目录(默认 build/):

文件

说明

<project>.bin

烧录固件二进制文件

<project>.elf

带调试信息的 ELF 文件(用于 GDB 调试)

<project>.map

链接映射文件(分析内存占用)

compile_commands.json

编译数据库(供 IDE / clangd 使用)

generated/include/autoconf.h

Kconfig 生成的配置头文件