环境搭建与编译指南
本文档介绍 fw-AC79_AIoT_SDK 的完整环境搭建与编译流程,涵盖支持的操作系统与编译方式、杰理编译工具链的安装(手动与自动脚本)、烧录工具的准备、顶层 Makefile 的编译目标机制,以及常见故障的排查方法。
Purpose and Scope
本页面向需要在本仓库(fw-AC79_AIoT_SDK,branch release/AC79NN_SDK_V1.2.0)上进行固件开发、编译与烧录的开发者,说明:
- 各操作系统下的环境前提条件(Windows / Linux / macOS);
- 杰理编译工具链(含
clang交叉编译器)的安装与验证方式; init_env.sh一键初始化脚本的内部机制;- 顶层 Makefile 支持的编译目标(target)及子工程 Makefile 的转发逻辑;
- 烧录工具(USB 升级工具 / 生产烧写工具 / Linux postbuild 工具)的获取与部署;
- 常见编译错误(
clang: command not found、Too many open files等)的定位与解决。
以下内容属于兄弟页面、不在本页展开:具体应用工程的业务功能(参见「应用工程」相关页面)、板级引脚与外设配置(参见「板级配置」相关页面)、固件升级与烧录协议细节(参见「固件升级」相关页面)。
Overview
AC79 系列 AIoT SDK 是杰理(Jieli)面向 WiFi 摄像头、IPC 网络摄像机、故事机、扫码盒等产品的嵌入式固件开发套件。SDK 的构建体系围绕 两个编译入口 设计:
- Code::Blocks IDE(Windows 推荐)——每个板级目录下提供
*.cbp工程文件,双击打开后点击 Build 即可编译,适合以图形化方式开发调试; - Makefile 命令行(Linux 推荐)——SDK 根目录的顶层
Makefile将编译命令转发到各个应用工程的板级Makefile,适合 CI、脚本化构建与批量编译。
两种方式最终都依赖同一套 杰理编译工具链(核心可执行文件为 /opt/jieli/common/bin/clang)。因此环境搭建的核心任务可以概括为:把工具链放到约定的位置、把烧录工具放到约定的位置、然后选择一种编译入口。init_env.sh 脚本将前两步自动化,显著降低了 Linux 用户的上手成本。
Architecture
下图展示了 SDK 环境搭建与编译的整体架构:开发者准备工具链与烧录工具后,通过 IDE 或顶层 Makefile 两条路径驱动子工程 Makefile,最终由杰理工具链产出固件,再交由烧录工具写入目标板。
flowchart TD
subgraph sg_Prepare["环境准备阶段"]
A["下载杰理编译工具链<br/>pkgman.jieliapp.com"] --> B["解压到 /opt/jieli<br/>验证 common/bin/clang"]
C["下载 postbuild 烧写工具<br/>pkgman.jieliapp.com"] --> D["解压到 cpu/wl82/tools<br/>packres → pack_res"]
end
subgraph sg_User["开发者入口"]
E["Windows 用户<br/>Code::Blocks (.cbp)"]
F["Linux 用户<br/>make ac791n_xxx"]
end
subgraph sg_Build["编译链路"]
G["顶层 Makefile<br/>14 个 ac791n_* target"] --> H["子工程 Makefile<br/>apps/*/board/wl82"]
H --> I["杰理工具链<br/>/opt/jieli/common/bin/clang"]
I --> J["固件产物<br/>*.bin / *.fw"]
end
subgraph sg_Flash["烧录阶段"]
K["USB 升级工具 / 生产烧写工具"]
L["Linux postbuild 工具<br/>cpu/wl82/tools"]
end
B --> E
B --> F
E --> H
F --> G
J --> K
J --> L
各部分职责说明:
- 工具链准备:编译的唯一硬性依赖。工具链被约定解压到
/opt/jieli,且必须保证/opt/jieli/common/bin/clang存在(目录层次不能错),这是 README 与 Makefile 反复强调的关键点。 - 烧录工具准备:Linux 下由
init_env.sh自动下载 postbuild 工具到cpu/wl82/tools,其中pack_res是资源打包工具,用于将 UI/音视频资源打包进固件。 - 编译入口:Windows 图形化路径与 Linux 命令行路径最终汇合到各应用的板级 Makefile,保证同一份板级配置(
board_79xx_cfg.h、board_*.c)在两套体系下行为一致。 - 产出与烧录:固件编译完成后,通过 USB 升级工具(开发/测试)或生产烧写工具(量产)写入目标芯片。
环境准备详解
支持的平台与编译方式
SDK 的官方支持矩阵定义在 README.md:
| 操作系统 | 支持情况 | 推荐编译方式 |
|---|---|---|
| Windows | ✅ 完全支持 | Code::Blocks IDE(双击打开 .cbp 工程文件编译) |
| Linux | ✅ 完全支持 | Makefile 命令行编译(make ac791n_xxx) |
| macOS | ⚠️ 需自行配置交叉编译工具链 | 命令行(非官方开箱即用路径) |
设计意图:Windows 是杰理工具链与 IDE 生态的主要目标平台,Code::Blocks 工程文件(AC791N_*.cbp)由杰理 IDE 工具链维护;Linux 则面向服务器/CI 场景,通过 Makefile 实现无头构建。macOS 未被官方自动化覆盖,需要手动把工具链配置到环境变量 PATH 中。
安装编译工具链(手动方式)
根据 README.md 的官方步骤:
- 从杰理开发环境文档页下载「杰理编译工具链」;
- Linux 用户从
pkgman.jieliapp.com获取下载链接,将压缩包解压到/opt/jieli目录,并确保/opt/jieli/common/bin/clang存在; - 安装完成后验证:
# 验证工具链是否安装成功
clang --version
Source: README.md
为什么是 /opt/jieli? 顶层 Makefile 的注释明确要求「解压到 /opt/jieli 目录下,保证 /opt/jieli/common/bin/clang 存在(注意目录层次)」,子工程 Makefile 会按此绝对路径查找工具链。若目录层次错误(例如多套了一层目录),clang 将无法被找到,链接阶段也会因工具缺失而失败。
安装烧录与测试工具
| 工具 | 用途 | 获取方式 |
|---|---|---|
| USB 升级工具 | 将固件烧录到目标板(开发/测试) | 使用文档 |
| 生产烧写工具 | 量产/裸片烧写 | 使用文档 |
来源:README.md。USB 升级工具面向单板调试,生产烧写工具面向产线,二者互补:开发阶段用前者快速迭代,量产阶段用后者提高吞吐。
init_env.sh 一键初始化脚本
Linux 用户可以运行仓库根目录的 init_env.sh 自动完成工具链与烧录工具的下载、解压、目录校验与环境变量配置。脚本的执行逻辑如下:
flowchart TD
Start([运行 init_env.sh]) --> S1["下载 linux-toolchain<br/>curl pkgman.jieliapp.com/s/linux-toolchain"]
S1 --> S2{"下载成功?"}
S2 -->|"否"| E1["exit 1 提示检查网络"]
S2 -->|"是"| S3["sudo 解压到 /opt/jieli<br/>按后缀分流 tar.gz/tgz/bz2/xz/zip"]
S3 --> S4{"解压成功?"}
S4 -->|"否"| E2["exit 1 提示文件完整性"]
S4 -->|"是"| S5{"/opt/jieli/common/bin/clang 存在?"}
S5 -->|"否"| W["警告:请检查工具链完整性"]
S5 -->|"是"| S6["询问是否写入 ~/.bashrc<br/>export PATH=/opt/jieli/common/bin"]
S6 --> S7["下载 linux-postbuild<br/>curl pkgman.jieliapp.com/s/linux-postbuild"]
S7 --> S8["解压到 cpu/wl82/tools"]
S8 --> S9["扁平化 jieli-linux-post-build-tools-* 目录"]
S9 --> S10["packres 重命名为 pack_res 并 chmod +x"]
S10 --> S11["询问是否删除下载的压缩包"]
S11 --> Done([初始化完成])
脚本的设计体现了三个关键决策:
- 固定目标路径:工具链始终落到
/opt/jieli(需要sudo),与子工程 Makefile 的查找路径保持一致,避免用户自己决定路径导致后续找不到工具; - 解压格式自适应:通过
case按文件后缀分发到tar -xzf / tar -xJf / unzip等不同命令,兼容工具链发布格式的变化; - 非破坏性合并:postbuild 工具解压后若存在
jieli-linux-post-build-tools-*顶层目录,脚本会将其内容扁平化合并到cpu/wl82/tools根目录并删除原目录,确保后续构建脚本按固定路径找到工具;packres会被重命名为pack_res并赋予可执行权限。
核心下载与校验逻辑(节选自 init_env.sh):
# 设定工具链 URL
TOOLCHAIN_URL="https://pkgman.jieliapp.com/s/linux-toolchain"
# 下载工具链到当前目录
echo "开始下载工具链文件..."
curl -o toolchain.tar.xz -L "$TOOLCHAIN_URL"
if [ $? -ne 0 ]; then
echo "下载失败,请检查 URL 或网络连接。"
exit 1
fi
# 确保目标目录存在
TARGET_DIR="/opt/jieli"
sudo mkdir -p "$TARGET_DIR"
# 根据文件后缀解压
FILE="toolchain.tar.xz"
case "$FILE" in
*.tar.gz)
sudo tar -xzf "$FILE" -C "$TARGET_DIR" ;;
*.tar.xz)
sudo tar -xJf "$FILE" -C "$TARGET_DIR" ;;
*.zip)
sudo unzip "$FILE" -d "$TARGET_DIR" ;;
*)
echo "不支持的文件格式:$FILE"
exit 1 ;;
esac
# 检查关键文件是否存在
if [ -f "$TARGET_DIR/common/bin/clang" ]; then
echo "clang 位置确认:$TARGET_DIR/common/bin/clang"
else
echo "警告:未找到 clang 文件,请检查工具链完整性。"
fi
Source: init_env.sh
脚本对每一步都做了显式失败检查(exit 1)并输出可操作的中文提示,这是为了在无人值守场景下也能快速定位是网络问题、压缩包损坏还是工具链版本不完整。clang 文件校验是唯一的硬性门禁——即使解压成功,若 clang 缺失也只会给出警告,因为脚本无法替代用户重新下载正确版本。
编译流程与 Makefile 机制
顶层 Makefile:多工程统一入口
SDK 根目录的 Makefile 是命令行编译的总入口。其设计模式是转发式 Makefile:顶层只负责定义目标名(target),实际编译动作全部委托给各应用工程板级目录下的子 Makefile。
# 总的 Makefile,用于调用目录下各个子工程对应的 Makefile
# 注意: Linux 下编译方式:
# 1. 从 http://pkgman.jieliapp.com/doc/all 处找到下载链接
# 2. 下载后,解压到 /opt/jieli 目录下,保证
# /opt/jieli/common/bin/clang 存在(注意目录层次)
# 3. 确认 ulimit -n 的结果足够大(建议大于8096),否则链接可能会因为打开文件太多而失败
# 可以通过 ulimit -n 8096 来设置一个较大的值
# 支持的目标
# make ac791n_wifi_camera
# make ac791n_scan_box
# make ac791n_wifi_ipc
# make ac791n_wifi_story_machine
# make ac791n_demo_demo_ble
# ...
Source: Makefile
每个 target 与子工程的对应关系如下(节选 Makefile):
ac791n_wifi_camera:
$(MAKE) -C apps/wifi_camera/board/wl82 -f Makefile
clean_ac791n_wifi_camera:
$(MAKE) -C apps/wifi_camera/board/wl82 -f Makefile clean
ac791n_scan_box:
$(MAKE) -C apps/scan_box/board/wl82 -f Makefile
clean_ac791n_scan_box:
$(MAKE) -C apps/scan_box/board/wl82 -f Makefile clean
ac791n_wifi_ipc:
$(MAKE) -C apps/wifi_ipc/board/wl82 -f Makefile
ac791n_wifi_story_machine:
$(MAKE) -C apps/wifi_story_machine/board/wl82 -f Makefile
Source: Makefile
设计意图:$(MAKE) -C <dir> -f Makefile 将当前工作目录切换到对应板级目录并调用其 Makefile,同时把顶层传入的变量(如 MAKEFLAGS)透传给子进程。每个 target 都配套一个 clean_<target>,用于单独清理该工程的编译产物;all 目标则串行编译全部 14 个工程,clean 全部清理。这种拆分让 CI 可以按需选择单个工程构建,而不必每次全量编译。
编译流程图
sequenceDiagram
participant Dev as 开发者
participant Top as 顶层 Makefile
participant Sub as 子工程 Makefile (apps/*/board/wl82)
participant TC as 杰理工具链 (/opt/jieli/common/bin/clang)
participant Out as 固件产物
Dev->>Top: make ac791n_wifi_camera
activate Top
Top->>Top: 校验 ulimit -n ≥ 8096 (注释提示)
Top->>Sub: $(MAKE) -C apps/wifi_camera/board/wl82
deactivate Top
activate Sub
Sub->>Sub: 读取 board_79xx_cfg.h 板级配置
Sub->>TC: 调用 clang 交叉编译源码
activate TC
TC-->>Sub: 目标文件 .o
deactivate TC
Sub->>TC: 调用链接器链接固件
activate TC
TC-->>Sub: 固件镜像
deactivate TC
Sub->>Sub: 调用 pack_res 打包资源
Sub-->>Out: 生成可烧录固件
deactivate Sub
Dev->>Out: USB 升级工具烧录到目标板
编译链路的关键约束:
- 工具链路径:子工程 Makefile 按
/opt/jieli绝对路径查找clang,因此工具链安装位置是硬约定,不能随意更改; - 文件描述符上限:顶层 Makefile 明确提示
ulimit -n需大于 8096,否则链接阶段会因打开文件过多而失败——嵌入式工程的中间目标文件数量庞大,这是实际踩坑后的经验总结; - 板级配置参与编译:子工程 Makefile 会包含
board_79xx_cfg.h(引脚、外设配置)与board_*.c(板级初始化代码),同一份代码可通过切换板级目录适配不同芯片型号(如board_7916A_cfg.h)。
快速开始(命令行)
完整流程见 README.md:
# 1. 克隆仓库
git clone https://gitee.com/Jieli-Tech/fw-AC79_AIoT_SDK.git
cd fw-AC79_AIoT_SDK
# 2. (Linux)一键初始化工具链与烧录工具
./init_env.sh
# 3. 编译指定工程(以 WiFi 摄像头为例)
make ac791n_wifi_camera
# 4. 清理单个工程产物
make clean_ac791n_wifi_camera
Windows 用户则按 README.md 的说明操作:
# 1. 进入对应的板级目录
cd apps/wifi_camera/board/wl82/
# 2. 双击打开 .cbp 工程文件(如 AC791N_WIFI_CAMERA.cbp)
# 3. 在 Code::Blocks 中点击 Build → Build (Ctrl+F9)
# 4. 编译成功后,使用 USB 升级工具烧录生成的固件文件
提示:所有支持的 target 名称见 Makefile 开头的注释;Windows 命令行用户可双击
tools/make_prompt.bat打开预配置的命令行环境。
工程与板级目录结构
编译目标与目录结构一一对应(来源:README.md):
SDK 根目录
├── apps/wifi_camera/ # WiFi 摄像头方案
├── apps/wifi_ipc/ # WiFi IPC 网络摄像机方案
├── apps/wifi_story_machine/ # WiFi 故事机方案
├── apps/scan_box/ # 扫码盒方案
└── apps/demo/ # 11 个功能 demo(ble/wifi/edr/ui/uvc/video/audio…)
每个应用目录下的 board/wl82/ 子目录包含:
Makefile—— 编译脚本(顶层 Makefile 的-C转发目标);AC791N_*.cbp—— Code::Blocks 工程文件;board_79xx_cfg.h—— 板级配置(引脚、外设等,按芯片型号区分,如board_7916A_cfg.h);board_*.c—— 板级初始化代码。
设计意图:SDK 将「应用逻辑」与「板级适配」分离——apps/<app>/ 存放应用代码,board/<board>/ 存放硬件相关配置。新做一款板子只需复制 board/wl82/ 并修改板级头文件,应用代码无需改动;这也是为什么 Makefile 的转发目标以「芯片(ac791n)+ 应用」命名。
Configuration Options
环境搭建涉及的配置项汇总如下:
| 配置项 | 类型 | 默认值/约定位置 | 说明 |
|---|---|---|---|
| 工具链安装目录 | 路径 | /opt/jieli | 杰理编译工具链的固定解压位置(sudo 权限) |
| 交叉编译器 | 路径 | /opt/jieli/common/bin/clang | 构建系统查找编译器的硬性校验点,目录层次不能错 |
PATH 环境变量 | 字符串 | 追加 /opt/jieli/common/bin 到 ~/.bashrc(可选) | 使 clang --version 可直接在终端执行 |
ulimit -n | 整数 | 建议 > 8096 | 文件描述符上限,过小会导致链接阶段 Too many open files |
| 烧录工具目录 | 路径 | cpu/wl82/tools | init_env.sh 下载 postbuild 工具的目标目录 |
| 资源打包工具 | 路径 | cpu/wl82/tools/pack_res | 由 packres 重命名而来,需具有可执行权限 |
| 下载源 URL | URL | https://pkgman.jieliapp.com/s/linux-toolchain、/s/linux-postbuild | init_env.sh 内置的工具链/烧写工具下载地址 |
| 编译目标 | Make 参数 | ac791n_wifi_camera 等 14 个 | 顶层 Makefile 支持的目标,见下文 API 参考 |
API Reference
Makefile 编译目标(Targets)
顶层 Makefile 提供以下 make 目标(定义于 Makefile,支持目标列表见 Makefile#L8-L22):
| Target | 转发的子工程目录 | 说明 |
|---|---|---|
make all | 全部 14 个工程 | 串行编译所有应用(输出 +ALL DONE) |
make clean | 全部 14 个工程 | 清理所有编译产物(输出 +CLEAN DONE) |
make ac791n_wifi_camera | apps/wifi_camera/board/wl82 | 编译 WiFi 摄像头方案 |
make ac791n_scan_box | apps/scan_box/board/wl82 | 编译扫码盒方案 |
make ac791n_wifi_ipc | apps/wifi_ipc/board/wl82 | 编译 WiFi IPC 网络摄像机方案 |
make ac791n_wifi_story_machine | apps/wifi_story_machine/board/wl82 | 编译 WiFi 故事机方案 |
make ac791n_demo_demo_ble | apps/demo/demo_ble/board/wl82 | 编译 BLE 功能 demo |
make ac791n_demo_demo_wifi_ext | apps/demo/demo_wifi_ext/board/wl82 | 编译 WiFi 扩展 demo |
make ac791n_demo_demo_edr | apps/demo/demo_edr/board/wl82 | 编译 EDR 蓝牙 demo |
make ac791n_demo_demo_ui | apps/demo/demo_ui/board/wl82 | 编译 UI demo |
make ac791n_demo_demo_hello | apps/demo/demo_hello/board/wl82 | 编译 hello world demo |
make ac791n_demo_demo_devkitboard | apps/demo/demo_devkitboard/board/wl82 | 编译开发板 demo |
make ac791n_demo_demo_uvc | apps/demo/demo_uvc/board/wl82 | 编译 UVC 摄像头 demo |
make ac791n_demo_demo_video | apps/demo/demo_video/board/wl82 | 编译视频 demo |
make ac791n_demo_demo_audio | apps/demo/demo_audio/board/wl82 | 编译音频 demo |
make ac791n_demo_demo_wifi | apps/demo/demo_wifi/board/wl82 | 编译 WiFi demo |
make clean_<target> | 对应工程 | 清理单个工程产物(如 make clean_ac791n_wifi_camera) |
参数与返回值约定:
- 每个 target 不接受额外参数;通过
-C <dir> -f Makefile将编译动作委托给子工程; - 成功时输出
+ALL DONE(all目标)或由子 Makefile 输出构建日志;失败时 Make 进程以非零退出码终止; clean系列目标输出+CLEAN DONE。
init_env.sh 交互式选项
脚本运行过程中的交互提示(init_env.sh):
| 提示 | 输入 | 行为 |
|---|---|---|
是否将工具链路径添加到环境变量?(y/n) | y | 追加 export PATH=/opt/jieli/common/bin:$PATH 到 ~/.bashrc 并 source |
是否删除下载的工具链文件?(y/n) | y | sudo rm -f toolchain.tar.xz |
是否删除下载的烧写工具文件?(y/n) | y | rm -f postbuild.tar.xz |
退出码约定: 工具链下载失败、解压失败、postbuild 下载失败、解压失败、不支持的压缩格式均以 exit 1 终止;成功路径最终打印 初始化完成!。
Failure Modes, Edge Cases & Concurrency
常见故障与排查
| 故障现象 | 根因 | 解决方式 |
|---|---|---|
clang: command not found | 工具链未安装,或 PATH 环境变量未配置 | 重新执行 init_env.sh,或将 /opt/jieli/common/bin 加入 PATH(见 README-en.md 的故障表) |
Too many open files(Linux) | ulimit -n 过小,链接阶段打开文件过多 | 执行 ulimit -n 8096 提高文件描述符上限(Makefile 注释明确提示) |
| 工具链下载失败 | 网络不通或 URL 变更 | init_env.sh 以 exit 1 退出并提示检查 URL/网络;可从 pkgman.jieliapp.com/doc/all 重新获取链接 |
| 解压失败 | 压缩包损坏或不支持的格式 | 脚本按后缀分流(tar.gz/tgz/bz2/xz/zip),其余格式提示「不支持的文件格式」并退出 |
找不到 clang 但解压成功 | 工具链目录层次错误 | 校验 /opt/jieli/common/bin/clang 是否存在,确保不是多套了一层目录 |
| 烧写工具缺失 | postbuild 未下载或目录结构变化 | 检查 cpu/wl82/tools/pack_res;脚本会扁平化 jieli-linux-post-build-tools-* 顶层目录并重命名 packres |
边界情况与并发注意
- 脚本幂等性:
init_env.sh重复执行会重新下载并覆盖解压,pack_res已存在时会先rm -rf再重命名,保证结果一致,但会重复消耗带宽,建议一次成功。 - sudo 权限:解压到
/opt/jieli与写入~/.bashrc需要sudo;在无交互的 CI 环境中,read等待用户输入可能导致脚本挂起,需要预置输入或改造脚本。 - 并行编译:顶层
all目标为串行$(MAKE) -C转发,各工程间无共享中间产物,理论上可并行,但官方未提供-j级别的并行编排;多个工程同时make会竞争工具链与输出目录,不建议。 - 环境变量持久性:
source ~/.bashrc只对当前 shell 生效,新开的终端若不重新登录/source,clang可能仍然不可见——这是「已验证成功但新终端报 command not found」的常见来源。
Performance & Operational Considerations
- 文件描述符是链接期的硬指标:AC79 固件的中间目标文件数量庞大,链接器一次性打开大量文件,
ulimit -n必须大于 8096,否则稳定复现Too many open files。建议在 CI 脚本中显式执行ulimit -n 8096。 - 增量构建:顶层
clean_<target>与子工程 Makefile 的clean配合,可对单个工程做清理后重建,避免全量清理影响其他工程产物。 - 工具链下载体积:工具链与 postbuild 包体积较大,脚本下载到当前目录再解压,磁盘需预留足够空间;脚本末尾提供删除压缩包的选项以回收空间。
- macOS 支持缺口:macOS 需要手动配置交叉编译工具链,官方脚本
init_env.sh面向 Linux(使用sudo、bash与curl),macOS 用户需手动完成等价操作。
Extension Points
- 新增应用工程:在
apps/下新建目录并创建board/wl82/(含 Makefile、.cbp、板级头文件),然后在顶层 Makefile 中仿照现有 target 增加$(MAKE) -C转发规则,即可纳入make all体系。 - 新增板级:复制现有
board/wl82/目录,修改board_79xx_cfg.h(按芯片型号如board_7916A_cfg.h)与board_*.c,应用代码无需改动。 - 自动化初始化:
init_env.sh的下载 URL(TOOLCHAIN_URL、POSTBUILD_URL)为变量形式,可依据内部镜像环境修改后复用;其「下载→校验→解压→扁平化→命名」的流水线也可作为其他工具链初始化的模板。
Related Links
- Makefile(顶层编译入口)
- init_env.sh(环境初始化脚本)
- README.md(SDK 总览与环境搭建章节)
- README-en.md(英文版,含故障排查表)
- 相关兄弟页面:SDK 总览与特性(见「SDK 概述」)、应用工程说明(见「应用工程」)、固件升级机制(见「固件升级」)