欢迎加入【开源鸿蒙PC社区】,一起共建鸿蒙化C/C++三方库生态。
前言
ouch 是由 ouch-org 团队开发的压缩与解压缩命令行工具 ,全称 Obvious Unified Compression Helper(直观的统一压缩助手)。它旨在提供一种简单、统一的方式来处理多种压缩格式,支持 tar、gz、bz2、zst、lz4、xz、lzma、zip、7z、rar 等多种格式之间的相互转换和操作。与传统的压缩工具需要分别记忆不同格式的命令不同,ouch 通过智能的文件扩展名检测和统一的命令行接口,让用户无需关心底层实现细节即可完成压缩和解压操作,是终端环境下文件压缩管理的得力助手。
前置条件
系列索引
| 篇章 | 标题 | 内容 |
|---|---|---|
| 第一篇 | 概述与环境配置 | Lycium 概念、构建机要求、OHOS SDK 配置 |
| 第二篇 | 项目结构与适配目录创建 | 目录结构、community vs thirdparty、创建适配目录 |
| 第三篇 | HPKBUILD 编写详解 | 元数据字段、过程函数、三种构建系统写法 |
| 第四篇 | 构建执行与产物获取 | 构建流程、日志分析、多库递归、HAP 集成 |
| 第五篇 | 流程图与角色职责 | 完整流程图、各角色职责、协作时序 |
| 第六篇 | 关键注意事项与最佳实践 | 依赖管理、架构超集、日志调试、外部适配仓 |
| 第七篇 | 快速参考与模板 | 入门步骤、模板、完整案例、检查清单 |
| 第八篇「番外」 | 扩展lycium框架使其满足rust三方库适配 | 不改变框架原有设计,增加Rust三方库适配能力 |
一、环境配置
1 OpenHarmony SDK 安装
1.1 下载 SDK(环境搭建)
从OpenHarmony 官方首页下载 ohos-sdk 压缩包,步骤省略,详情可见前置条件中环境搭建相关文章。
SDK 下载注意事项:
- 需要注册并登录
AtomGit账户才可以下载。- 使用
Mac系统的开发者一定要下载linux版本的 sdk。- 存放路径不要含有中文字符、空格或特殊字符,建议直接放在用户根目录。
- 资源目录中依赖
ohos-sdk压缩包,解压后请勿移动/删除原始压缩包。
1.2 SDK 放置位置
接下来,我们需要将 ohos-sdk 解压并放置到适当的位置。以下是适用于 Linux 和 macOS 的示例命令:
bash
# Linux / macOS 示例(包名以 DCP 页面为准)
cd ~/
tar -xzf ohos-sdk-linux-v5.0.0-*.tar.gz
mv ohos-sdk ohos-sdk # 统一命名为 ohos-sdk
1.3 SDK 目录结构
解压后 SDK 的目录结构大致如下:
bash
ohos-sdk/
├── linux/ # 主机平台工具链
│ ├── native/ # Native 开发相关工具
│ │ ├── build-tools/ # cmake、ninja 等构建工具
│ │ ├── llvm/ # LLVM 工具链(clang、lld 等)
│ │ ├── sysroot/ # 系统根目录,包含 OHOS 头文件和库
│ │ ├── nativeapi_syscap_config/
│ │ └── ...
│ └── ...
└── ...
1.4 环境变量配置
将 SDK 路径添加到 shell 配置文件(如 ~/.zshrc、~/.bashrc 或 ~/.bash_profile):
bash
# OpenHarmony SDK 路径
export OHOS_SDK_HOME="$HOME/ohos-sdk"
export OHOS_NATIVE_HOME="$OHOS_SDK_HOME/linux/native"
# 添加到 PATH
export PATH="$OHOS_NATIVE_HOME/build-tools/bin:$OHOS_NATIVE_HOME/llvm/bin:$PATH"
# 验证
source ~/.zshrc # 或 source ~/.bashrc
1.5 验证 SDK 配置
使用以下命令验证 OHOS SDK 是否正确配置:
bash
# 检查 SDK 路径
echo $OHOS_SDK_HOME
# 期望输出: /Users/your-username/ohos-sdk
# 检查工具是否在 PATH 中
which cmake
which ninja
# 期望输出: /Users/your-username/ohos-sdk/linux/native/build-tools/bin/cmake
# 期望输出: /Users/your-username/ohos-sdk/linux/native/build-tools/bin/ninja
# 检查 SDK 工具目录
ls $OHOS_NATIVE_HOME
# 期望看到: build-tools llvm sysroot nativeapi_syscap_config 等目录
# 验证工具版本
cmake --version
ninja --version
2 Rust 工具链安装
Rust 工具链的安装方法在所有平台上基本一致,关键在于添加正确的 OHOS 目标平台支持。
2.1 安装 Rust
bash
# 安装 Rust(如果未安装)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# 验证安装
rustc --version # 应显示 rustc 1.xx.x 或更高版本
cargo --version # 应显示 cargo 1.xx.x
2.2 添加 OHOS 目标平台
bash
# 添加 OHOS 的目标平台支持
rustup target add aarch64-unknown-linux-ohos
2.3 配置 Rust 环境变量
bash
# Rust 环境变量(通常由 rustup 自动添加)
export CARGO_HOME="$HOME/.cargo"
export PATH="$CARGO_HOME/bin:$PATH"
export OHOS_RUST_TARGET=aarch64-unknown-linux-ohos
# 验证
source ~/.zshrc
echo $OHOS_RUST_TARGET
# 期望输出: aarch64-unknown-linux-ohos
注意:实际编译时,
lycium会自动设置环境变量,用户一般无需手动设置。
二、适配步骤
1. 分析ouch构建特性
ouch 由Rust语言编写,使用Cargo作为构建系统。编译后产出的二进制命令为ouch(与包名相同)。ouch 的 Cargo.toml 中 default = ["unrar", "use_zlib", "use_zstd_thin", "bzip3"] 表示默认启用 RAR、zlib、Zstandard 瘦版和 BZip3 支持。需要注意的是,ouch 的默认特性依赖了多个 C 语言库(unrar、zlib、zstd、bzip3),这些 C 库的源码通过 Rust 的 cc crate 在编译时自动编译。由于 lycium 框架已配置好 OHOS 交叉编译环境(CC、CFLAGS 等环境变量),cc crate 能够正确调用 OHOS 的交叉编译器,因此使用默认特性即可完成交叉编译。对于 RAR 格式的 unrar 依赖,如果需要简化构建过程,也可以通过 --no-default-features --features use_zlib,use_zstd_thin,bzip3 禁用它。
核心特性
-
统一压缩与解压
通过智能的文件扩展名检测,自动识别压缩格式并执行相应的压缩或解压操作。用户无需记忆不同工具的命令行参数,只需指定源文件和目标文件即可。
-
多格式支持
支持 tar、gz(gzip)、bz2(bzip2)、xz、lzma、zst(zstd)、lz4、zip、7z、rar 等多种常见压缩格式,以及格式之间的相互转换,满足日常文件处理的各种需求。
-
压缩级别控制
通过
--compression参数灵活控制压缩级别(0-9 或具体格式支持的级别范围),支持在压缩速度和文件大小之间按需平衡。 -
保留文件权限与时间戳
在解压时自动保留源文件的权限、修改时间和创建时间,确保文件元数据不丢失,适合用于备份和归档场景。
-
并行压缩加速
利用
rayon并行计算库,在多核 CPU 上并行处理文件压缩任务,显著提升大规模文件或目录的压缩速度。 -
友好的错误提示与进度显示
提供清晰、可读的错误消息,在压缩和解压过程中显示文件处理进度,帮助用户实时了解操作状态。
2. 创建适配项目
参考前置条件列表完成lycium_plusplus交叉框架编译环境搭建,以及lycium_plusplus交叉框架代码克隆,在lycium_plusplus/RustAdapt创建目标库ouch适配目录为ohos-ouch。
为什么是
ohos-ouch?为了和源库名称做区分,表示该库用于ohos设备。
ohos-ouch创建可以借助编辑器工具(如VSCode)或者使用文件夹在lycium_plusplus/RustAdapt目录下创建目标库适配目录ohos-ouch,也可以执行以下命令进行创建。
shell
# 我将交叉编译框架克隆在根目录,此处可改为正确的目录地址
cd ~/lycium_plusplus/RustAdapt
mkdir ohos-ouch
3. 编写HPKBUILD
然后将lycium/template/HPKBUILD.cargo拷贝到RustAdapt/ohos-ouch目录下,并重命名为HPKBUILD,HPKBUILD是lycium交叉编译框架完成编译构建的核心配置文件,定义包的元信息、依赖、构建和打包逻辑。需要根据模板在HPKBUILD开头声明ouch的基本信息,这些字段被lycium用于下载、组织和记录:
bash
# lycium_plusplus/RustAdapt/ohos-ouch/HPKBUILD
pkgname=ouch # 库名
pkgver=0.7.1 # 库版本
pkgrel=0 # 发布号
pkgdesc="A command-line utility for easily compressing and decompressing files and directories." # 库描述
url="https://github.com/ouch-org/ouch" # 官网链接
archs=("arm64-v8a") # cpu 架构
license=("MIT")
depends=() # 依赖库的目录名 必须保证被依赖的库的archs是当前库的archs的超集
makedepends=("cargo" "rustc") # 构建库时的依赖工具->需要用户安装的工具
source="https://github.com/ouch-org/ouch/archive/refs/tags/${pkgver}.tar.gz" # 库源码下载链接
downloadpackage=true # 是否自动下载压缩包,如若不写默认 true. (应对一些特殊情况,代码只能 git clone (项目中依赖 submoudle ))
autounpack=true # 是否自动解压,如若不写默认 true, 如果为 false 则需要用户在 prepare 函数中自行解压
buildtools=cargo # 编译方法: cmake(默认) | configure | cargo | 其它则不在此注入 buildargs,由 build() 自行处理
builddir=ouch-${pkgver} # 源码压缩包解压后目录名 编译目录名
packagename=$builddir.tar.gz # 压缩包名
注意 :ouch 的 GitHub 标签采用数字版本号格式(
0.7.1),不带v前缀 。因此source字段中${pkgver}前不加v,与常见的v${pkgver}格式不同。
| 字段 | 配置值 | 用途 |
|---|---|---|
pkgname |
ouch |
pkgname=ouch:包名,用于在 LYCIUM_ROOT/usr/ 下创建安装目录、标识依赖关系。 |
pkgver |
0.7.1 |
pkgver=0.7.1:上游版本号,与 https://github.com/ouch-org/ouch 仓库最新发行版本保持一致。 |
pkgrel |
0 |
pkgrel=0:包发布号,当同一上游版本需要重新打包时递增,首次适配为 0。 |
pkgdesc |
- | 包的简短描述,取自 ouch 官方 README。 |
url |
- | 上游项目主页 URL。 |
archs |
("arm64-v8a") |
archs=("arm64-v8a"):声明支持的架构数组。此处仅列出 arm64-v8a,但代码内部实际也处理了 armeabi-v7a 和 x86_64,此处是声明"主要支持"而非"仅支持"。当前鸿蒙 PC 设备为 arm64 架构,因此必须配置arm64-v8a。 |
license |
("MIT") |
ouch 采用 MIT 协议。 |
depends |
() |
无运行时依赖。 |
makedepends |
("cargo" "rustc") |
makedepends=("cargo" "rustc"):编译时依赖。Rust 工具链是构建前提。 |
source |
tags/${pkgver}.tar.gz |
源码包下载地址。使用 ${pkgver} 变量拼接,下载 ouch 0.7.1 的 release tarball(注意标签不带 v 前缀)。 |
downloadpackage |
true |
downloadpackage=true:告诉 lycium 构建系统自动下载 source 指定的源码包。如果设置为false需要在目标库目录下手动下载源码包。 |
autounpack |
true |
autounpack=true:下载后自动解压,无需手动解压步骤。如果设置为false需要手动解压。 |
buildtools |
cargo |
buildtools=cargo:声明构建工具类型。lycium 据此选择 Cargo 构建流程(而非 make/cmake 等)。 |
builddir |
ouch-${pkgver} |
builddir=ouch-${pkgver}:解压后的源码目录名。prepare()/build()/package() 均通过 cd $builddir 进入此目录。 |
packagename |
${builddir}.tar.gz |
packagename=${builddir}.tar.gz:源码包文件名,用于校验/定位。 |
package函数中编译完成后的二进制文件名称与包名一致,ouch项目编译完成后,会产出一个名为ouch的二进制文件,此处需要将cp target/${OHOS_RUST_TARGET}/release/xxx改为cp target/${OHOS_RUST_TARGET}/release/ouch并复制到安装目录。
sh
# 打包安装
package() {
# 进入 Rust 项目目录(和编译时同一个目录)
cd $builddir
# 定义安装路径:鸿蒙库的安装目录
DEST="$LYCIUM_ROOT/usr/$pkgname/$ARCH"
# 创建安装目录bin 文件夹
mkdir -p $DEST/bin/
# 【关键】把编译好的 Rust 程序 → 复制到目标目录的 bin 文件夹
cp target/${OHOS_RUST_TARGET}/release/ouch "$DEST/bin/"
cd $OLDPWD
}
4 HNP 打包配置
在lycium_plusplus/RustAdapt/ohos-ouch目录下创建hnp.json文件,因为在HPKBUILD中存在archive函数,用于将产物打包为 output/<arch>/<pkgname>_<ver>.tar.gz,或执行 HNP 打包,详细介绍可参考系列索引-构建执行与产物获取。
json
{
"type": "hnp-config",
"name": "ouch",
"version": "0.7.1",
"install": {}
}
5 交叉编译并解决可能存在的问题
HPKBUILD中函数不做改变,在lycium_plusplus/lycium目录下打开终端工具,输入./build.sh ohos-xh进行第一次交叉编译。
构建失败,ouch 依赖 unrar → unrar_sys 会编译 C++ 并打成静态库。最终链接时命令里会出现 -lstdc++(来自 rustc 对"含 C++ 对象"的默认处理,而不是 unrar_sys 的 build.rs 显式写的),于是报错:
sh
ld.lld: error: unable to find library -lstdc++
ouch 默认启用 unrar(Cargo.toml 的 default = ["unrar", ...]),unrar_sys 在编译 RAR 的 C++ 代码时,经 cc crate 把 -lstdc++ 写进 rlib 元数据,而 OHOS SDK只有 libc++(libc++.so 等),没有 libstdc++,在 lycium/script/build_hpk.sh 的 cargodependpath() 里已设置交叉链接器,但未指定 OHOS 的 C++ 标准库名。
在 lycium/script/build_hpk.sh 的 cargodependpath() 里,告诉 cc crate(各 *-sys 的 build.rs 里编译 C/C++ 时用)链接时使用 libc++,而不是默认的 libstdc++。
sh
# Rust(cargo):为 depends 拼接 pkg-config / OpenSSL 路径,并设置 OHOS 交叉链接器与 C/C++ 编译环境(供 build.rs/cc-rs)
cargodependpath() {
buildargs=""
pkgconfigpath=""
unset CARGO_TARGET_AARCH64_UNKNOWN_LINUX_OHOS_LINKER CARGO_TARGET_ARMV7_UNKNOWN_LINUX_OHOS_LINKER CARGO_TARGET_X86_64_UNKNOWN_LINUX_OHOS_LINKER 2>/dev/null
unset CARGO_TARGET_AARCH64_UNKNOWN_LINUX_OHOS_RUSTFLAGS CARGO_TARGET_ARMV7_UNKNOWN_LINUX_OHOS_RUSTFLAGS CARGO_TARGET_X86_64_UNKNOWN_LINUX_OHOS_RUSTFLAGS 2>/dev/null
unset CXXSTDLIB OPENSSL_DIR OPENSSL_LIB_DIR OPENSSL_INCLUDE_DIR 2>/dev/null
if [ ${#depends[@]} -ne 0 ]
then
for depend in ${depends[@]}
do
dependpath=$LYCIUM_ROOT/usr/$depend/$1/lib/pkgconfig
if [ -d "${dependpath}" ]
then
pkgconfigpath=$pkgconfigpath"${dependpath}:"
fi
case "$depend" in
openssl|openssl111)
if [ -d "$LYCIUM_ROOT/usr/$depend/$1" ]
then
export OPENSSL_DIR="$LYCIUM_ROOT/usr/$depend/$1"
export OPENSSL_LIB_DIR="$OPENSSL_DIR/lib"
export OPENSSL_INCLUDE_DIR="$OPENSSL_DIR/include"
fi
;;
esac
done
pkgconfigpath=${pkgconfigpath%:*}
fi
if [ -n "$pkgconfigpath" ]
then
export PKG_CONFIG_PATH="$pkgconfigpath"
export PKG_CONFIG_ALLOW_CROSS=1
else
unset PKG_CONFIG_PATH
fi
case "$1" in
arm64-v8a) export OHOS_RUST_TARGET=aarch64-unknown-linux-ohos ;;
armeabi-v7a) export OHOS_RUST_TARGET=armv7-unknown-linux-ohos ;;
x86_64) export OHOS_RUST_TARGET=x86_64-unknown-linux-ohos ;;
*) echo "cargodependpath: unknown ARCH=$1"; return 1 ;;
esac
if [ -f "${LYCIUM_ROOT}/script/envset.sh" ]
then
# shellcheck source=envset.sh
. "${LYCIUM_ROOT}/script/envset.sh"
if [ -n "${TARGET_HARMONYOS}" ] && [ "$1" = "arm64-v8a" ]
then
setHarmonyOSENV
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_OHOS_LINKER="${CC:-clang}"
else
case "$1" in
armeabi-v7a) setarm32ENV ;;
arm64-v8a) setarm64ENV ;;
x86_64) setx86_64ENV ;;
esac
if [ -n "$OHOS_SDK" ] && [ -d "$OHOS_SDK/native/llvm/bin" ]
then
case "$1" in
arm64-v8a)
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_OHOS_LINKER="$OHOS_SDK/native/llvm/bin/aarch64-linux-ohos-clang"
;;
armeabi-v7a)
export CARGO_TARGET_ARMV7_UNKNOWN_LINUX_OHOS_LINKER="$OHOS_SDK/native/llvm/bin/arm-linux-ohos-clang"
;;
x86_64)
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_OHOS_LINKER="$OHOS_SDK/native/llvm/bin/x86_64-linux-ohos-clang"
;;
esac
else
case "$1" in
arm64-v8a) export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_OHOS_LINKER="${CC:-clang}" ;;
armeabi-v7a) export CARGO_TARGET_ARMV7_UNKNOWN_LINUX_OHOS_LINKER="${CC:-clang}" ;;
x86_64) export CARGO_TARGET_X86_64_UNKNOWN_LINUX_OHOS_LINKER="${CC:-clang}" ;;
esac
fi
# OHOS 使用 libc++;rustc 链接含 C++ 静态库时仍会注入 -lstdc++,需改链 libc++ 并提供兼容符号
export CXXSTDLIB=c++
if [ -n "$OHOS_SDK" ]
then
case "$1" in
arm64-v8a)
_ohos_rust_triple=aarch64-linux-ohos
_ohos_rust_libdir="${OHOS_SDK}/native/llvm/lib/${_ohos_rust_triple}"
_ohos_rust_linkhack="${LYCIUM_ROOT}/tmp/ohos-rust-link/${_ohos_rust_triple}"
mkdir -p "${_ohos_rust_linkhack}"
ln -sf "${_ohos_rust_libdir}/libc++.so" "${_ohos_rust_linkhack}/libstdc++.so"
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_OHOS_RUSTFLAGS="-L${_ohos_rust_linkhack} -L${_ohos_rust_libdir} -C link-arg=-lc++"
;;
armeabi-v7a)
_ohos_rust_triple=arm-linux-ohos
_ohos_rust_libdir="${OHOS_SDK}/native/llvm/lib/${_ohos_rust_triple}"
_ohos_rust_linkhack="${LYCIUM_ROOT}/tmp/ohos-rust-link/${_ohos_rust_triple}"
mkdir -p "${_ohos_rust_linkhack}"
ln -sf "${_ohos_rust_libdir}/libc++.so" "${_ohos_rust_linkhack}/libstdc++.so"
export CARGO_TARGET_ARMV7_UNKNOWN_LINUX_OHOS_RUSTFLAGS="-L${_ohos_rust_linkhack} -L${_ohos_rust_libdir} -C link-arg=-lc++"
;;
x86_64)
_ohos_rust_triple=x86_64-linux-ohos
_ohos_rust_libdir="${OHOS_SDK}/native/llvm/lib/${_ohos_rust_triple}"
_ohos_rust_linkhack="${LYCIUM_ROOT}/tmp/ohos-rust-link/${_ohos_rust_triple}"
mkdir -p "${_ohos_rust_linkhack}"
ln -sf "${_ohos_rust_libdir}/libc++.so" "${_ohos_rust_linkhack}/libstdc++.so"
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_OHOS_RUSTFLAGS="-L${_ohos_rust_linkhack} -L${_ohos_rust_libdir} -C link-arg=-lc++"
;;
esac
fi
fi
fi
return 0
}

