杰理 SDK 文档中心
首页
首页
  • SDK 概述与入门

    • SDK 总览
    • 支持芯片与蓝牙认证
    • 工程结构导航
  • 开发环境与构建

    • 环境搭建与工具链安装
    • 编译指南与工程选择
    • 烧录与生产工具
  • BLE 透传/数传应用

    • 透传应用框架与处理模块
    • 透传与数传示例
    • 多连接与自定义服务示例
    • FindMy 与查找网络示例
  • HID 人机交互应用

    • 键盘与按键设备示例
    • 鼠标设备示例
    • 遥控器示例
    • HID 蓝牙应用模块
  • 公共 BSP 模块

    • 按键、编码器与红外输入
    • 传感器驱动
    • LED 与显示控制
    • 串口与 USB 通信
    • 存储、参数与时钟
    • 电源与温度管理
    • 消息、内存与系统配置
    • OTA 升级框架
  • 蓝牙协议栈与库

    • BLE 控制器与协议栈适配
    • 经典蓝牙 BR/EDR 支持
    • 第三方蓝牙协议
    • 设备管理框架
    • DUT 测试与射频认证
  • 构建系统与开发工具

    • Makefile 构建系统
    • 固件后处理与配置工具
    • 辅助脚本与库合并
  • 文档与硬件资料

    • AT 命令参考
    • 硬件参考资料
    • SDK 文档与在线资源

辅助脚本与库合并

本页介绍 fw-AW33N_BLE_SDK 仓库中 tools/ 目录下的辅助脚本体系:开发环境引导脚本 make_prompt.bat、静态库合并脚本 do_merge_libs.bat,以及随附的 Windows 工具集(make.exe、find.exe、merge-archives.exe 等)。这些脚本共同支撑了 SDK 在 Windows 环境下以 GNU Make 驱动的构建流程,以及将多个 .a 静态库归档合并为单一库的链接前处理环节。

Purpose and Scope

本页覆盖以下内容:

  • tools/make_prompt.bat:一键进入带工具链 PATH 的 cmd 开发环境;
  • tools/utils/do_merge_libs.bat:把指定目录下的全部 .a 归档合并为一个输出归档;
  • tools/utils/ 工具集:为 Windows 提供类 Unix 命令行工具,其中 merge-archives.exe 是库合并的实际执行者;
  • 库合并机制与 --no-rewrite 参数的设计意图。

本页不覆盖 SDK 的芯片驱动、BLE 协议栈实现、Makefile 的具体构建规则与链接脚本(linker script)等内容,这些属于其他目录页的主题。本页聚焦于"脚本工具本身如何工作、为何这样设计"。

Overview

背景与动机

AW33N BLE SDK 的固件工程采用 GNU Make 作为构建驱动,源码树中包含大量 .a 静态库归档(如协议栈、驱动、DSP 库等),并经常需要把多个归档合并成一个整体库后再交给链接器。Windows 原生环境不提供 make、find、rm 等工具,也不提供类 Unix 的归档处理流程,因此 SDK 在 tools/ 下捆绑了一套可移植工具链与批处理脚本:

  • make_prompt.bat 负责"环境引导"——把 tools/utils 加入 PATH,并切换到 SDK 根目录,随后打开交互式 cmd,让开发者在开箱即用的环境中执行 make;
  • do_merge_libs.bat 负责"库合并"——枚举输入目录下的所有 .a 文件,调用 merge-archives.exe 以 --no-rewrite 模式合并输出,保证归档成员的原始名称与顺序语义被保留。

关键概念

概念说明
.a 归档ar 格式的静态库归档文件,链接器按成员顺序扫描解析符号
--no-rewrite合并归档时保留原始成员名,不重写/重命名成员
延迟变量展开setlocal enabledelayedexpansion 配合 !VAR! 语法,使循环内累积的变量在运行时取值
可移植工具集由 MSYS/MinGW 风格工具(如 make.exe、find.exe)与运行时 DLL(libiconv2.dll、libintl3.dll)构成

Architecture

下图展示辅助脚本与工具集在 SDK 构建流程中的位置与调用关系:

