基于 OpenHarmony 的 libzip 适配与交叉编译实践:构建系统、依赖管理与 HNP 打包全解析
前言
推动 PC 端 OpenHarmony 生态快速完善的过程中,大量三方开源库需要完成适配、编译链路打通与 HNP 组件化发布,而 libzip 则是文件压缩类库中最基础、使用最广的工具之一。无论是文件管理工具、更新包解析、应用安装器,还是后台资源解压,几乎都会依赖 ZIP 能力。因此,将 libzip 成功迁移到 OpenHarmony 不仅是单一库的适配,更是构建完整开发环境的重要一环。
本文基于实际的 PC 端鸿蒙开发环境,完整演示 libzip 的 交叉编译流程、CMake 构建配置、依赖声明、HNP 元数据定义、产物安装目录处理 以及最终的 HNP 打包产出流程。同时也补充了 GitCode 托管与适配仓库维护方法,帮助开发者从零到一完成一个第三方库在鸿蒙上的全流程适配。希望本文能作为你后续适配更多三方开源库的标准模版参考。
libzip 鸿蒙适配与构建全流程指南
切换到build/code目录,通过 Git 从指定 GitCode 仓库地址克隆 libzip 工具的源码,在当前目录生成libzip文件夹存放源码,为后续开源鸿蒙适配准备基础源码
bash# 进入build目录下的code子目录 cd code # 从GitCode仓库克隆libzip工具的源码到当前目录,创建名为libzip的文件夹 git clone https://gitcode.com/gh_mirrors/li/libzip.git
dependency.json 配置:声明 libzip 的鸿蒙依赖信息
在 dependency.json 配置文件中,定义 libzip 的依赖信息,指定其名称、适配鸿蒙的 1.11.4_ohos 分支,以及对应的 GitCode 仓库地址,供构建流程拉取指定版本的 libzip 源码
json{ "dependency": [ { "name" : "libzip", "branch" : "1.11.4_ohos", "url" : "https://gitcode.com/weixin_62765017/libzip.git" } ] }
build.sh 主构建脚本:环境初始化与鸿蒙交叉编译配置
这是 libzip 鸿蒙适配的主构建脚本,先校验并传入鸿蒙 SDK 路径,根据构建系统配置编译工具链,检查 Python 依赖并给出系统适配的安装指引,配置编译相关环境变量及鸿蒙编译参数;默认进入 libzip 目录执行专属构建脚本,也可通过参数按 dependency.json 拉取依赖构建
bash#!/bin/bash SDK_PATH="" while [[ $# -gt 0 ]]; do case "$1" in --sdk) SDK_PATH="$2" shift 2 ;; *) echo "Error: unknow param $1" echo "Usage: $0 --sdk <SDK path>" exit 1 ;; esac done if [ -z "$SDK_PATH" ]; then echo "Error: SDK path must be specified with the \"--sdk\" option" echo "Usage: $0 --sdk <SDK path>" exit 1 fi if [ ! -d "$SDK_PATH" ]; then echo "Error: SDK path is not exist or no permossion: [$SDK_PATH]" exit 2 fi export OHOS_SDK="$SDK_PATH" export HNP_PERFIX= BUILD_OS=$(uname) case $BUILD_OS in 'OpenHarmony') echo "Build in: <$(uname -a)> by local tool chains." export COMPILER_TOOLCHAIN=${OHOS_TOOL_CHAIN_PATH} ;; 'HarmonyOS') echo "Build in: <$(uname -a)> by local tool chains." export COMPILER_TOOLCHAIN=${HMOS_TOOL_CHAIN_PATH} export HNP_PERFIX=${PWD}/hnp ;; *) echo "Build in: <$(uname -a)> by cross tool chains." export COMPILER_TOOLCHAIN=${OHOS_SDK}/native/llvm/bin/ ;; esac if [ -z "${HNP_PERFIX}" ]; then export HNP_PERFIX="${PWD}/hnp" fi if [ -n "${HNP_PERFIX}" ]; then mkdir -p "${HNP_PERFIX}" fi PYTHON=$(python --version) echo "python : $PYTHON" if [ -z "$PYTHON" ]; then echo "You need install python in your system" case "$BUILD_OS" in OpenHarmony|HarmonyOS) echo "${BUILD_OS} install by url://www.xxx.xxx.com" ;; Linux* ) if command -v apt-get &> /dev/null; then echo "1. sudo apt update" echo "2. sudo apt install python3 python3-pip" elif command -v yum &> /dev/null; then echo "1. sudo yum install python3 python3-pip" else echo "Please install python3 and pip using your system's package manager." fi ;; Darwin*) echo "1. Use Homebrew: brew install python" echo "or" echo "2. Download by python org: https://www.python.org/downloads/macos/" ;; CYGWIN*|MINGW32*|MSYS*|MINGW*) echo "1. Download by python org: https://www.python.org/downloads/windows/" echo "2. Check the \"Add Python to PATH\" option during installation." ;; *) echo "Unable to determine the appropriate Python installation method for your system." ;; esac exit 1 fi export CC=${COMPILER_TOOLCHAIN}clang && echo "CC : ${CC}" export CXX=${COMPILER_TOOLCHAIN}clang++ && echo "CXX : ${CXX}" export HOSTCC=${CC} && echo "HOSTCC : ${HOSTCC}" export HOSTCXX=${CXX} && echo "HOSTCXX : ${HOSTCXX}" export CPP=${CXX} && echo "CPP : ${CPP}" export AS=${COMPILER_TOOLCHAIN}llvm-as && echo "AS : ${AS}" export LD=${COMPILER_TOOLCHAIN}ld.lld && echo "LD : ${LD}" export STRIP=${COMPILER_TOOLCHAIN}llvm-strip && echo "STRIP : ${STRIP}" export RANLIB=${COMPILER_TOOLCHAIN}llvm-ranlib && echo "RANLIB : ${RANLIB}" export OBJDUMP=${COMPILER_TOOLCHAIN}llvm-objdump && echo "OBJDUMP : ${OBJDUMP}" export OBJCOPY=${COMPILER_TOOLCHAIN}llvm-objcopy && echo "OBJCOPY : ${OBJCOPY}" export NM=${COMPILER_TOOLCHAIN}llvm-nm && echo "NM : ${NM}" export AR=${COMPILER_TOOLCHAIN}llvm-ar && echo "AR : ${AR}" export SYSROOT=${OHOS_SDK}/native/sysroot export PKG_CONFIG_SYSROOT_DIR=${SYSROOT}/usr/lib/aarch64-linux-ohos export PKG_CONFIG_PATH=${PKG_CONFIG_SYSROOT_DIR} export PKG_CONFIG_EXECUTABLE=${PKG_CONFIG_SYSROOT_DIR} export HNP_TOOL=${OHOS_SDK}/toolchains/hnpcli export CMAKE=${OHOS_SDK}/native/build-tools/cmake/bin/cmake export TOOLCHAIN_FILE=${OHOS_SDK}/native/build/cmake/ohos.toolchain.cmake export WORK_ROOT=${PWD} export ARCHIVE_PATH=${WORK_ROOT}/output export COMM_DEP_PATH=${WORK_ROOT}/deps_install export HNP_PUBLIC_PATH=${HNP_PERFIX}/data/service/hnp/ export MAKE_QUITE_PARAM=" -s " export CONFIGURE_QUITE_PARAM=" --quiet " export TARGET_PLATFORM=aarch64-linux-ohos export CFLAGS="-fPIC -D__MUSL__=1 -D__OHOS__ -fstack-protector-strong --target=${TARGET_PLATFORM} -fuse-ld=${LD} --sysroot=${SYSROOT}" export CXXFLAGS="${CFLAGS} " export LD_LIBRARY_PATH=${SYSROOT}/usr/lib:${LD_LIBRARY_PATH} export LDFLAGS="${LDFLAGS} -fuse-ld=${LD} --target=${TARGET_PLATFORM} --sysroot=${SYSROOT}" export HOST_TYPE="--host=aarch64-linux --build=aarch64-linux" mkdir -p ${HNP_PUBLIC_PATH} mkdir -p ${ARCHIVE_PATH} mkdir -p code # 默认直接构建指定目录,除非显式要求按 dependency.json 走 BUILD_BY_DEPENDENCY="${BUILD_BY_DEPENDENCY:-false}" # 需要构建的组件名称(默认构建 libzip) SPECIFIC_DIR="${SPECIFIC_DIR:-libzip}" if [[ "${BUILD_BY_DEPENDENCY}" == "true" ]]; then python build_dependency.py else pushd "code/${SPECIFIC_DIR}" chmod +x build_ohos.sh ./build_ohos.sh popd fi
hnp.json 配置:HNP 组件元信息定义
在 hnp.json 配置文件中,定义 libzip 的 HNP 配置信息,指定配置类型为 hnp-config、组件名称和版本号,为空的 install 字段预留安装相关配置空间,用于鸿蒙 HNP 打包时识别组件基础信息
json{ "type":"hnp-config", "name":"libzip", "version":"1.11.4", "install":{} }
build_ohos.sh:libzip 的鸿蒙平台专属构建脚本
libzip 针对鸿蒙的专属构建脚本,定义组件名称版本及安装路径,清理并创建构建目录;通过 CMake 配置鸿蒙编译参数(指定工具链、关闭非必要功能、配置编译器 / 链接器参数),编译并安装 libzip 到指定路径;接着拷贝文档和 hnp.json 配置文件,最后用 HNP 工具打包组件并生成压缩包,完成鸿蒙适配的构建产物输出
sh#!/bin/bash set -euo pipefail component_name="libzip" component_version="1.11.4" install_prefix="/usr" export LIBZIP_INSTALL_HNP_PATH="${HNP_PUBLIC_PATH}/${component_name}.org/${component_name}_${component_version}" echo "Install root: ${LIBZIP_INSTALL_HNP_PATH}" mkdir -p "${LIBZIP_INSTALL_HNP_PATH}" # 清理之前的构建 if [ -d "build" ]; then rm -rf build fi mkdir -p build # 使用 CMake 配置和构建 pushd build ${CMAKE} .. \ -DCMAKE_TOOLCHAIN_FILE="${TOOLCHAIN_FILE}" \ -DCMAKE_SYSROOT="${SYSROOT}" \ -DCMAKE_INSTALL_PREFIX="${install_prefix}" \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_SHARED_LIBS=ON \ -DBUILD_TOOLS=ON \ -DENABLE_OPENSSL=OFF \ -DENABLE_GNUTLS=OFF \ -DENABLE_MBEDTLS=OFF \ -DENABLE_COMMONCRYPTO=OFF \ -DENABLE_WINDOWS_CRYPTO=OFF \ -DENABLE_BZIP2=OFF \ -DENABLE_LZMA=OFF \ -DENABLE_ZSTD=OFF \ -DBUILD_REGRESS=OFF \ -DBUILD_EXAMPLES=OFF \ -DBUILD_DOC=OFF \ -DCMAKE_C_COMPILER="${CC}" \ -DCMAKE_CXX_COMPILER="${CXX}" \ -DCMAKE_C_FLAGS="${CFLAGS}" \ -DCMAKE_CXX_FLAGS="${CXXFLAGS}" \ -DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}" \ -DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}" \ -DCMAKE_STATIC_LINKER_FLAGS="${LDFLAGS}" ${CMAKE} --build . --config Release --parallel $(nproc) DESTDIR="${LIBZIP_INSTALL_HNP_PATH}" ${CMAKE} --install . --prefix "${install_prefix}" popd # 安装文档 doc_dir="${LIBZIP_INSTALL_HNP_PATH}/usr/share/doc/${component_name}" mkdir -p "${doc_dir}" if [ -f "README.md" ]; then install -m 644 README.md "${doc_dir}/" fi if [ -f "LICENSE" ]; then install -m 644 LICENSE "${doc_dir}/" fi if [ -f "NEWS.md" ]; then install -m 644 NEWS.md "${doc_dir}/" fi # 安装 hnp.json install -m 644 hnp.json "${LIBZIP_INSTALL_HNP_PATH}/" pushd "${LIBZIP_INSTALL_HNP_PATH}/../" ${HNP_TOOL} pack -i "${LIBZIP_INSTALL_HNP_PATH}" -o "${ARCHIVE_PATH}/" tar -zvcf "${ARCHIVE_PATH}/ohos_${component_name}_${component_version}.tar.gz" "${component_name}_${component_version}/" popd
构建与打包流程:生成 HNP 产物并输出安装包
进入本地 build 目录,执行主构建脚本 build.sh 并传入鸿蒙 SDK 的 Linux 版本路径,触发 libzip 针对鸿蒙系统的完整构建流程,生成适配的构建产物
bashcd ~/build ./build.sh --sdk ~/ohos-sdk/linux
推送至 GitCode:开源共建及远程仓库维护流程
1、GitCode 创建代码仓库
2、本地 Git 关联远程仓库(可能会报错,错误是 Git 的安全机制检测到仓库目录的所有者有问题因为是 WSL 跨系统目录,按照提示添加安全目录例外即可)
bashgit config --global --add safe.directory '%(prefix)///wsl$/Ubuntu-24.04/home/weishuo/build/code/libzip'3、拉取远程 main 分支同步
bash# 拉取远程main分支到本地(如果本地没有main分支,会自动创建) git pull origin main4、暂存所有本地修改和未追踪文件
bash# 暂存所有本地修改(android/do.sh 等)+ 未追踪的 hnp.json git add . # 验证:确认无未合并路径、所有修改已暂存 git status5、完成合并提交
bashgit commit -m "合并远程main分支:以本地代码为主,覆盖README.md冲突"6、强制推送本地代码到远程
git push -u origin main --force
libzip 鸿蒙构建安装错误解决方案总览
错误现象描述
在鸿蒙系统上构建 libzip 1.11.4 时,安装阶段出现以下错误:
Unknown argument --
Usage: cmake --install <dir> [options]
...
错误原因定位与触发点分析
错误发生在构建脚本的安装命令中:
bash
${CMAKE} --install . --prefix "${install_prefix}" -- DESTDIR="${LIBZIP_INSTALL_HNP_PATH}"
CMake 3.20+ 版本不再接受 -- DESTDIR= 这种参数传递方式
最终解决方案
修改文件:code/libzip/build_ohos.sh
修改行号:第 48 行
修改前(错误):
bash${CMAKE} --install . --prefix "${install_prefix}" -- DESTDIR="${LIBZIP_INSTALL_HNP_PATH}"修改后(正确):
bashDESTDIR="${LIBZIP_INSTALL_HNP_PATH}" ${CMAKE} --install . --prefix "${install_prefix}"修改说明
- 将 DESTDIR 从命令行参数改为环境变量
- 删除无效的 -- 分隔符
- 保持其他参数不变
构建结果验证方法
执行构建脚本后,检查 libzip 是否成功安装到指定目录:
bash# 查看安装目录 ls -la ${LIBZIP_INSTALL_HNP_PATH} # 检查库文件 ls -la ${LIBZIP_INSTALL_HNP_PATH}/usr/local/lib/*.a
构建与安装的注意事项
- 此修改只影响 CMake 3.20+ 版本的构建
- 编译过程中的 "warning: argument unused during compilation" 是无害警告,不影响最终结果
- 修改后的命令遵循 CMake 官方推荐的环境变量传递方式
这个解决方案已在实际的鸿蒙系统构建中验证通过,能够成功完成 libzip 的构建和安装













