一、前言

bzip2 是一款经典且高效的无损数据压缩/解压缩工具,其压缩率优于传统的 gzip,在Linux、类Unix等系统中是标配的命令行工具,被广泛用于文件打包、数据归档等场景。

鸿蒙PC版作为面向桌面场景的鸿蒙操作系统形态,原生命令行工具链中暂未集成bzip2相关工具(如bzip2bzcatbunzip2等)能力,无法直接处理 .bz2tar.bz2等格式的压缩文件。

本次技术适配的核心目标是:将经典的 bzip2 v1.0.8 版本源码完成鸿蒙PC(AArch64架构)的交叉编译移植,为鸿蒙PC命令行环境新增完整的bz2格式压缩/解压缩能力,补齐鸿蒙PC在文件压缩格式支持上的短板,同时也为鸿蒙生态下的命令行工具移植提供标准化的实操参考。

二、环境准备与基础说明

2.1 鸿蒙PC交叉编译核心环境

本次移植基于鸿蒙官方Linux版SDK完成交叉编译,目标架构为 鸿蒙PC 标准的 AArch64 (aarch64-linux-ohos),核心依赖的鸿蒙SDK及编译工具链均为官方原生提供,所有环境配置均可复现:

# 鸿蒙SDK根目录配置
export OHOS_SDK=~/harmonypc/ohos-sdk/linux

# 配置鸿蒙编译工具链PATH优先级,保证优先调用鸿蒙SDK内置工具
export PATH=${OHOS_SDK}/native/llvm/bin:$PATH

2.2 鸿蒙交叉编译工具链全局环境变量配置

鸿蒙SDK内置了完整的 LLVM 编译工具链,替代了传统的 GCC 工具链,是鸿蒙系统交叉编译的标准选型。我们通过全局环境变量指定所有编译、链接、归档相关工具,保证整个编译流程统一使用鸿蒙官方工具链,无环境冲突:

# 鸿蒙llvm编译工具链全量配置
export AS=${OHOS_SDK}/native/llvm/bin/llvm-as
export CC="${OHOS_SDK}/native/llvm/bin/clang"
export CXX="${OHOS_SDK}/native/llvm/bin/clang++"
export LD=${OHOS_SDK}/native/llvm/bin/ld.lld
export STRIP=${OHOS_SDK}/native/llvm/bin/llvm-strip
export RANLIB=${OHOS_SDK}/native/llvm/bin/llvm-ranlib
export OBJDUMP=${OHOS_SDK}/native/llvm/bin/llvm-objdump
export OBJCOPY=${OHOS_SDK}/native/llvm/bin/llvm-objcopy
export NM=${OHOS_SDK}/native/llvm/bin/llvm-nm
export AR=${OHOS_SDK}/native/llvm/bin/llvm-ar

# 核心编译CFLAGS/CXXFLAGS,指定鸿蒙目标平台+编译特性
export CFLAGS="--target=aarch64-linux-ohos -fPIC -D__MUSL__=1"
export CXXFLAGS="--target=aarch64-linux-ohos -fPIC -D__MUSL__=1"
关键编译参数说明
  1. --target=aarch64-linux-ohos:核心交叉编译参数,指定编译产物的目标运行平台为鸿蒙PC的AArch64架构,clang会根据该参数适配对应的系统调用、库链接规则;
  2. -fPIC:生成位置无关代码,满足鸿蒙动态链接的标准要求,保证编译产物可正常集成到鸿蒙系统;
  3. -D__MUSL__=1:鸿蒙系统底层采用 musl libc 作为C标准库,该宏定义可让bzip2源码适配musl libc的编译规则,避免标准库接口兼容问题。

三、获取bzip2 v1.0.8 源码

本次选择 bzip2 稳定版 v1.0.8 进行移植,该版本功能完善、bug少、兼容性强,是生产环境的主流选型。源码通过git克隆获取,指定对应tag,保证源码版本精准无差异:

# 克隆bzip2源码,指定checkout到v1.0.8稳定版本
git clone https://atomgit.com/oh-tpc/bzip2.git -b v1.0.8
cd bzip2

四、核心适配改造:编写Makefile补丁,实现外部环境变量优先级支持