flowchart TD
    subgraph sg_Boot["开发环境引导"]
        Prompt["tools/make_prompt.bat"]
    end

    subgraph sg_Utils["tools/utils 工具集"]
        MergeExe["merge-archives.exe"]
        Make["make.exe"]
        Find["find.exe"]
        Other["rm / ls / true / uname / override-seg 等"]
    end

    subgraph sg_Merge["库合并脚本"]
        DoMerge["tools/utils/do_merge_libs.bat"]
    end

    subgraph sg_Output["构建产物"]
        LibA["输入目录 *.a 静态库"]
        MergedLib["合并后的 .a 输出库"]
    end

    Prompt -->|"将 utils 目录加入 PATH"| sg_Utils
    Make -->|"构建流程中调用"| DoMerge
    DoMerge -->|"dir /b 枚举"| LibA
    DoMerge -->|"%MERGE% --no-rewrite --output"| MergeExe
    MergeExe --> MergedLib

架构说明:

  • make_prompt.bat 是环境入口。它不直接参与编译,而是把 tools/utils 前置到 PATH,使 cmd 中可以直接调用 make、find、merge-archives 等工具,随后 cd .. 回到 SDK 根目录并打开交互 shell。
  • tools/utils 是工具供给层。除 GNU 工具外,merge-archives.exe 是库合并功能的真正执行者,fixbat.exe、override-seg.exe 等则服务于构建链中的其他辅助需求(其内部实现未包含在已读脚本中,故本页不展开)。
  • do_merge_libs.bat 是合并流程的编排者。它把"枚举文件"与"执行合并"两个动作串联起来,输出供链接器使用的合并归档。

实现详解

make_prompt.bat:开发环境引导

tools/make_prompt.bat 全文只有 4 行,是整个 SDK 在 Windows 下构建体验的入口:

SET SCRIPT_PATH=%~dp0%
set PATH=%SCRIPT_PATH%\utils;%PATH%
cd ..
cmd

Source: make_prompt.bat

逐行解读:

  1. SET SCRIPT_PATH=%~dp0%:%~dp0 是批处理文件的驱动盘符+所在目录(以反斜杠结尾),例如 C:\sdk\tools\。此处使用 % 闭合的写法(%~dp0%)在 Windows 批处理中实际等效于 %~dp0,其目的是捕获脚本自身位置,从而不依赖"当前工作目录"这一易变状态——这是批处理脚本中常见的"自定位"技巧,保证无论从何处运行都能找到配套工具。
  2. set PATH=%SCRIPT_PATH%\utils;%PATH%:把 tools\utils 前置到 PATH 最前面。前置(而非追加)意味着若系统里已装有同名工具,也会优先使用 SDK 捆绑版本,避免版本差异导致的构建行为漂移。
  3. cd ..:从 tools/ 上溯到 SDK 根目录(tools 的上一级即仓库根),让后续 make 等命令天然在正确的工作目录下执行。
  4. cmd:启动一个继承上述环境变量的交互式 shell,开发者可直接键入 make 开始构建。

设计意图: SDK 构建强依赖 GNU 工具链,但 Windows 原生不提供。与其要求用户安装 MSYS2/Cygwin,不如把最小工具集随 SDK 分发,用一个脚本完成"环境装配",降低上手成本并保证工具版本可控。

tools/utils 工具集

tools/utils/ 目录捆绑了构建所需的可执行文件与运行时库(经 ListFiles 确认存在):

文件作用(依据文件名与调用关系推断)
make.exeGNU make,SDK Makefile 的执行引擎
find.exe / ls.exe / rm.exe / mkdir_win.exe类 Unix 文件操作工具,供 Makefile 规则调用
true.exe / uname.exeGNU 兼容工具,uname 常用于 Makefile 中的平台判断
merge-archives.exe归档合并工具,do_merge_libs.bat 的执行目标
override-seg.exe构建链中段(segment)覆盖相关工具
fixbat.exe批处理文件修正工具
libiconv2.dll / libintl3.dllGNU iconv / gettext 运行时库,支撑上述 MSYS 系工具的运行

注:fixbat.exe、override-seg.exe 等工具为二进制程序,仓库中未包含其源码或文档,本页对它们仅作存在性说明,不推断其内部行为。

do_merge_libs.bat:库合并脚本

tools/utils/do_merge_libs.bat 是合并流程的核心编排脚本:

@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%

Source: do_merge_libs.bat

