本文记录使用命令 OHOS_ARCH=aarch64 OHOS_ABI=arm64-v8a sh ./create-hnp.sh 构建 Libarchive 3.8.1 的完整过程,包括环境、构建链路、关键日志、常见问题与解决方案、产物验证与重建方法,便于复现与运维。
📖 Libarchive 简介
Libarchive 是一个功能强大的多格式归档和压缩库,提供了统一的接口来处理各种归档格式。它是 FreeBSD 项目的一部分,被广泛用于文件归档、备份、软件包管理等场景。Libarchive 支持读取和写入多种归档格式,包括 tar、zip、cpio、ISO 9660 等。
🎯 Libarchive 的作用与重要性
Libarchive 是现代软件生态中归档处理的核心组件,提供了:
- 多格式支持:支持 tar、zip、cpio、ISO 9660、7z、ar、mtree 等多种格式
- 压缩支持:支持 gzip、bzip2、xz、lzma、zstd、lz4 等多种压缩算法
- 统一接口:提供统一的 API 处理不同格式的归档文件
- 命令行工具 :提供
bsdtar、bsdcpio、bsdcat、bsdunzip等工具 - 开发库 :提供
libarchive库供应用程序使用 - 跨平台:支持多种操作系统和架构
🔧 Libarchive 核心特性
1. 支持的归档格式
- tar:标准 tar 格式(包括 USTAR、GNU tar、PAX)
- zip:ZIP 格式(包括 PKZIP、Info-ZIP)
- cpio:CPIO 格式(包括 ASCII、binary、newc)
- ISO 9660:CD/DVD 镜像格式
- 7z:7-Zip 格式
- ar:静态库归档格式
- mtree:FreeBSD mtree 格式
- shar:Shell 归档格式
2. 支持的压缩算法
- gzip:基于 zlib 的 gzip 压缩
- bzip2:bzip2 压缩算法
- xz/lzma:xz/lzma 压缩算法(可选)
- zstd:Zstandard 压缩算法
- lz4:LZ4 压缩算法
- compress:传统 compress 压缩
3. 命令行工具
bsdtar- tar 归档工具(类似 GNU tar)bsdcpio- cpio 归档工具bsdcat- 查看归档文件内容bsdunzip- ZIP 文件解压工具
4. API 特性
- 流式处理:支持流式读取和写入,适合大文件处理
- 过滤器链:支持多个压缩过滤器组合
- 格式自动检测:自动检测归档格式和压缩算法
- 错误处理:完善的错误码和错误处理机制
🚀 构建入口与环境
- 📝 执行命令 :
OHOS_ARCH=aarch64 OHOS_ABI=arm64-v8a sh ./create-hnp.sh - 🔧 入口脚本 :
create-hnp.sh- 检查必需的环境变量
OHOS_ARCH和OHOS_ABI - 导出
LC_CTYPE、TOOL_HOME、OHOS_SDK_HOME - 执行
make -C build-hnp
- 检查必需的环境变量
- 📦 顶层构建 :
build-hnp/MakefilePKGS变量定义需要构建的包列表(包含libarchive)- 通过
check-pkgs机制自动检测PKGS变化并触发重新构建 - 自动合并
external-hnp目录下的外部 HNP 包 base.hnp依赖所有包的.stamp和外部 HNP 包- 总目标
all: copy,打包base.hnp并拷贝到entry/hnp/$(OHOS_ABI)
⚙️ Libarchive 包的构建配置
- 📁 包目录 :
build-hnp/libarchive/Makefile- 继承通用规则:
include ../utils/Makefrag - 源地址:
https://www.libarchive.org/downloads/libarchive-3.8.1.tar.gz - 版本:
3.8.1
- 继承通用规则:
- ⚙️ Autotools 配置参数 :
--prefix=$(PREFIX)- 安装前缀(/data/app/base.org/base_1.0)--host $(OHOS_ARCH)-unknown-linux-musl- 目标平台--disable-static- 禁用静态库--enable-shared- 构建共享库--without-xml2 --without-expat- 禁用 XML 支持--without-libb2 --without-lzma- 禁用 bzip2 和 xz 支持CPPFLAGS/CFLAGS/LDFLAGS- 指定 sysroot 和目标架构- 依赖显式传入:
ZLIB_LIBS、LZ4_LIBS、ZSTD_LIBS、OPENSSL_LIBS等
- 🔨 构建流程 :
- 下载源码包(支持多镜像回退)
- 解包并进入
temp/libarchive-3.8.1目录 - 运行
./configure配置构建系统 - 使用
make -j $(nproc)并行编译 - 使用
make install安装 - 执行 ELF strip 减小体积
- 复制到
../sysroot
- 🔧 通用工具链与路径 :
build-hnp/utils/MakefragCC/CXX/LD/AR/RANLIB/...均指向 OHOS SDK 的 LLVM 工具链- 下载支持多镜像回退:
wget→curl,主镜像失败时自动尝试备用镜像
📋 关键日志与过程节点
- 📥 下载与解包 :
- 从
libarchive.org下载libarchive-3.8.1.tar.gz - 完成解包并进入
temp/libarchive-3.8.1目录 - 下载规则支持多镜像回退:
wget→curl兜底
- 从
- ⚙️ 配置阶段 :
- 运行
./configure --prefix=... --host=aarch64-unknown-linux-musl --disable-static --enable-shared ... - 显式传递依赖库路径:
ZLIB_LIBS、LZ4_LIBS、ZSTD_LIBS、OPENSSL_LIBS - 配置成功,检测到 zlib、lz4、zstd、openssl 支持
- 生成
Makefile和构建配置
- 运行
- 🔨 编译与安装 :
- 使用
make -j $(nproc)并行编译 - 成功编译生成
libarchive.so.13.8.1和命令行工具 - 使用
make install安装到临时前缀 - 执行
llvm-strip剥离共享库和二进制符号 - 复制到
../sysroot
- 使用
- 📦 打包 :
- 完成
base.hnp重打包,拷贝产物到entry/hnp/arm64-v8a/ - Libarchive 库和工具已成功打包到
base.hnp中
- 完成
✅ 产物验证
📦 检查打包文件
bash
ls build-hnp/base.hnp # 应存在
ls entry/hnp/arm64-v8a/*.hnp # 应包含 base.hnp 与 base-public.hnp
🔍 检查二进制和库文件
bash
# 检查 libarchive 命令行工具
ls -lh build-hnp/sysroot/bin/bsd*
file build-hnp/sysroot/bin/bsdtar
file build-hnp/sysroot/bin/bsdcpio
# 检查库文件
ls -lh build-hnp/sysroot/lib/libarchive.so*
file build-hnp/sysroot/lib/libarchive.so.13.8.1
# 检查头文件
ls -lh build-hnp/sysroot/include/archive*.h
# 检查 pkg-config 文件
ls -lh build-hnp/sysroot/lib/pkgconfig/libarchive.pc
cat build-hnp/sysroot/lib/pkgconfig/libarchive.pc
✅ 构建验证结果:
- ✅ libarchive 命令行工具已成功安装:
bsdtar(80K) - tar 归档工具bsdcpio(46K) - cpio 归档工具bsdcat(11K) - 查看归档文件内容bsdunzip(31K) - ZIP 文件解压工具
- ✅ Libarchive 库已安装:
libarchive.so.13.8.1(1017K) - 主库文件libarchive.so.13- 版本符号链接libarchive.so- 通用符号链接
- ✅ 文件类型:ELF 64-bit LSB shared object/executable, ARM aarch64
- ✅ 头文件已安装:
archive.h(55K)、archive_entry.h(35K) - ✅ pkg-config 文件已安装:
libarchive.pc(361 bytes) - ✅ 版本信息:3.8.1
💻 终端中执行的示例命令
📦 bsdtar 基本使用
1. 创建归档文件
bash
# 创建 tar 归档
bsdtar -cf archive.tar file1.txt file2.txt
# 创建 tar.gz 归档(gzip 压缩)
bsdtar -czf archive.tar.gz directory/
# 创建 tar.zst 归档(zstd 压缩)
bsdtar -czf archive.tar.zst directory/
# 创建 tar.lz4 归档(lz4 压缩)
bsdtar -czf archive.tar.lz4 directory/
# 创建 tar 归档并显示进度
bsdtar -cvf archive.tar directory/
# 创建归档并排除某些文件
bsdtar -czf archive.tar.gz --exclude='*.log' --exclude='*.tmp' directory/
2. 提取归档文件
bash
# 提取 tar 归档
bsdtar -xf archive.tar
# 提取 tar.gz 归档
bsdtar -xzf archive.tar.gz
# 提取 tar.zst 归档
bsdtar -xzf archive.tar.zst
# 提取到指定目录
bsdtar -xzf archive.tar.gz -C /path/to/destination
# 提取并显示进度
bsdtar -xvf archive.tar.gz
# 提取特定文件
bsdtar -xzf archive.tar.gz file1.txt file2.txt
# 提取并保留权限
bsdtar -xzf archive.tar.gz --preserve-permissions
3. 查看归档内容
bash
# 列出归档内容
bsdtar -tf archive.tar
# 列出归档内容(详细)
bsdtar -tvf archive.tar.gz
# 列出归档内容(长格式)
bsdtar -tvvf archive.tar.gz
# 搜索归档中的文件
bsdtar -tf archive.tar.gz | grep pattern
# 查看归档信息
bsdtar -tzf archive.tar.gz --list
4. 更新和追加文件
bash
# 更新归档中的文件
bsdtar -uf archive.tar file1.txt
# 追加文件到归档
bsdtar -rf archive.tar newfile.txt
# 追加文件到压缩归档
bsdtar -rzf archive.tar.gz newfile.txt
5. 压缩格式选项
bash
# 使用 gzip 压缩(-z)
bsdtar -czf archive.tar.gz directory/
# 使用 zstd 压缩(-z,自动检测)
bsdtar -czf archive.tar.zst directory/
# 使用 lz4 压缩(-z,自动检测)
bsdtar -czf archive.tar.lz4 directory/
# 指定压缩级别(gzip)
bsdtar -czf archive.tar.gz --options gzip:compression-level=9 directory/
# 不使用压缩
bsdtar -cf archive.tar directory/
📦 bsdcpio 基本使用
6. 创建和提取 cpio 归档
bash
# 创建 cpio 归档(从文件列表)
find directory/ -print | bsdcpio -o > archive.cpio
# 创建 cpio 归档(gzip 压缩)
find directory/ -print | bsdcpio -o | gzip > archive.cpio.gz
# 提取 cpio 归档
bsdcpio -i < archive.cpio
# 提取 cpio.gz 归档
gunzip -c archive.cpio.gz | bsdcpio -i
# 提取到指定目录
bsdcpio -i -d /path/to/destination < archive.cpio
# 列出 cpio 归档内容
bsdcpio -t < archive.cpio
# 列出 cpio 归档内容(详细)
bsdcpio -tv < archive.cpio
📦 bsdcat 和 bsdunzip 使用
7. 查看归档内容
bash
# 查看归档文件内容(自动检测格式)
bsdcat archive.tar
# 查看压缩归档内容
bsdcat archive.tar.gz
# 查看并提取到标准输出
bsdcat archive.tar.gz | head -20
# 查看特定文件
bsdcat archive.tar.gz file1.txt
8. 解压 ZIP 文件
bash
# 解压 ZIP 文件
bsdunzip archive.zip
# 解压到指定目录
bsdunzip -d /path/to/destination archive.zip
# 列出 ZIP 文件内容
bsdunzip -l archive.zip
# 测试 ZIP 文件完整性
bsdunzip -t archive.zip
# 解压特定文件
bsdunzip archive.zip file1.txt file2.txt
📦 高级用法
9. 归档格式转换
bash
# 从 tar 转换为 cpio
bsdtar -cf - directory/ | bsdcpio -o > archive.cpio
# 从 cpio 转换为 tar
bsdcpio -i < archive.cpio | bsdtar -cf archive.tar
# 转换压缩格式
bsdtar -xzf archive.tar.gz -O | bsdtar -czf archive.tar.zst
10. 实际应用示例
bash
# 备份目录(带时间戳)
bsdtar -czf backup-$(date +%Y%m%d-%H%M%S).tar.gz /path/to/backup
# 增量备份(只备份修改的文件)
bsdtar -czf backup.tar.gz --newer-mtime="2024-01-01" directory/
# 创建归档并验证
bsdtar -czf archive.tar.gz directory/ && bsdtar -tzf archive.tar.gz
# 归档并排除大文件
bsdtar -czf archive.tar.gz --exclude='*.iso' --exclude='*.img' directory/
# 归档多个目录
bsdtar -czf archive.tar.gz dir1/ dir2/ dir3/
# 从归档中删除文件
bsdtar --delete -f archive.tar file1.txt
# 比较归档和目录
bsdtar -df archive.tar.gz directory/
# 流式归档(通过网络传输)
bsdtar -czf - directory/ | ssh remote "bsdtar -xzf -"
# 归档并显示统计信息
bsdtar -czf archive.tar.gz directory/ --totals
# 创建归档并设置权限
bsdtar -czf archive.tar.gz --mode=755 directory/
🧪 功能验证脚本
bash
#!/bin/bash
# Libarchive 工具验证脚本
LIBARCHIVE_BIN="build-hnp/sysroot/bin"
LIBARCHIVE_LIB="build-hnp/sysroot/lib"
echo "=== Libarchive 工具验证 ==="
# 检查命令行工具
for tool in bsdtar bsdcpio bsdcat bsdunzip; do
if [ -f "$LIBARCHIVE_BIN/$tool" ]; then
echo "✓ $tool: 存在"
file "$LIBARCHIVE_BIN/$tool"
echo "文件大小: $(ls -lh "$LIBARCHIVE_BIN/$tool" | awk '{print $5}')"
else
echo "✗ $tool: 缺失"
fi
done
# 检查库文件
echo ""
echo "=== 库文件验证 ==="
if [ -f "$LIBARCHIVE_LIB/libarchive.so.13.8.1" ]; then
echo "✓ libarchive.so.13.8.1: 存在"
file "$LIBARCHIVE_LIB/libarchive.so.13.8.1"
echo "文件大小: $(ls -lh "$LIBARCHIVE_LIB/libarchive.so.13.8.1" | awk '{print $5}')"
else
echo "✗ libarchive.so.13.8.1: 缺失"
fi
# 检查符号链接
for link in libarchive.so libarchive.so.13; do
if [ -L "$LIBARCHIVE_LIB/$link" ]; then
echo "✓ $link: 符号链接 -> $(readlink "$LIBARCHIVE_LIB/$link")"
else
echo "✗ $link: 缺失"
fi
done
# 检查头文件
echo ""
echo "=== 头文件验证 ==="
for header in archive.h archive_entry.h; do
if [ -f "build-hnp/sysroot/include/$header" ]; then
echo "✓ $header: 存在"
echo " 文件大小: $(ls -lh "build-hnp/sysroot/include/$header" | awk '{print $5}')"
else
echo "✗ $header: 缺失"
fi
done
# 检查 pkg-config 文件
echo ""
echo "=== pkg-config 验证 ==="
if [ -f "build-hnp/sysroot/lib/pkgconfig/libarchive.pc" ]; then
echo "✓ libarchive.pc: 存在"
cat build-hnp/sysroot/lib/pkgconfig/libarchive.pc
else
echo "✗ libarchive.pc: 缺失"
fi
🐛 常见问题与处理
❌ 问题 1:编译器/环境污染
- 🔍 症状 :configure 读取到异常的
CC值(包含宿主PATH串),导致编译器探测失败或参数解析错乱 - 🔎 原因:环境变量被 PATH 污染,交叉编译器路径不正确
- ✅ 解决方法 :
- 确保使用
create-hnp.sh脚本执行构建(自动设置环境变量) - 在
configure命令中显式指定CFLAGS和LDFLAGS,包含--target和--sysroot - 位置:
build-hnp/libarchive/Makefile:11-12
- 确保使用
❌ 问题 2:标准头缺失与类型检测失败
- 🔍 症状 :
stddef.h not found、pid_t doesn't exist on this platform? - 🔎 原因 :交叉环境未正确设置
--target与--sysroot,导致头文件路径不正确 - ✅ 解决方法 :
- 在
CPPFLAGS中显式指定 sysroot 和 include 路径:CPPFLAGS="--sysroot=$(OHOS_SDK_HOME)/native/sysroot -I$(OHOS_SDK_HOME)/native/sysroot/usr/include"
- 在
CFLAGS和LDFLAGS中指定--target和--sysroot - 位置:
build-hnp/libarchive/Makefile:10-12
- 在
❌ 问题 3:依赖库未找到
- 🔍 症状:configure 失败,提示找不到 zlib、lz4、zstd 或 openssl
- 🔎 原因 :依赖库未正确安装到
../sysroot或路径配置不正确 - ✅ 解决方法 :
- 确保依赖库已构建:
zlib、lz4、zstd、openssl - 显式传递依赖库路径:
ZLIB_LIBS、LZ4_LIBS、ZSTD_LIBS、OPENSSL_LIBS - 设置
PKG_CONFIG_PATH指向../sysroot/lib/pkgconfig - 位置:
build-hnp/libarchive/Makefile:13-17
- 确保依赖库已构建:
❌ 问题 4:LZMA/XML 支持问题
- 🔍 症状:需要 xz 或 XML 支持但未启用
- 🔎 原因 :当前配置禁用了
liblzma(xz)和 XML 相关依赖 - ✅ 解决方法 :
- 如果需要 xz 支持,需要先构建
xz/liblzma,然后移除--without-lzma - 如果需要 XML 支持,需要先构建
libxml2或expat,然后移除--without-xml2或--without-expat - 位置:
build-hnp/libarchive/Makefile:9
- 如果需要 xz 支持,需要先构建
❌ 问题 5:静态库未构建
- 🔍 症状 :需要静态库但构建时使用了
--disable-static - 🔎 原因:当前配置禁用了静态库以减小体积
- ✅ 解决方法 :
- 如果需要静态库,移除
--disable-static或添加--enable-static - 位置:
build-hnp/libarchive/Makefile:8
- 如果需要静态库,移除
🔄 重建与扩展
-
🔧 重建单包:
bashmake -C build-hnp rebuild-libarchive # 触发子包重新编译并刷新 .stamp -
🧹 清理:
bashmake -C build-hnp clean # 清理 sysroot、所有 .stamp 和 PKGS_MARKER -
📦 扩展:Libarchive 是许多归档和压缩工具的基础依赖
-
🔄 自动重建机制:
- 修改
PKGS后,check-pkgs会自动检测变化并触发重新构建 - 新增外部 HNP 包到
external-hnp目录后,会自动合并到base.hnp
- 修改
💡 实践建议
- 🔧 依赖管理:确保所有依赖库(zlib、lz4、zstd、openssl)已正确构建和安装
- 🚀 格式支持:根据需求选择支持的归档格式和压缩算法
- 📦 体积优化:禁用不需要的功能(如 xz、XML)可以减小库体积
- 🔗 工具使用 :
bsdtar是tar的替代品,提供更好的格式支持和错误处理 - 🌐 压缩栈建设 :Libarchive 与
zlib/zstd/lz4及(可选)xz联合提供全面的归档/压缩支持
📝 结论与建议
- ✅ 本次已在 aarch64 环境下完成 Libarchive 3.8.1 的交叉编译与打包,libarchive 命令行工具和库已安装到
sysroot并纳入 HNP 包。 - 💡 为保证构建稳定 :
- 固定可靠的上游镜像,避免下载阶段随机失败(已实现自动回退机制)
- 使用 Autotools 构建系统,显式传递交叉编译参数
- 确保
--target与--sysroot正确传递,避免环境污染 - 显式传递依赖库路径,确保特性探测和链接成功
- 利用
check-pkgs机制自动检测包列表变化,无需手动清理 - Libarchive 可与
zlib/zstd/lz4及(可选)xz联合提供全面的归档/压缩支持 - 常见陷阱包括环境污染(
CC/OHOS_SDK_HOME被 PATH 串污染)与路径格式问题;当前已通过切换 Autotools 与显式参数修复
📚 以上为 Libarchive 构建的深度解读与实践记录。