如上图所示,是v1.0.8版本的bzip2源码,可以看到不包含autogen.sh,不包含configure,不包含CMakeLists.txt,只有一个Makefile,也就是说这份源码是直接通过make方式进行直接编译的。

但是,当我们执行完make命令发现,得到的bzip2命令是x86-64架构,并不是我们需要的aarch64架构。

4.1 问题根源:原生Makefile的编译变量硬编码问题

如上图所示,是Makefile开头部分的代码,可以看到CCARRANLIBLDFLAGSCFLAGS全部都是硬编码写死。硬编码带来一个缺陷:我们在外部通过 export 配置了鸿蒙的交叉编译环境变量(如CC=clangAR=llvm-ar)后,执行make时,Makefile内的硬编码值会覆盖掉外部的环境变量,导致始终调用本地的gcc/ar而非鸿蒙的交叉编译工具链,最终编译产物为x86架构,无法在鸿蒙PC运行。

4.2 改造Makefile支持交叉编译

针对上述问题,我们对bzip2的Makefile做最小化、无侵入式的改造,核心原则:让外部配置的环境变量拥有最高优先级,原生Makefile的配置作为兜底默认值,补丁commit信息及完整diff如下:

commit 496c3d547980817bc266300f9cd2dd650160c62f (HEAD -> v1.0.8)
Author: Alex <guoyong.lei@163.com>
Date:   Sat Jan 10 00:14:58 2026 +0800

    外部CC/AR/RANLIB/LDFLAGS/CFLAGS优先,便于鸿蒙pc交叉编译

diff --git a/Makefile b/Makefile
index f8a1772..5e6f3dc 100644
--- a/Makefile
+++ b/Makefile
@@ -15,13 +15,13 @@
 SHELL=/bin/sh

 # To assist in cross-compiling
-CC=gcc
-AR=ar
-RANLIB=ranlib
-LDFLAGS=
+CC?=gcc
+AR?=ar
+RANLIB?=ranlib
+LDFLAGS?=

 BIGFILES=-D_FILE_OFFSET_BITS=64
-CFLAGS=-Wall -Winline -O2 -g $(BIGFILES)
+CFLAGS+=-Wall -Winline -O2 -g $(BIGFILES)

本次改造的目的是为了让原生Makefile支持交叉编译,仅修改了赋值语法,无任何业务逻辑变更,改动量极小且完全兼容原生编译,核心修改点共2类:

4.3.1 改造1:= 改为 ?= (变量弱赋值)

Makefile中的 ?=条件赋值语法,其核心规则:如果该变量在外部(环境变量/命令行)已经被定义,则不执行赋值;如果未定义,则使用等号后的默认值

  • 原语法 CC=gcc:强制赋值,无论外部是否配置CC,均使用gcc;
  • 新语法 CC?=gcc:兜底赋值,外部配置了CC=clang则用clang,未配置则默认用gcc。
    该改造同时作用于 CC/AR/RANLIB/LDFLAGS 四个核心变量,完美解决了外部交叉编译工具链被覆盖的问题。
4.3.2 改造2:CFLAGS= 改为 CFLAGS+= (变量追加赋值)

Makefile中的 +=追加赋值语法,其核心规则:保留外部已定义的变量值,将后面的内容追加到变量末尾

  • 原语法 CFLAGS=-Wall -Winline -O2 -g $(BIGFILES):强制覆盖所有CFLAGS配置,外部的--target=aarch64-linux-ohos等鸿蒙编译参数会全部失效;
  • 新语法 CFLAGS+=-Wall -Winline -O2 -g $(BIGFILES):保留我们外部配置的CFLAGS="--target=aarch64-linux-ohos -fPIC -D__MUSL__=1",同时追加bzip2原生的编译优化、告警、大文件支持参数,实现外部鸿蒙编译参数 + 原生编译参数的无缝融合

如上图所示,该补丁已经提交到仓库中,可点击链接查看详情。

五、执行鸿蒙交叉编译,生成鸿蒙PC可执行产物

完成上述补丁改造后,整个编译流程变得极简,无需修改任何源码、无需配置复杂的编译脚本,所有交叉编译的规则都通过环境变量+Makefile补丁自动生效,这也是本次移植的核心优势:极简适配、无侵入改造

