开源鸿蒙PC三方库:从空白文件开始,写出第一份 HPKBUILD
开源鸿蒙PC三方库:从空白文件开始,写出第一份 HPKBUILD
以 MediaInfo 为例,还原我从一份空模板开始,一点点把它填成可用配方的真实过程。
欢迎加入开源鸿蒙 PC 社区:https://harmonypc.csdn.net/
开源仓库地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_mediainfo_hpkbuild
本篇思路源自社区作者 wei_shuo 的https://weishuo.blog.csdn.net/article/details/161294044,我按自己的理解重新组织了讲法。致谢原作者的开源贡献。
为什么很多人卡在「空白的 HPKBUILD」
我自己刚上手时也一样:知道要写 HPKBUILD,但盯着空文件不知道第一行敲什么。后来想明白了——HPKBUILD 没那么玄,它就是一个遵循框架约定的 bash 脚本,你只要实现框架点名要的几个函数,它会按固定顺序帮你调。
lycium(lycium_plusplus)帮我屏蔽了交叉编译里最难的四类差异:
- CPU 架构:x86_64 ↔ ARM64
- 操作系统:Linux ↔ 鸿蒙
- C 标准库:glibc ↔ musl
- 编译器:gcc ↔ clang
我不需要懂这些底层细节,只要写好配方,框架按下面这条生命周期跑:
prepare() → build() → check() → package() → archive()

第一步:搭骨架(先抄官方模板)
不要从零手敲,直接拿官方模板改。模板顶部是一堆元信息变量,中间是几个空函数。我先把元信息填了:
pkgname=mediainfo
pkgver=25.03
pkgrel=0
pkgdesc="A unified display of technical and tag data for video/audio files (CLI)"
url="https://github.com/MediaArea/MediaInfo"
archs=("armeabi-v7a" "arm64-v8a")
license=("BSD-2-Clause")
depends=() # 运行时依赖,这里没有
makedepends=("cmake") # 编译期工具
这一步纯粹是「填表」,没什么难度,但 license、pkgdesc 这些是合规和检索要用的,别偷懒留空。
第二步:决定源码从哪来
官方模板默认是「远程下载 + 自动解压」。但我这次源码是本地准备好的(放在 Projects/MediaInfo),所以要关掉自动下载:
autounpack=false
downloadpackage=false
srcpath="${LYCIUM_ROOT}/../Projects/MediaInfo"
builddir=${pkgname}-${pkgver}
这个选择会直接影响 prepare() 的写法——既然不自动下载,那源码的「就位」就得我自己在 prepare 里手动做。
第三步:一个函数一个函数地填
我把「官方模板 → MediaInfo 实际版本」每个函数多了什么、为什么多,整理成了对照笔记。这比单纯贴最终代码有用得多。
prepare():从 2 行膨胀到十几行
模板里它几乎是空的。我的版本要做四件事:
- 建构建目录、把本地源码
cp进去(替代自动下载解压); - 删
.bak备份文件; - 删 Windows 残留的
:Zone.Identifier文件; - 打 musl 补丁。
prepare() {
if [ -d "$srcpath" ]; then
mkdir -p "$builddir"
cp -rf "$srcpath"/* "$builddir/"
find "$builddir" -name "*.bak" -delete 2>/dev/null || true
find "$builddir" -name "*:Zone.Identifier" -delete 2>/dev/null || true
if [ -f "../mediainfo-zenlib-musl.patch" ]; then
cd "$builddir"; patch -p1 < "../mediainfo-zenlib-musl.patch"; cd "$OLDPWD"
fi
else
echo "ERROR: Source not found at $srcpath"; exit 1
fi
}
我特意保留了最后的 else exit 1——源码不在就尽早报错,比让后面编译抛一堆莫名其妙的错强。
build():关键是 -S 和那几个开关
模板里的 build() 假设 CMakeLists.txt 在源码根目录。但 MediaInfo 的在 Project/CMake/CLI/ 子目录,必须用 -S 指过去。另外要把依赖库的构建开关打开:
build() {
cd "$builddir"
cmake "$@" \
-B"$ARCH-build" \
-S./Project/CMake/CLI/ \
-D CMAKE_BUILD_TYPE=Release \
-D CMAKE_INSTALL_PREFIX="/usr" \
-D BUILD_ZENLIB=ON \
-D BUILD_MEDIAINFOLIB=ON \
-D BUILD_ZLIB=ON \
-D ZLIB_BUILD_SHARED=OFF \
-D MediaInfoLib_BUILD_STATIC=ON
make -j4 -C "$ARCH-build"
ret=$?
cd "$OLDPWD"
return $ret
}
我的理解:BUILD_ZENLIB=ON 这类是让 CMake 顺手把依赖一起编了,省去单独适配每个依赖的麻烦;*_BUILD_STATIC=ON 则是把依赖编成静态库打进主程序,产物更独立、运行时不缺 .so。
package():别忘了 DESTDIR
模板的 make install 会装到系统目录,那不是我们要的。加 DESTDIR 把产物收到框架约定的位置:
package() {
cd "$builddir"
make -C "$ARCH-build" install DESTDIR="${LYCIUM_ROOT}/usr/${pkgname}/${ARCH}"
cd "$OLDPWD"
}
check() 和 archive()
check() 我没改——交叉编译出来的 arm64 产物没法在 x86 构建机上跑,所以这里就是个占位,提示「请到鸿蒙设备上测」。
archive() 模板里没有,是我按需补的,作用是生成 tar.gz 和调用 hnpcli 打 .hnp 包。
我的总结:模板是骨架,调研是肌肉
把模板和实际版本一对比,结论很清楚:官方模板只是最小骨架,真正决定成败的是你对目标库的调研。MediaInfo 这次的「增量」其实就四类:
- 本地源码处理(srcpath + cp + 关闭自动下载);
- musl 兼容补丁;
- 项目特有的 CMake 选项(
-S子目录 + 依赖开关); - 产物打包(archive 生成 tar.gz / hnp)。
我自己的体会是:写不出 HPKBUILD,几乎总是因为「还没搞清楚这个库怎么编、依赖啥」。前期花时间读它的 CMakeLists.txt、跑通它在 Linux 上的原生编译,HPKBUILD 自然就水到渠成了。
小结
这一篇把系列里反复出现的 HPKBUILD「揭开盖子」讲了一遍。掌握了「填元信息 → 定源码来源 → 逐函数填充 → 对照模板查缺」这套方法,再去写别的库的配方就有章可循了。
下一篇回到 libplacebo 本体,聊聊它作为 Meson 构建系统的库,交叉编译时和 CMake 类项目有什么不一样。感谢 wei_shuo 的开源分享。
更多推荐





所有评论(0)