关键机制:

  • 参数约定:%1=输入目录(INDIR)、%2=合并工具路径(MERGE)、%3=输出归档路径(AROUT)。参数化的设计让脚本可以被 Makefile 以不同目标反复调用,工具路径也可替换为其他兼容实现。
  • setlocal enabledelayedexpansion 与 !FILES!:这是本脚本最值得注意的细节。在 for 循环体内给变量赋值,若使用普通 %FILES% 语法,会在整条语句解析时就完成展开(此时 FILES 仍为空);必须启用延迟展开并用 !FILES! 才能在每次循环执行时取到当前值。这是批处理中"循环内累积字符串"的标准解法。
  • for /f "tokens=*" %%i in ('dir /b %INDIR%\*.a'):对输入目录执行 dir /b(仅文件名)并逐行迭代,tokens=* 保证含空格的路径也能整体取到;每行把 INDIR\文件名 追加进 FILES。
  • %MERGE% --no-rewrite --output %AROUT% %FILES%:最终调用合并工具。--no-rewrite 与 --output 是 merge-archives.exe 的 CLI 选项(调用形式即为其接口文档)。

merge-archives 与 --no-rewrite 的设计意图

merge-archives.exe 的选项通过 do_merge_libs.bat 第 17 行的调用约定得以确认:

%MERGE% --no-rewrite --output %AROUT% %FILES%

两个选项的意义:

  • --output <path>:指定合并结果的输出路径,即第三个参数 AROUT。
  • --no-rewrite:合并时不重写归档成员名。ar 归档按成员顺序保存对象文件,链接器对归档的解析是"顺序扫描 + 按需抽取";若合并工具重命名成员或重排成员顺序,可能改变链接器的符号解析结果,导致已解析符号被重新抽取、重复定义或未定义引用等问题。--no-rewrite 保证合并后的归档在链接语义上等价于"原样拼接"多个归档,这是 BLE 固件链接稳定性(链接顺序敏感)的关键保障。

设计意图总结:库合并不是简单的"文件拼接",而是要在保留归档成员语义(名称、顺序、符号表)的前提下做物理合并。do_merge_libs.bat 把"枚举—组装—执行"拆成清晰三步,参数全部外置,既便于 Makefile 复用,也让合并行为(工具、输入、输出)对构建脚本完全透明。

核心流程

环境引导流程

sequenceDiagram
    participant Dev as 开发者
    participant Prompt as make_prompt.bat
    participant Utils as tools/utils
    participant Shell as cmd 交互环境

    Dev->>Prompt: 双击 / 命令行运行
    Prompt->>Prompt: SCRIPT_PATH=%~dp0%(脚本自定位)
    Prompt->>Utils: PATH 前置 tools\utils
    Prompt->>Prompt: cd .. 进入 SDK 根目录
    Prompt->>Shell: 启动 cmd(继承新环境)
    Shell-->>Dev: 可直接执行 make / merge 等命令

库合并流程

flowchart TD
    Start([构建脚本调用 do_merge_libs.bat]) --> P1["读取参数<br/>INDIR / MERGE / AROUT"]
    P1 --> P2["dir /b 枚举 INDIR 下全部 *.a"]
    P2 --> P3{"存在 .a 文件?"}
    P3 -->|"否"| E1["FILES 为空,仅生成空归档"]
    P3 -->|"是"| P4["延迟展开拼接 FILES 列表"]
    P4 --> P5["执行 MERGE --no-rewrite --output AROUT"]
    P5 --> E2["得到合并后的 .a 输出库"]
    E1 --> End([结束])
    E2 --> End

两个流程说明:环境引导是"一次性装配"——脚本只负责把工具暴露出来并回到正确目录,后续命令由开发者在 shell 中自由执行;库合并是"幂等转换"——输入是目录快照,输出是单一归档,脚本自身不保留状态,任何时刻重跑都会得到一致的合并结果(前提是输入目录未变化)。

使用示例

启动开发环境

双击运行 tools/make_prompt.bat 后,在出现的 cmd 中即可直接使用捆绑工具:

REM 运行 make_prompt.bat 后,PATH 已包含 tools\utils
make -j8
find . -name "*.a"

Source: make_prompt.bat

调用库合并脚本

典型调用(三个位置参数:输入目录、合并工具、输出文件):

call do_merge_libs.bat build\libs tools\utils\merge-archives.exe build\libs\app_merged.a

脚本内部实际执行的命令等价于:

tools\utils\merge-archives.exe --no-rewrite --output build\libs\app_merged.a build\libs\lib_a.a build\libs\lib_b.a ...