在bzip2源码根目录,直接执行原生的make; make install命令即可完成bzip2工具集的编译和安装,鸿蒙的交叉编译环境会自动介入:

# 执行鸿蒙交叉编译,无任何额外参数
make; make install

如上如所示,可以看到,最终得到的工具集也由之前的X86_64架构变成了鸿蒙PC专属的ARM aarch64架构。

六、鸿蒙PC端验证与使用

6.1 自签名并增加可执行权限

将编译生成的 bzip2bunzip2bzcat三个可执行程序拷贝到鸿蒙PC,进行自签名,然后赋予执行权限:

# 自签名
bash-5.3$ binary-sign-tool sign -inFile bzip2 -outFile bzip2 -selfSign "1"
bash-5.3$ binary-sign-tool sign -inFile bunzip2 -outFile bunzip2 -selfSign "1"
bash-5.3$ binary-sign-tool sign -inFile bzcat -outFile bzcat -selfSign "1"

# 增加可执行权限
chmod +x bzip2 bunzip2 bzcat

6.2 功能验证

在鸿蒙PC的命令行终端执行以下命令,验证bzip2的完整功能,所有操作均与Linux原生bzip2完全一致,无缝兼容用户使用习惯.

6.2.1 查看bzip2版本号
bzip2 --version

如上图所示,bzip2命令执行成功,版本号也是我们移植的1.0.8,符合预期。

6.2.2 压缩+解压文件测试
# 1. 压缩文件:生成xxx.bz2压缩包,保留原文件
bzip2 -k hello.py

# 2. 解压缩文件:解压xxx.bz2,保留压缩包
bunzip2 -k hello.py.bz2

如上图所示,bzip2命令的压缩功能和bunzip2命令的解压功能工作正常。

6.2.3 解压tar.bz2格式文件测试

使用tar xjf命令解压tar.bz2格式文件,需要系统中存在bzcat命令。

tar xjf myapp.tar.bz2

如上图所示,tar命令已经可以顺利解压tar.bz2格式文件。

七、移植总结与技术沉淀

本次bzip2移植到鸿蒙PC的工作,全程遵循最小化改造、标准化适配、无侵入开发的原则,最终实现了完美适配,核心收获与技术经验如下:

  1. 鸿蒙交叉编译核心原则:鸿蒙PC的交叉编译本质是「指定目标架构+使用官方工具链」,所有第三方C/C++工具的移植,核心都是让源码适配鸿蒙的 aarch64-linux-ohos 目标平台,无需对业务源码做大幅修改;
  2. Makefile适配最佳实践:第三方开源工具的原生Makefile大多为硬编码,改造的核心就是通过 ?=(弱赋值)和 +=(追加赋值)让外部环境变量优先级高于内部配置,这是通用解决方案,适用于绝大多数开源工具的鸿蒙移植;
  3. 环境变量的重要性:统一配置鸿蒙SDK的工具链环境变量,能从根源上避免编译工具冲突,保证交叉编译的一致性和可复现性;
  4. 兼容性保障:本次移植的bzip2 v1.0.8版本与鸿蒙PC的musl libc完全兼容,编译产物无任何依赖问题,可直接在鸿蒙PC上稳定运行,无崩溃、无内存泄漏。

八、结尾

这次成功将bzip2命令移植到鸿蒙PC,增加了对.bz2格式的压缩和解压缩支持,丰富了鸿蒙PC的命令行工具。该移植过程具有很强的通用性,可以作为其他开源命令行工具(如xz、zip、unzip等)移植的参考。作为新兴的桌面操作系统,鸿蒙PC需要更多开源工具的支持。通过基于官方SDK的标准交叉编译,可以使这一适配过程更加简单高效。希望此次技术实践能为鸿蒙生态的开发者提供有价值的参考,共同推动鸿蒙PC工具链生态的发展。

本次移植的所有配置、补丁、编译命令均可100%复现,无任何隐藏依赖,适配过程简洁高效。若在移植过程中遇到问题,可参考bzip2官方文档或加入开源鸿蒙PC社区交流。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