如果提示ALL JOBS DONE!!!表示当前交叉编译没有问题,编译后的产物,可以在lycium/usr/目录和out/arm64-v8目录下查看。

三、 在鸿蒙PC上验证交叉编译后的ouch命令是否可用
将lycium_plusplus/lycium/usr/ouch/arm64-v8a/bin/ouch二进制文件传到鸿蒙PC上,方式有多种,可以通过聊天软件。macos设备可以在App Store下载【鸿蒙星河互联】,通过分享方式将ouch二进制文件发送到鸿蒙PC设备上,这种方式需要鸿蒙PC开启华为分享为所有人可见。在鸿蒙PC右下角会弹出接受弹窗,选择"接受"或者"另存为",接受ouch二进制文件。接受后的二进制文件是不可以直接运行的,哪怕使用chmod +x ouch这种方式授权也是无法运行的。需要给二进制文件进行签名后才可以,在鸿蒙 PC 侧执行前涉及二进制签名流程,可参考《鸿蒙PC端二进制文件签名命令行使用指南》。打开鸿蒙PC终端,输入以下命令为ouch签名授权。
sh
# 进入ouch所在目录
cd Desktop
# 执行签名
binary-sign-tool sign -inFile ouch -outFile ouch -selfSign "1"
# 授予权限
chmod +x ouch
# 查看ouch版本
./ouch --version
# 使用 ouch 压缩文件
echo "hello ouch" > test.txt && ./ouch compress test.txt test.tar.gz
# 使用 ouch 解压文件
./ouch decompress test.tar.gz

四、 FAQ
执行签名命令出现"zsh: command not found: binary-sign-tool"提示。
需要在应用市场搜索DevBox并安装,DevBox提供了一些开发者常用命令,主要包含文件和目录操作命令、网络命令、构建命令、签名工具等。
