SDK 辅助工具与脚本
fw-AC79_AIoT_SDK 的 tools/ 目录为开发者提供了一组 Windows 平台下的构建辅助工具与批处理脚本,包括预配置的命令行环境脚本 make_prompt.bat、静态库合并脚本 do_merge_libs.bat 以及一组 GNU 兼容命令行工具(make.exe、merge-archives.exe、find.exe 等),用于支撑基于 Makefile 的 SDK 编译流程。
Purpose and Scope
本文档介绍 SDK 中 tools/ 目录下辅助工具与脚本的用途、实现细节、调用方式及其与构建系统的关系,具体包括:
tools/make_prompt.bat—— Windows 下预配置的构建命令行环境入口;tools/utils/工具集 —— 随 SDK 分发的 GNU 兼容命令行工具(make.exe、merge-archives.exe、find.exe、ls.exe、rm.exe、uname.exe等);tools/utils/do_merge_libs.bat—— 静态库(.a归档)合并辅助脚本;- 这些工具如何与顶层
Makefile(SDK 统一编译入口)协同工作。
本文档不覆盖以下主题,它们属于兄弟页面:
- SDK 的完整编译目标、模块划分与 Makefile 规则本身(参见「构建系统」相关页面);
- 固件烧录、调试器连接等硬件工具链(参见「烧录与调试工具」相关页面);
- 在线文档(
docs/目录的 RST 源文件)的编写规范。
Overview
AC79 系列 AIoT SDK 采用 Makefile 驱动的命令行构建方式。在 Windows 环境下,系统自带的 cmd 并不包含 make、find、rm 等 GNU 工具,直接输入 make 会报「不是有效命令」的错误(README.md 常见问题)。
为解决这一问题,SDK 在 tools/ 目录中随包分发了一组免安装的 GNU 工具,并提供了一个一键进入构建环境的脚本 make_prompt.bat:开发者双击该脚本后,脚本会自动把 tools/utils 目录前置到 PATH 环境变量,并切换到仓库根目录,随后打开一个已就绪的 cmd 控制台,开发者即可直接执行 make 等命令。
tools/utils 中的 merge-archives.exe 与 do_merge_libs.bat 则服务于构建过程中的静态库归档合并环节:当多个子模块编译出各自的 .a 文件后,通过该脚本将指定目录下的所有 .a 归档合并为一个输出库文件,供链接阶段使用。
Architecture
下图展示了 tools/ 目录中各组件的职责划分及其与构建流程的关系:
flowchart TD
subgraph sg_tools["tools/ 目录(SDK 辅助工具)"]
make_prompt["make_prompt.bat<br/>构建命令行环境入口"]
subgraph sg_utils["utils/ 工具集(GNU 兼容命令)"]
make_exe["make.exe"]
merge_exe["merge-archives.exe"]
do_merge["do_merge_libs.bat<br/>静态库合并脚本"]
find_exe["find.exe / ls.exe / rm.exe<br/>等基础命令"]
other_utils["mkdir_win.exe / override-seg.exe<br/>等 SDK 专用工具"]
end
end
Dev["Windows 开发者"] -->|"双击运行"| make_prompt
make_prompt -->|"将 utils 前置到 PATH"| sg_utils
make_prompt -->|"cd 到仓库根目录"| Makefile["Makefile<br/>顶层统一编译入口"]
Makefile -->|"编译子模块产出"| libs_a["各模块 .a 静态库"]
libs_a -->|"调用脚本合并"| do_merge
do_merge -->|"遍历目录下 *.a"| merge_exe
merge_exe -->|"--no-rewrite 合并归档"| libs_out["合并后的 .a 库<br/>供链接使用"]
Dev -->|"在控制台输入 make 等命令"| make_exe
各组件职责说明:
| 组件 | 职责 | 关键点 |
|---|---|---|
make_prompt.bat | 一键打开预配置的构建控制台 | 修改 PATH、切换工作目录、启动 cmd |
make.exe | GNU make 的 Windows 移植版 | 支撑顶层 Makefile 的执行 |
merge-archives.exe | 静态库归档合并器 | 支持 --no-rewrite、--output 参数 |
do_merge_libs.bat | 批量合并指定目录下的 .a 文件 | 遍历、拼接文件列表、调用合并器 |
find.exe / ls.exe / rm.exe 等 | GNU 基础命令的 Windows 版 | 供 Makefile 规则及脚本调用 |
override-seg.exe / mkdir_win.exe | SDK 专用辅助工具 | 段覆盖、Windows 下建目录等特殊需求 |
设计意图:将工具链随 SDK 一起分发(而不是要求开发者自行安装 MSYS2 / Cygwin),可以保证所有开发者的构建环境一致,避免因工具链版本差异导致的构建结果不一致;同时用 make_prompt.bat 把环境配置封装成「双击即可用」,降低了 Windows 开发者的上手门槛。
目录结构与工具清单
tools/ 目录的完整内容如下(由仓库文件列表确认):
tools/
├── make_prompt.bat # 构建命令行环境入口脚本
└── utils/ # 随 SDK 分发的 Windows 工具集
├── do_merge_libs.bat # 静态库合并辅助脚本
├── merge-archives.exe # 归档合并工具(合并 .a 库)
├── make.exe # GNU make(Windows 版)
├── find.exe # GNU find(Windows 版)
├── ls.exe # GNU ls(Windows 版)
├── rm.exe # GNU rm(Windows 版)
├── uname.exe # GNU uname(Windows 版)
├── true.exe # GNU true(Windows 版)
├── fixbat.exe # 批处理修复工具
├── override-seg.exe # 段(segment)覆盖工具
├── mkdir_win.exe # Windows 建目录工具
├── libiconv2.dll # 字符编码转换运行库(iconv)
└── libintl3.dll # 国际化(gettext)运行库
其中 libiconv2.dll 与 libintl3.dll 是 GNU 工具在 Windows 上运行所依赖的动态链接库,它们与 *.exe 位于同一目录,保证工具可被直接执行而不需要额外安装运行环境。
README 中对 tools/ 的定位是「编译工具(make_prompt.bat + utils)」,并紧邻顶层 Makefile(「顶层统一编译入口」)列出(README.md 目录树),说明该目录是 Windows 构建链路中不可或缺的一部分。
make_prompt.bat:构建命令行环境入口
源码与逐行解读
make_prompt.bat 的实现非常精简,只有 5 行:
SET SCRIPT_PATH=%~dp0%
set PATH=%SCRIPT_PATH%\\utils;%PATH%
cd ..
cmd
| 行 | 作用 | 设计意图 |
|---|---|---|
SET SCRIPT_PATH=%~dp0% | 把脚本自身所在目录(含末尾反斜杠)存入 SCRIPT_PATH | %~dp0 是批处理中获取「脚本所在目录」的标准写法,无论脚本从哪个工作目录被调用都能正确定位 |
set PATH=%SCRIPT_PATH%\\utils;%PATH% | 将 tools/utils 前置到 PATH 环境变量 | 前置而非追加,确保 make、find 等命令优先命中 SDK 自带的 GNU 工具,而不是系统中可能存在的其他同名程序 |
cd .. | 从 tools/ 切换到上一级目录(即仓库根目录) | SDK 的顶层 Makefile 位于仓库根目录,开发者进入控制台后即可直接执行 make |
cmd | 启动一个新的交互式命令行窗口 | 保持控制台打开,供开发者持续输入构建命令 |
典型使用方式
README 在快速上手部分明确给出了 Windows 下的入口(README.md):
# Windows 用户:双击 tools/make_prompt.bat 打开命令行环境
# Windows 用户:双击 tools/make_prompt.bat 打开命令行环境
来源:README.md
make_prompt.bat 解决的问题在 README 的 FAQ 中被明确记录(README.md):
Q: Windows 下编译报错
make不是有效命令? A: 使用tools/make_prompt.bat进入预配置的命令行环境,该脚本已设置好make路径和环境变量。
核心流程:从双击脚本到开始编译
sequenceDiagram
participant Dev as Windows 开发者
participant BAT as make_prompt.bat
participant UTIL as tools/utils 目录
participant CON as cmd 控制台
participant MK as make.exe
Dev->>BAT: 双击运行脚本
BAT->>BAT: 记录 SCRIPT_PATH(脚本所在目录)
BAT->>BAT: PATH = SCRIPT_PATH\utils + 原 PATH
BAT->>BAT: cd .. 进入仓库根目录
BAT->>CON: 启动交互式 cmd
Dev->>CON: 输入 make 目标命令
CON->>MK: 从 PATH 定位并执行 make.exe
MK-->>CON: 读取 Makefile 开始编译
CON-->>Dev: 输出编译日志
do_merge_libs.bat:静态库合并脚本
源码与逐行解读
do_merge_libs.bat 用于把指定目录下的所有 .a 静态库归档合并成一个输出库:
@echo off
setlocal enabledelayedexpansion
set INDIR=%1%
set MERGE=%2%
set AROUT=%3%
echo %INDIR%
echo %MERGE%
echo %AROUT%
set FILES=
for /f "tokens=*" %%i in ('dir /b %INDIR%\*.a') DO SET FILES=!FILES! %INDIR%\%%i
echo %FILES%
%MERGE% --no-rewrite --output %AROUT% %FILES%
参数约定:
| 参数 | 位置 | 含义 |
|---|---|---|
%1(INDIR) | 第 1 个 | 存放待合并 .a 文件的输入目录 |
%2(MERGE) | 第 2 个 | merge-archives.exe 的路径(或其所在路径) |
%3(AROUT) | 第 3 个 | 合并后输出库文件的路径 |
关键实现细节:
setlocal enabledelayedexpansion:启用延迟变量展开。这是本脚本正确工作的核心——在for循环体内用!FILES!而非%FILES%访问变量,%FILES%会在循环开始前被一次性展开,无法累积拼接;!FILES!则在每次迭代时实时读取最新值,从而把循环中逐个找到的.a文件累积成一个空格分隔的文件列表。dir /b %INDIR%\*.a:以简洁格式列出输入目录下所有.a归档文件;for /f "tokens=*"逐行读取该输出,tokens=*保证整行(含路径中的空格)被完整捕获。%MERGE% --no-rewrite --output %AROUT% %FILES%:调用合并器。--no-rewrite表示合并时不重写归档内容(保留各成员原始状态,避免不必要的重压缩/重写,加快合并速度),--output指定输出文件,其后为全部输入归档路径。
合并流程示意
flowchart TD
Start(["do_merge_libs.bat INDIR MERGE AROUT"]) --> S1["setlocal enabledelayedexpansion<br/>启用延迟变量展开"]
S1 --> S2["解析三个参数<br/>INDIR / MERGE / AROUT"]
S2 --> S3["dir /b INDIR\\*.a<br/>列出所有待合并归档"]
S3 --> S4{"找到 .a 文件?"}
S4 -->|"否"| E1["FILES 为空<br/>merge-archives 无输入"]
S4 -->|"是"| S5["for 循环累积<br/>FILES = 文件1 文件2 ..."]
S5 --> S6["merge-archives.exe<br/>--no-rewrite --output AROUT FILES"]
S6 --> End(["输出合并后的静态库"])
设计意图
- 为什么用批处理而不是在 Makefile 里内联循环? 将「遍历目录、拼接文件列表」这类纯 Windows 相关的逻辑独立成脚本,使 Makefile 规则保持简洁、可读,且脚本可以被不同 Makefile 目标复用。
- 为什么需要合并静态库? AC79 这类多模块 SDK 中,各子模块(协议栈、编解码、外设驱动等)可能独立编译为
.a;链接阶段若逐个指定会非常冗长,合并为一个库后,链接器只需引用单一归档,简化了链接参数管理,也便于把合并后的库分发给下游(如二次开发客户)使用。 --no-rewrite的性能考量:合并大批量归档时,重写成员会引入大量磁盘 I/O 与压缩开销;--no-rewrite直接拼接成员表,显著缩短构建时间。
utils/ 工具集详解
GNU 基础命令工具
tools/utils 提供了多款 GNU 命令的 Windows 移植版本,使 Makefile 中的常见规则(find、ls、rm、mkdir 等)可以在不安装额外软件的情况下直接运行:
| 工具 | 在构建中的作用(典型场景) |
|---|---|
make.exe | 执行顶层 Makefile 的核心引擎;make_prompt.bat 保证其可被直接调用 |
find.exe | 在 Makefile 规则中遍历源文件、收集依赖清单(如 $(shell find ...)) |
ls.exe | 目录列表,常用于调试脚本或生成文件清单 |
rm.exe | 清理构建产物(make clean 等目标的核心命令) |
uname.exe | 探测主机类型,供构建脚本做平台分支判断 |
true.exe | 返回成功退出码,常用于 Makefile 中占位/空操作目标 |
mkdir_win.exe | 在 Windows 上创建目录的辅助工具(弥补原生 mkdir 在复杂路径下的行为差异) |
fixbat.exe | 批处理文件修复工具,用于处理脚本兼容性问题 |
这些工具依赖同目录下的 libiconv2.dll(字符集转换)与 libintl3.dll(消息国际化)运行库,因此不能单独拷贝某个 exe 到其他目录运行,必须保持 utils 目录的完整性——这也是 make_prompt.bat 把整个 utils 目录加入 PATH 的原因之一。
merge-archives.exe
merge-archives.exe 是 SDK 构建链中的专用工具,功能为合并 GNU ar 格式的静态库归档。从 do_merge_libs.bat 的调用方式可以确认其命令行接口:
merge-archives.exe --no-rewrite --output <输出库文件> <输入库1.a> <输入库2.a> ...
--no-rewrite:合并时保留各成员归档的原始内容,不执行重写(提升性能);--output <文件>:指定合并结果的输出路径;- 位置参数:一个或多个待合并的
.a归档文件。
override-seg.exe
override-seg.exe 用于段(segment)覆盖操作,属于链接/布局阶段的高级辅助工具。在 AC79 系列芯片的固件构建中,通常需要通过段覆盖机制调整代码/数据在 Flash 或 RAM 中的放置位置(如将热更新模块覆盖到固定地址区间),该工具即为这类定制化布局需求提供命令行支持。
Usage Examples
示例 1:进入构建环境并执行 make
# 1. 双击 tools/make_prompt.bat(或在命令行中执行)
# 2. 脚本自动进入仓库根目录,PATH 已包含 tools/utils
# 3. 直接执行构建命令
make
来源:README.md(用法入口)与 tools/make_prompt.bat(环境配置实现)
示例 2:手动调用静态库合并脚本
rem 语法: do_merge_libs.bat <输入目录> <merge-archives 路径> <输出库>
do_merge_libs.bat build\obj\sub build\tools\utils\merge-archives.exe build\lib\liball.a
脚本内部等价执行:
merge-archives.exe --no-rewrite --output build\lib\liball.a build\obj\sub\liba.a build\obj\sub\libb.a ...
示例 3:FAQ 中给出的排障路径
Q: Windows 下编译报错 `make` 不是有效命令?
A: 使用 tools/make_prompt.bat 进入预配置的命令行环境,
该脚本已设置好 make 路径和环境变量。
来源:README.md
Configuration Options
这些工具通过环境变量与命令行参数进行配置,没有独立的配置文件:
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
PATH(由 make_prompt.bat 修改) | 环境变量 | 追加 tools/utils 前缀 | 使 make、find 等命令可被直接调用;utils 位于最前以保证优先级 |
SCRIPT_PATH(脚本内部变量) | 批处理变量 | %~dp0(脚本所在目录) | make_prompt.bat 定位 utils 目录的依据 |
INDIR(do_merge_libs.bat 参数 1) | 命令行参数 | 无(必填) | 待合并 .a 文件所在目录 |
MERGE(do_merge_libs.bat 参数 2) | 命令行参数 | 无(必填) | merge-archives.exe 路径 |
AROUT(do_merge_libs.bat 参数 3) | 命令行参数 | 无(必填) | 合并输出库路径 |
--no-rewrite(merge-archives 选项) | 命令行开关 | 由脚本固定传入 | 不重写归档成员,提升合并性能 |
--output(merge-archives 选项) | 命令行参数 | 由脚本传入 | 指定输出归档文件 |
工作目录约定:make_prompt.bat 会执行 cd .. 使控制台位于仓库根目录,因此后续 make 命令默认读取根目录下的顶层 Makefile。
失败模式与边界情况
1. make 不是有效命令(环境未初始化)
在普通 cmd 窗口(而非通过 make_prompt.bat 打开的窗口)中直接执行 make,会因 PATH 中不存在 make.exe 而失败。这是 README FAQ 中明确记录的最常见问题,官方解决路径就是使用 make_prompt.bat(README.md)。
建议:始终通过 make_prompt.bat 进入构建环境;若需在 CI 或自定义脚本中调用,应手动将 tools/utils 加入 PATH。
2. 输入目录中没有 .a 文件
do_merge_libs.bat 中若 dir /b %INDIR%\*.a 无结果,FILES 变量保持为空,最终执行的命令变为:
merge-archives.exe --no-rewrite --output <AROUT>
即合并器在没有任何输入归档的情况下运行,输出为空库或直接报错。脚本本身没有做参数与文件存在性校验(仅打印回显),因此调用方需要保证 INDIR 路径正确且包含待合并的归档。
3. 路径含空格
for /f "tokens=*" 配合 !FILES! 的拼接方式对路径中的空格较为敏感:文件名中的空格会被当作列表分隔符。若 SDK 被克隆到含空格的目录(如 C:\Program Files\...),%~dp0 与 INDIR 都可能引入空格,导致合并参数被错误切分。
建议:将 SDK 放置在无空格的路径下(如 C:\jieli\fw-AC79_AIoT_SDK),这是嵌入式 Windows 构建环境的通用最佳实践。
4. DLL 依赖缺失
utils 中的 GNU 工具依赖 libiconv2.dll 与 libintl3.dll。若只拷贝单个 exe(如 make.exe)到其他目录使用,程序会因找不到 DLL 而启动失败。保持 utils 目录完整,并整体加入 PATH。
5. 延迟变量展开的陷阱(并发/嵌套场景)
setlocal enabledelayedexpansion 只在当前脚本进程内生效。若在嵌套调用中依赖 !FILES! 展开,需注意每个脚本都要独立启用延迟展开;同时,若目录中文件名包含 ! 字符,延迟展开会把 ! 当作变量边界符导致文件名被截断——这属于已知的批处理语言固有限制,实践中通过命名规范(文件名不使用 !)规避。
性能与运维注意事项
- 合并性能:
--no-rewrite跳过归档成员重写,避免大量磁盘 I/O,适合频繁全量合并的场景;若需要压缩或规范化归档,应去掉该选项(由构建需求决定)。 - 构建环境一致性:工具随 SDK 分发并整体入
PATH,消除了「开发者本机 GNU 工具版本不一致」导致的构建漂移问题;升级 SDK 时,tools/目录应随仓库整体更新,避免新旧工具混用。 - 并发构建:
make.exe支持-j并行编译;但do_merge_libs.bat的合并属于链接前聚合阶段,应在所有子模块归档生成完毕后再执行,多个合并任务并发写同一输出文件会产生竞态,需由 Makefile 依赖关系保证串行。 - Windows 专用性:
make_prompt.bat与do_merge_libs.bat均为 Windows 批处理;Linux/macOS 开发者直接使用系统 GNU 工具链即可,无需这些脚本。
扩展点
- 新增自定义构建工具:可将新的 Windows 辅助 exe 放入
tools/utils/,并确保其依赖的 DLL 一并放置,即可被make_prompt.bat建立的PATH直接访问。 - 复用合并脚本:
do_merge_libs.bat的参数化设计(输入目录、合并器、输出库)使其可被任意 Makefile 目标调用,只需保证三个参数按约定传入。 - 环境定制:
make_prompt.bat中cd ..假设脚本位于tools/子目录;若调整目录结构,需同步修改该行(例如cd /d %SCRIPT_PATH%..的等价写法)。
测试情况说明
仓库中未发现针对 tools/ 批处理脚本的自动化测试文件。这些脚本的「测试」主要体现在:
- README 快速上手流程中「双击
make_prompt.bat→ 执行make」的端到端验证(README.md); - FAQ 中记录的
make命令失败排障路径(README.md); - 实际 SDK 构建流程中对
do_merge_libs.bat+merge-archives.exe组合的反复调用(由 Makefile 驱动)。
Related Links
- README.md(快速上手与 FAQ)
- tools/make_prompt.bat(构建命令行环境脚本)
- tools/utils/do_merge_libs.bat(静态库合并脚本)
- tools/utils/ 工具集目录
- 构建系统与 Makefile 规则:参见「构建系统」相关页面
- 固件烧录与调试工具:参见「烧录与调试工具」相关页面
- 在线文档源(RST):参见
docs/目录说明