本文记录在 aarch64 目标下使用命令 OHOS_ARCH=aarch64 OHOS_ABI=arm64-v8a sh ./create-hnp.sh 构建 Expat 2.7.1 的完整过程,涵盖源获取与配置、构建日志、常见问题处理,便于复现与维护。
📖 Expat 简介
Expat 是一个用 C 语言编写的流式 XML 解析器库,由 James Clark 开发。Expat 是一个事件驱动的解析器,它通过回调函数来处理 XML 文档中的元素、属性和文本内容。Expat 是许多 XML 处理工具和库的基础,被广泛用于各种应用程序中。
🎯 Expat 的作用与重要性
Expat 是 XML 处理的核心库,提供了:
- 流式解析:支持流式解析,可以处理大型 XML 文件而无需将整个文件加载到内存中
- 事件驱动:基于回调函数的事件驱动模型,高效且灵活
- 轻量级:代码库小巧,性能优秀,适合嵌入式系统
- 标准兼容:符合 XML 1.0 标准,支持命名空间
- 广泛使用:被许多知名项目使用,如 Python、Perl、PHP、Apache、libarchive 等
- 命令行工具:提供
xmlwf工具用于验证 XML 文件的格式正确性
🔧 Expat 核心特性
1. 流式解析
- 内存效率:不需要将整个 XML 文件加载到内存中
- 大文件支持:可以处理任意大小的 XML 文件
- 实时处理:可以在解析过程中实时处理数据
- 低延迟:解析速度快,延迟低
2. 事件驱动模型
- 回调函数:通过回调函数处理 XML 事件
- 元素处理:
XML_StartElementHandler- 元素开始 - 元素结束:
XML_EndElementHandler- 元素结束 - 文本内容:
XML_CharacterDataHandler- 文本数据 - 属性处理:在元素开始回调中处理属性
- 命名空间:支持 XML 命名空间处理
3. 编码支持
- UTF-8:默认支持 UTF-8 编码
- UTF-16:支持 UTF-16 编码(大端和小端)
- ISO-8859-1:支持 Latin-1 编码
- US-ASCII:支持 ASCII 编码
- 自动检测:可以自动检测 XML 声明的编码
4. 错误处理
- 错误回调:
XML_ErrorHandler- 处理解析错误 - 错误信息:提供详细的错误信息和位置
- 错误恢复:支持错误恢复机制
- 验证模式:可以启用严格的验证模式
5. 性能优化
- 快速解析:高效的解析算法
- 内存管理:灵活的内存管理选项
- 线程安全:支持多线程环境
- 可配置:可以配置解析器的行为
6. 应用场景
- 配置文件解析:解析 XML 配置文件
- 数据交换:处理 XML 格式的数据交换
- Web 服务:处理 SOAP、REST API 的 XML 响应
- 文档处理:处理 XML 格式的文档
- 嵌入式系统:在资源受限的环境中处理 XML
🚀 构建入口与顶层组织
- 📝 执行命令:
OHOS_ARCH=aarch64 OHOS_ABI=arm64-v8a sh ./create-hnp.sh - 🔧 入口脚本:
create-hnp.sh导出 SDK 路径并触发顶层构建 - 顶层 Makefile:
build-hnp/Makefile已将expat纳入PKGS,base.hnp依赖所有包完成标记STAMP并完成打包与拷贝到entry/hnp/$(OHOS_ABI)
⚙️ 包配置与工具链
- 包 Makefile:
build-hnp/expat/Makefile- 源地址:
https://github.com/libexpat/libexpat/releases/download/R_2_7_1/expat-2.7.1.tar.xz - 配置参数:
--prefix=$(PREFIX) --disable-static --enable-shared --host $(OHOS_ARCH)-unknown-linux-musl - 使用通用 Autotools 宏构建(下载→解包→
configure→make→install→strip→复制至../sysroot)
- 源地址:
- 工具链:
aarch64-unknown-linux-ohos-clang与 LLVMar/ranlib/strip
📋 关键执行与日志
- 下载与解包:
- 从 GitHub Releases 获取归档,解包至
temp/expat-2.7.1并创建build目录
- 从 GitHub Releases 获取归档,解包至
- 配置与编译:
- 交叉构建启用;CMake 片段用于安装
expat-config.cmake与 pkg-configexpat.pc(由上游make install生成)
- 交叉构建启用;CMake 片段用于安装
- 安装与复制:
- 安装共享库与头文件、
xmlwf工具、手册与文档;随后 strip 并复制至../sysroot
- 安装共享库与头文件、
✅ 产物验证
📦 检查打包文件
ls build-hnp/base.hnp # 应存在
ls entry/hnp/arm64-v8a/*.hnp # 应包含 base.hnp 与 base-public.hnp
🔍 检查 Expat 库和工具
# 检查共享库
ls -lh build-hnp/sysroot/lib/libexpat*
file build-hnp/sysroot/lib/libexpat.so.1
# 检查头文件
ls -lh build-hnp/sysroot/include/expat*.h
# 检查命令行工具
ls -lh build-hnp/sysroot/bin/xmlwf
file build-hnp/sysroot/bin/xmlwf
# 检查 pkg-config 文件
ls -lh build-hnp/sysroot/lib/pkgconfig/expat.pc
cat build-hnp/sysroot/lib/pkgconfig/expat.pc
# 检查 CMake 配置文件
ls -lh build-hnp/sysroot/lib/cmake/expat-2.7.1/

✅ 构建验证结果:
- ✅ Expat 共享库已安装:
libexpat.so.1.10.2(144K) - 主共享库libexpat.so.1- 版本符号链接libexpat.so- 开发符号链接
- ✅ 文件类型:ELF 64-bit LSB shared object, ARM aarch64
- ✅ 动态链接:
dynamically linked - ✅ 已剥离符号:
stripped - ✅ 头文件已安装:
expat.h(44K) - 主头文件expat_external.h(5.9K) - 外部接口头文件expat_config.h(4.1K) - 配置头文件
- ✅ 命令行工具已安装:
xmlwf(27K) - XML 格式验证工具
- ✅ 配置文件已安装:
expat.pc(300B) - pkg-config 配置文件expat-config.cmake- CMake 配置文件
- ✅ HNP 包产物:
entry/hnp/arm64-v8a/base.hnp与base-public.hnp - ✅ 已打包到
base.hnp中
🐛 常见问题与处理
❌ 问题 1:镜像下载失败
- 🔍 症状:下载
expat-2.7.1.tar.xz失败 - 🔎 原因:GitHub Releases 访问不稳定或网络问题
- ✅ 解决方法:
- 通用规则中已引入
curl兜底 - 必要时可扩展为备用源(如镜像站点)
- 检查网络连接和代理设置
- 位置:
build-hnp/expat/Makefile的下载规则
- 通用规则中已引入
❌ 问题 2:静态/共享策略
- 🔍 症状:需要静态链接或共享库配置问题
- 🔎 原因:当前配置启用共享库并移除
.la文件 - ✅ 解决方法:
- 如需静态链接,可调整配置选项为
--enable-static --disable-shared - 共享库配置适合大多数场景
- 位置:
build-hnp/expat/Makefile:6
- 如需静态链接,可调整配置选项为
❌ 问题 3:链接错误
- 🔍 症状:编译时出现
undefined reference to 'XML_*'错误 - 🔎 原因:未正确链接 Expat 库
- ✅ 解决方法:
- 使用
-lexpat链接选项 - 设置
LD_LIBRARY_PATH=/data/app/base.org/base_1.0/lib - 使用 pkg-config:
pkg-config --libs expat - 确保头文件路径正确:
-I/data/app/base.org/base_1.0/include
- 使用
❌ 问题 4:编码问题
- 🔍 症状:解析包含非 ASCII 字符的 XML 文件时出错
- 🔎 原因:XML 文件编码与解析器设置不匹配
- ✅ 解决方法:
- 确保 XML 文件有正确的编码声明:
<?xml version="1.0" encoding="UTF-8"?> - 使用
XML_SetEncoding设置编码 - 检查文件实际编码与声明是否一致
- 使用 UTF-8 编码(推荐)
- 确保 XML 文件有正确的编码声明:
❌ 问题 5:内存问题
- 🔍 症状:解析大型 XML 文件时内存不足
- 🔎 原因:流式解析器配置不当或内存管理问题
- ✅ 解决方法:
- 使用流式解析,分块读取文件
- 使用
XML_SetUserData传递用户数据 - 及时释放不需要的数据
- 检查内存泄漏(使用工具如 valgrind)
❌ 问题 6:命名空间处理
- 🔍 症状:无法正确处理 XML 命名空间
- 🔎 原因:未使用命名空间感知的解析器
- ✅ 解决方法:
- 使用
XML_ParserCreateNS创建命名空间感知的解析器 - 使用
XML_SetStartElementHandler和XML_SetEndElementHandler处理命名空间 - 检查命名空间 URI 和前缀
- 使用
❌ 问题 7:错误处理
- 🔍 症状:解析错误时无法获取详细信息
- 🔎 原因:未设置错误处理回调
- ✅ 解决方法:
- 使用
XML_SetErrorHandler设置错误处理回调 - 使用
XML_GetErrorCode获取错误代码 - 使用
XML_ErrorString获取错误描述 - 使用
XML_GetCurrentLineNumber和XML_GetCurrentColumnNumber获取错误位置
- 使用
❌ 问题 8:线程安全
- 🔍 症状:多线程环境下解析出错
- 🔎 原因:Expat 解析器不是线程安全的
- ✅ 解决方法:
- 每个线程使用独立的解析器实例
- 使用互斥锁保护共享数据
- 避免在多线程间共享解析器实例
🔄 重建与清理
-
🔧 重建单包:
make -C build-hnp rebuild-expat # 触发子包重新编译并刷新 .stamp -
🧹 清理:
make -C build-hnp clean # 清理 sysroot、所有 .stamp 和 PKGS_MARKER -
📦 扩展:Expat 是 XML 处理的基础库,适合用于配置文件解析、数据交换等场景
-
🔄 自动重建机制:
- 修改
PKGS后,check-pkgs会自动检测变化并触发重新构建 - 新增外部 HNP 包到
external-hnp目录后,会自动合并到base.hnp
- 修改
💡 实践建议
- 🔧 构建配置:使用 Autotools 构建系统,配置清晰,交叉编译参数正确
- 🚀 使用场景:Expat 适合用于 XML 配置文件解析、数据交换、Web 服务等场景
- 📦 依赖管理:Expat 是独立的库,无特殊依赖,适合轻量级应用
- 🔗 链接建议:使用 pkg-config 或直接链接
-lexpat,设置正确的库路径 - 🌐 编码建议:推荐使用 UTF-8 编码,确保 XML 文件有正确的编码声明
- 🔒 安全建议:验证 XML 文件格式,处理解析错误,避免 XML 注入攻击
📝 结论与建议
- ✅ Expat 2.7.1 在 aarch64 目标下完成交叉构建,库与头文件进入
sysroot并纳入 HNP 打包。 - 💡 为保证构建稳定:
- 使用 Autotools 构建系统,配置清晰
- 无特殊依赖,构建过程简单
- 确保通过
create-hnp.sh触发构建以获得完整环境变量 - 利用
check-pkgs机制自动检测包列表变化,无需手动清理 - Expat 为 XML 处理提供了高效的流式解析能力
- 常见陷阱包括镜像下载失败、链接错误、编码问题、内存问题;当前已通过构建配置处理
- 建议作为 XML 处理的基础库,适合轻量级应用和嵌入式系统
- 构建过程简洁,Autotools 交叉参数清晰,产物安装路径明确
- 产物开箱即用,适合在设备上进行 XML 文件解析和验证
📚 以上为 Expat 构建的深度解读与实践记录。Expat 是 XML 处理的基础库,被广泛用于各种应用程序中,为配置文件解析、数据交换等场景提供了高效的解决方案。
442

被折叠的 条评论
为什么被折叠?



