基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析

前言

推動 PC 端 OpenHarmony 生態快速完善的過程中,大量三方開源庫需要完成適配、編譯鏈路打通與 HNP 組件化發佈,而 libzip 則是文件壓縮類庫中最基礎、使用最廣的工具之一。無論是文件管理工具、更新包解析、應用安裝器,還是後台資源解壓,幾乎都會依賴 ZIP 能力。因此,將 libzip 成功遷移到 OpenHarmony 不僅是單一庫的適配,更是構建完整開發環境的重要一環。

本文基於實際的 PC 端鴻蒙開發環境,完整演示 libzip 的 交叉編譯流程、CMake 構建配置、依賴聲明、HNP 元數據定義、產物安裝目錄處理 以及最終的 HNP 打包產出流程。同時也補充了 GitCode 託管與適配倉庫維護方法,幫助開發者從零到一完成一個第三方庫在鴻蒙上的全流程適配。希望本文能作為你後續適配更多三方開源庫的標準模版參考。

libzip 鴻蒙適配與構建全流程指南

切換到build/code目錄,通過 Git 從指定 GitCode 倉庫地址克隆 libzip 工具的源碼,在當前目錄生成libzip文件夾存放源碼,為後續開源鴻蒙適配準備基礎源碼

# 進入build目錄下的code子目錄 cd code # 從GitCode倉庫克隆libzip工具的源碼到當前目錄,創建名為libzip的文件夾 git clone https://gitcode.com/gh_mirrors/li/libzip.git

基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析_python

dependency.json 配置:聲明 libzip 的鴻蒙依賴信息

在 dependency.json 配置文件中,定義 libzip 的依賴信息,指定其名稱、適配鴻蒙的 1.11.4_ohos 分支,以及對應的 GitCode 倉庫地址,供構建流程拉取指定版本的 libzip 源碼

{ "dependency": [ { "name" : "libzip", "branch" : "1.11.4_ohos", "url" : "https://gitcode.com/weixin_62765017/libzip.git" } ] }

基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析_python_02

build.sh 主構建腳本:環境初始化與鴻蒙交叉編譯配置

這是 libzip 鴻蒙適配的主構建腳本,先校驗並傳入鴻蒙 SDK 路徑,根據構建系統配置編譯工具鏈,檢查 Python 依賴並給出系統適配的安裝指引,配置編譯相關環境變量及鴻蒙編譯參數;默認進入 libzip 目錄執行專屬構建腳本,也可通過參數按 dependency.json 拉取依賴構建

#!/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

基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析_python_03

hnp.json 配置:HNP 組件元信息定義

在 hnp.json 配置文件中,定義 libzip 的 HNP 配置信息,指定配置類型為 hnp-config、組件名稱和版本號,為空的 install 字段預留安裝相關配置空間,用於鴻蒙 HNP 打包時識別組件基礎信息

{ "type":"hnp-config", "name":"libzip", "version":"1.11.4", "install":{} }

基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析_json_04

build_ohos.sh:libzip 的鴻蒙平台專屬構建腳本

libzip 針對鴻蒙的專屬構建腳本,定義組件名稱版本及安裝路徑,清理並創建構建目錄;通過 CMake 配置鴻蒙編譯參數(指定工具鏈、關閉非必要功能、配置編譯器 / 鏈接器參數),編譯並安裝 libzip 到指定路徑;接着拷貝文檔和 hnp.json 配置文件,最後用 HNP 工具打包組件並生成壓縮包,完成鴻蒙適配的構建產物輸出

#!/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

基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析_json_05

構建與打包流程:生成 HNP 產物並輸出安裝包

進入本地 build 目錄,執行主構建腳本 build.sh 並傳入鴻蒙 SDK 的 Linux 版本路徑,觸發 libzip 針對鴻蒙系統的完整構建流程,生成適配的構建產物

cd ~/build ./build.sh --sdk ~/ohos-sdk/linux

基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析_#OpenHarmony_06

基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析_#libzip_07

推送至 GitCode:開源共建及遠程倉庫維護流程

1、GitCode 創建代碼倉庫

基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析_json_08

2、本地 Git 關聯遠程倉庫(可能會報錯,錯誤是 Git 的安全機制檢測到倉庫目錄的所有者有問題因為是 WSL 跨系統目錄,按照提示添加安全目錄例外即可)

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

基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析_json_09

3、拉取遠程 main 分支同步

# 拉取遠程main分支到本地(如果本地沒有main分支,會自動創建) git pull origin main

基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析_git_10

4、暫存所有本地修改和未追蹤文件

# 暫存所有本地修改(android/do.sh 等)+ 未追蹤的 hnp.json git add . # 驗證:確認無未合併路徑、所有修改已暫存 git status

基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析_json_11

5、完成合並提交

git commit -m "合併遠程main分支:以本地代碼為主,覆蓋README.md衝突"

基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析_git_12

6、強制推送本地代碼到遠程

git push -u origin main --force

基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析_git_13

基於 OpenHarmony 的 libzip 適配與交叉編譯實踐:構建系統、依賴管理與 HNP 打包全解析_python_14

libzip 鴻蒙構建安裝錯誤解決方案總覽

錯誤現象描述

在鴻蒙系統上構建 libzip 1.11.4 時,安裝階段出現以下錯誤:

Unknown argument --
Usage: cmake --install <dir> [options]
...
錯誤原因定位與觸發點分析

錯誤發生在構建腳本的安裝命令中:

${CMAKE} --install . --prefix "${install_prefix}" -- DESTDIR="${LIBZIP_INSTALL_HNP_PATH}"

CMake 3.20+ 版本不再接受 – DESTDIR= 這種參數傳遞方式

最終解決方案

修改文件:code/libzip/build_ohos.sh

修改行號:第 48 行

修改前(錯誤)

${CMAKE} --install . --prefix "${install_prefix}" -- DESTDIR="${LIBZIP_INSTALL_HNP_PATH}"

修改後(正確)

DESTDIR="${LIBZIP_INSTALL_HNP_PATH}" ${CMAKE} --install . --prefix "${install_prefix}"

修改説明

  • 將 DESTDIR 從命令行參數改為環境變量
  • 刪除無效的 – 分隔符
  • 保持其他參數不變
構建結果驗證方法

執行構建腳本後,檢查 libzip 是否成功安裝到指定目錄:

# 查看安裝目錄 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 的構建和安裝