Source: do_merge_libs.bat

配置选项

do_merge_libs.bat 位置参数

参数类型必需说明
%1(INDIR)目录路径是存放待合并 .a 文件的输入目录
%2(MERGE)可执行文件路径是合并工具,通常为 tools\utils\merge-archives.exe
%3(AROUT)文件路径是合并输出归档的完整路径

merge-archives.exe 命令行选项

选项说明
--no-rewrite合并时保留归档成员的原始名称,不重写成员(保持链接语义)
--output <path>指定输出归档路径

选项名称与语义来自 do_merge_libs.bat 的实际调用;该工具为二进制程序,仓库内无更多文档。

make_prompt.bat 环境变量

变量说明
PATH前置追加 tools\utils,使捆绑工具优先生效
SCRIPT_PATH脚本自身所在目录(%~dp0 展开),用于定位 utils 子目录

失败模式与边界情况

输入目录为空或无 .a 文件

dir /b %INDIR%\*.a 匹配不到任何文件时,FILES 保持为空,合并命令退化为 merge-archives.exe --no-rewrite --output AROUT(无输入成员)。此时生成的归档为空归档,链接时不会提供任何符号。Makefile 侧应在调用前确认输入目录产物已生成完毕,否则会出现"合并成功但链接缺符号"的隐性失败。

路径含空格

for /f "tokens=*" 保证枚举到的文件名整体赋给 %%i,且每个文件都以 INDIR\%%i 形式带引号加入 FILES?——注意:脚本并未显式加引号。若 SDK 仓库路径或输入目录路径含空格,%MERGE% --no-rewrite --output %AROUT% %FILES% 这一行的参数切分可能出错。因此建议将 SDK 放置在无空格的路径(如 C:\sdk\)下运行,这是批处理脚本常见的隐性约束。

延迟展开陷阱

若有人把 !FILES! 改成 %FILES%,循环内赋值将永不生效(整块在解析期一次性展开),最终 FILES 为空——这是本脚本最容易在维护时被改坏的点。保留 setlocal enabledelayedexpansion 与 !FILES! 的配对是正确性的前提。

并发与一致性

do_merge_libs.bat 读取输入目录快照并生成单一输出文件,脚本本身无并发保护。若多个 make 目标并行(make -j)同时对同一 INDIR 执行合并、写入同一 AROUT,将产生竞争写。实践中应由 Makefile 通过目标依赖关系串行化合并步骤,确保"先完成全部子库构建,再执行合并"。

setlocal 作用域

脚本使用 setlocal 而未显式 endlocal,批处理结束时环境变量自动恢复,不会污染调用方 shell;但这也意味着脚本内部设置的 FILES 等变量无法在调用方复用,属于"一次性计算"语义。

性能与运维说明

  • 合并操作为纯文件级拷贝/归档重组,耗时与归档总大小线性相关,通常远小于编译时间;无需额外优化。
  • merge-archives.exe 为 Windows 本地可执行文件,不依赖 MSYS2/Cygwin 运行时(仅依赖同目录的 libiconv2.dll/libintl3.dll),部署即拷即用。
  • make_prompt.bat 每次运行都重建环境,无缓存、无状态,适合反复进入开发环境。

扩展点

  • 替换合并工具:do_merge_libs.bat 的 %2 参数接受任意兼容 --no-rewrite/--output 接口的工具,可平滑替换为其他归档合并实现。
  • 扩充工具集:在 tools/utils 中追加新的可执行文件即可被 make_prompt.bat 暴露到 PATH,无需修改脚本。
  • 多目录合并:当前脚本仅支持单一输入目录;如需合并多个目录,可在 Makefile 层多次调用或先拷贝汇总到同一目录。

测试情况

仓库中未发现针对这两个批处理脚本的自动化测试(脚本为构建辅助性质,随构建流程隐式验证:合并结果能通过链接即视为通过)。若需回归验证,可构造含多个已知符号的 .a 归档,合并后用 nm/链接器检查符号完整性。

Related Links

  • tools/make_prompt.bat:开发环境引导脚本
  • tools/utils/do_merge_libs.bat:库合并脚本
  • tools/utils/:Windows 工具集目录(含 merge-archives.exe、make.exe 等)
  • 构建系统与 Makefile 规则、链接脚本等主题请参见对应目录页(本页不展开)
Prev
固件后处理与配置工具