.. _build_guide: ================ 构建系统指南 ================ 本文档详细介绍 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 参数参考 ================= .. code-block:: shell ./build.sh [选项] -S <项目路径> -DBOARD=<板型> .. list-table:: :widths: 25 75 :header-rows: 1 * - 选项 - 说明 * - ``-S `` - 指定项目源码路径(默认为 SDK 根目录) * - ``-DBOARD=<板型>`` - 目标板型(必需),SDK 内置 ``arcs_mini`` 和 ``arcs_evb`` * - ``-B `` - 指定构建输出目录(默认为 ``build``) * - ``-C`` - 清理构建目录后重新构建 * - ``-t `` - 指定构建目标(如 ``menuconfig``) * - ``-j `` - 并发构建任务数(默认 4) * - ``-r`` - Release 模式(移除 DEBUG_PATH 信息) * - ``-w`` - 将编译警告视为错误 * - ``-v`` - 显示详细的编译命令 * - ``-d`` - 调试模式(自动启用 ``-v``,附加 ninja 诊断输出) * - ``-G `` - 指定构建工具(``Ninja`` 或 ``Makefile``,默认 ``Ninja``) * - ``-D=`` - 传递 CMake 变量,可多次使用 命令示例 -------- .. code-block:: shell # 基本编译 ./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`` 依赖以下环境变量,均支持自动发现,通常无需手动设置: .. list-table:: :widths: 30 70 :header-rows: 1 * - 环境变量 - 说明 * - ``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/`` 目录自动设置。 如果自动发现失败(例如目录结构不符合约定),可手动导出: .. code-block:: shell 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 .. _external_project_integration: 外部工程集成 ============ ``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. **从脚本所在目录开始,向上逐级搜索**: a. 检查当前目录自身是否为 SDK 根目录(是否存在 ``cmake/listenai-cmake-config.cmake``) b. 检查当前目录的一级子目录是否包含 SDK c. 若未找到,继续向上级目录重复 a、b 步骤 3. **查找失败** — 报错并提示手动设置 ``ARCS_BASE`` 各场景查找示例: .. list-table:: :widths: 40 60 :header-rows: 1 * - 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`` 环境变量。 使用示例 -------- .. code-block:: shell # 方式 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 项目完全一致,无需额外适配: .. code-block:: cmake 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`` 遵循固定模式: .. code-block:: cmake 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_=`` 格式: .. code-block:: kconfig # 启用日志 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 # 构建系统配置选项 使用 menuconfig ---------------- menuconfig 提供交互式的图形化配置界面: .. code-block:: shell ./build.sh -S samples/helloworld -t menuconfig -DBOARD=arcs_mini 在 menuconfig 中可以: - 浏览所有可用配置项及其依赖关系 - 启用/禁用驱动和组件 - 调整参数(缓冲区大小、DMA 通道等) - 查看配置项的帮助说明 .. note:: menuconfig 修改后的配置保存在构建目录中。如需持久化,应将对应的 ``CONFIG_*`` 项写入项目的 ``prj.conf`` 文件。 CMake 扩展 API =============== SDK 提供了一组 CMake 宏/函数,用于简化项目和库的构建配置。 可执行目标 ---------- .. code-block:: cmake # 创建可执行目标(自动链接 SDK 运行时库) listenai_add_executable(my_app) # 添加源文件(使用标准 CMake target_sources) target_sources(my_app PRIVATE src/main.c src/app.c) 库目标 ------ .. code-block:: cmake # 定义一个命名库 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 ) 链接与依赖 ---------- .. code-block:: cmake # 链接其他库 listenai_link_libraries(some_other_lib) 构建输出 ======== 编译成功后,构建产物位于输出目录(默认 ``build/``): .. list-table:: :widths: 30 70 :header-rows: 1 * - 文件 - 说明 * - ``.bin`` - 烧录固件二进制文件 * - ``.elf`` - 带调试信息的 ELF 文件(用于 GDB 调试) * - ``.map`` - 链接映射文件(分析内存占用) * - ``compile_commands.json`` - 编译数据库(供 IDE / clangd 使用) * - ``generated/include/autoconf.h`` - Kconfig 生成的配置头文件