基于 OpenHarmony 的 libzip 适配与交叉编译实践:构建系统、依赖管理与 HNP 打包全解析

基于 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 针对鸿蒙系统的完整构建流程,生成适配的构建产物

bash 复制代码
cd ~/build
./build.sh --sdk ~/ohos-sdk/linux
推送至 GitCode:开源共建及远程仓库维护流程

1、GitCode 创建代码仓库

2、本地 Git 关联远程仓库(可能会报错,错误是 Git 的安全机制检测到仓库目录的所有者有问题因为是 WSL 跨系统目录,按照提示添加安全目录例外即可)

bash 复制代码
git config --global --add safe.directory '%(prefix)///wsl$/Ubuntu-24.04/home/weishuo/build/code/libzip'

3、拉取远程 main 分支同步

bash 复制代码
# 拉取远程main分支到本地(如果本地没有main分支,会自动创建)
git pull origin main

4、暂存所有本地修改和未追踪文件

bash 复制代码
# 暂存所有本地修改(android/do.sh 等)+ 未追踪的 hnp.json
git add .

# 验证:确认无未合并路径、所有修改已暂存
git status

5、完成合并提交

bash 复制代码
git 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}"

修改后(正确)

bash 复制代码
DESTDIR="${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 的构建和安装

相关推荐
●VON3 小时前
Flutter for OpenHarmony前置知识《Flutter 状态管理入门实战:使用 Provider 构建计数器应用》
前端·学习·flutter·华为·openharmony
●VON1 天前
Flutter vs React Native vs 原生开发:有何不同?
学习·flutter·react native·react.js·openharmony
白茶三许1 天前
【OpenHarmony】深入理解 Flutter 异步编程:从基础到实战
flutter·开源·openharmony·gitcode
●VON1 天前
从零开始:用 Flutter 构建一个简洁高效的待办事项应用V1.0.0
学习·flutter·arm·openharmony·开源鸿蒙
●VON1 天前
Flutter for OpenHarmony前置知识《Flutter 基础组件初探:第一章》
学习·flutter·跨平台·开发·openharmony·开源鸿蒙
●VON1 天前
逐行解读 Flutter 默认模板:从 `main()` 到计数器 App
前端·学习·flutter·openharmony
A懿轩A1 天前
【2025版 OpenHarmony】GitCode 口袋工具 v1.0.3:Flutter + HarmonyOS 深色模式全面启用
flutter·harmonyos·openharmony·gitcode·开源鸿蒙
●VON2 天前
基于 Electron 模拟鸿蒙设备硬件信息查询的可行性探索
javascript·学习·electron·openharmony
●VON2 天前
Electron 项目在“鸿蒙端”与“桌面端”运行的区别
javascript·学习·electron·openharmony