鸿蒙三方库适配读懂 `HPKBUILD`:lycium 怎么知道「下载谁、怎么编、装到哪」?

鸿蒙三方库适配读懂 HPKBUILD:lycium 怎么知道「下载谁、怎么编、装到哪」?

欢迎大家加入开源鸿蒙跨平台开发者社区

前言

在 OpenHarmony 三方库 lycium 体系里,每个库目录下会有一个 HPKBUILD 文件。你可以把它理解成 「构建说明书」 :用 Shell 变量 描述 包是谁、版本多少、从哪下载 ,再用若干个 函数 描述 解压后要改什么、怎么交叉编译、产物拷贝到哪、要不要打 HNP 包。

本文件由 lycium/script/build_hpk.sh 通过 source HPKBUILD 读入并调用其中的函数;你在 lycium 根目录 执行 ./build.sh AES 时,脚本会进入 thirdparty/AES (或你工程里对应路径),在该目录下 source 本 HPKBUILD 并执行 build_hpk.sh 里的主流程。

本文在 变量(字段) 、各函数职责 之外,补充:脚本真实调用顺序 、传入 build() 的 CMake 参数从哪来 、常见目录长什么样 、排错与升级时要改哪些地方 ,方便对照仓库里的 HPKBUILD 原文 阅读。


工作目录与路径约定(读脚本前先建立空间感)

概念 本仓库典型值 说明
库根目录(PKGBUILD_ROOT) .../thirdparty/AES build_hpk.sh 所在目录;PWD 在执行 prepare/build/package 的多数时刻会 cd 到 builddir 再返回,但 archive() 里复制 hnp.json 用的是 ${PWD}/hnp.json ,要求 在库根执行(与 lycium 设计一致)。
LYCIUM_ROOT .../lycium lycium/build.sh 里导出;安装产物 在 $LYCIUM_ROOT/usr/AES/<ARCH>/ ,archive 输出 在 $LYCIUM_ROOT/output/<ARCH>/。
builddir tiny-AES-c-1.0.0 与 packagename 解压结果一致,位于 库根下 (与 HPKBUILD 同级)。
CMake 构建目录 tiny-AES-c-1.0.0/arm64-v8a-build -B"$ARCH-build" 相对 源码根 ;HPKCHECK 必须 cd "${builddir}/${ARCH}-build",与此严格一致。

引号习惯: builddir 含连字符 ,凡 cd、rm -rf、路径拼接 建议写 "$builddir" 、"${PWD}/$builddir",避免被 shell 拆成多个词(社区 HPK 规范里这是常见坑)。


上半部分:变量(字段)一览

下面这些不是 JSON 字段,而是 Bash 变量 ,供 build_hpk.sh 使用。

变量名 本仓库取值 通俗含义
pkgname AES 包 / 库在 lycium 里的名字 ,必须与 thirdparty/ 下文件夹名 一致,否则 ./build.sh AES 找不到。同时决定安装根路径 $LYCIUM_ROOT/usr/AES/。
pkgver 1.0.0 上游源码版本号 ,与 tag v1.0.0 、builddir、packagename、hnp.json 的 version 等应对齐。
pkgrel 0 适配脚本发布号(第几次打 HPK 包),与上游版本独立;只改适配脚本未改上游时,通常会递增它。
pkgdesc 英文短描述 一句话说明这个包是干什么的,给人读和维护用。
url GitHub 上游地址 上游主页,溯源、文档链接用。
archs armeabi-v7a、arm64-v8a 要编哪些 CPU 架构 ;数组里 每个架构 都会完整跑一遍 prepare → build → package → archive(若有)→ check(若开启)。
license Unlicense 上游许可证 (tiny-AES-c);本仓库另有 MIT 的适配文件,见 LICENSE / README.OpenSource。
depends 空数组 运行时依赖的其他 HPK 包名 (目录名)。本库无。若有依赖,./build.sh A B 里 要先写被依赖的 B ,否则 A 会因 builddepends 返回 101 而推迟构建。
makedepends 空数组 本机构建前要用到的可执行命令名 (如 python3);脚本会对每个元素 which,找不到就退出。本库依赖 cmake/make 由 lycium 全局检查,此处可空。
source codeload 的 tar.gz URL 源码下载地址 ;用 ${pkgver} 拼出版本。codeload.github.com 在 macOS wget 下往往比 github.com/.../archive/refs/tags/... 更稳。
downloadpackage true 是否自动下载 packagename ;设为 false 时需自行把源码放到约定位置并在 prepare 里处理。
autounpack true 是否自动解压 ;false 时在 prepare 里自己 tar/unzip。
buildtools cmake 构建方式 。为 cmake (或空,默认 cmake)时,build_hpk.sh 在 build 前 调用 cmakedependpath $ARCH ,拼出传给 build "$@" 的 buildargs。
builddir tiny-AES-c-${pkgver} 解压后的源码根目录名 ;含连字符 ,cd 务必加引号。
packagename ${builddir}.tar.gz 磁盘上的源码压缩包文件名 ;wget -O 的目标名,且应与 SHA512SUM 第二列一致。

第一行注释 # Maintainer: ... 仅说明维护关系,不参与逻辑。


SHA512SUM 与下载:和 HPKBUILD 怎么配合?

build_hpk.sh 在 download $source $packagename 之后:若库目录下存在 SHA512SUM 文件,会执行 sha512sum -c SHA512SUM。

  • 作用 :防止下载损坏或被劫持的 tarball,与 source URL 变更后内容是否仍一致。
  • 你要做的 :更换 pkgver / source / packagename 后,用新包算一遍 SHA512 ,更新 SHA512SUM 里对应行。
  • 校验失败 :脚本会提示失败并退出,不会自动删包,方便你比对后决定是重下还是修正哈希。

下载日志在库根 download.log (wget 的 -o 输出),体积异常或 404 时可打开查看。


build_hpk.sh 里真实发生的事(按时间顺序)

下面与 lycium/script/build_hpk.sh 中 main → cleanhpk → builpackage 逻辑对应,便于你把 变量 和 函数 对上号。
否 exit 101
是
是
否
是
否
是
否
cleanhpk: cleanbuild + 可选删坏包
builpackage: builddepends 检查 depends
依赖齐全?
写入待编译依赖列表
download source -> packagename
存在 SHA512SUM?
sha512sum -c
unpack packagename
for arch in archs
ARCH=arch 设置 buildlog
prepare
cmakedependpath 拼 buildargs
build buildargs
package
定义了 archive?
archive
跳过
LYCIUM_BUILD_CHECK=true?
check
跳过 check
recordbuildlibs

要点摘要:

  1. cleanbuild() 会先删掉 $builddir 和 $packagename,保证本次是干净树(若你本地想保留已下载的 tar,需知每次 full build 会清掉,与 lycium 一致)。
  2. depends :在 builpackage 入口 用 builddepends 与「已编译列表」比对;缺依赖时 exit 101 ,不会进入 prepare。
  3. prepare 在每个 arch 循环里都执行一次 :本库 prepare 幂等 (整文件覆盖 CMakeLists.txt ),重复执行不会叠加坏内容;若某库用 cat >> 追加 CMake,则要自己 grep -q 做幂等(别的库的坑,此处顺带提醒)。
  4. build $buildargs :这里的 $buildargs 来自 cmakedependpath ,不是 HPKBUILD 里手写的 ;HPKBUILD 的 build() 里用 "$@" 接住。
  5. declare -F archive :只有 HPKBUILD 里定义了 archive 函数 才会调用;本仓库 有。
  6. check :仅当 LYCIUM_BUILD_CHECK 为 true 时执行;在 Darwin 上 lycium/build.sh 常把 LYCIUM_BUILD_CHECK 设为 false ,则 不会跑 check() ,这是环境行为,不是 HPKBUILD 写错。
  7. recordbuildlibs :往 $LYCIUM_ROOT/usr/hpk_build.csv 记一笔,供依赖解析与跳过已构建使用。

传给 build() 的 CMake 参数(cmakedependpath 摘要)

buildtools="cmake" 时,cmakedependpath $ARCH 会构造 buildargs,核心包括(具体以你 SDK 路径为准):

片段 作用
-DCMAKE_TOOLCHAIN_FILE=${OHOS_SDK}/native/build/cmake/ohos.toolchain.cmake 指定 OHOS 交叉编译工具链。
-DCMAKE_INSTALL_PREFIX=$LYCIUM_ROOT/usr/$pkgname/$ARCH/ CMake 语义上的安装前缀;本库 package() 仍 手动 cp ,与此前缀 对齐同一套目录结构。
-G "Unix Makefiles" 生成 Makefile ,后续 $MAKE -C $ARCH-build。
-DOHOS_ARCH=$ARCH 目标架构,与 armeabi-v7a / arm64-v8a 对应。
-DCMAKE_BUILD_TYPE=Release 等 Release、跳过 RPATH 等,减少设备上多余依赖。

本库 depends=() ,因此 不会 追加 -DCMAKE_FIND_ROOT_PATH=... (有依赖时才会把其它库的 usr/<dep>/$ARCH 拼进搜索路径)。

build() 里 又额外传入 -B"$ARCH-build" -S. ,与 buildargs 合并后交给 ${OHOS_SDK}/native/build-tools/cmake/bin/cmake ,并把 stdout/stderr 追加到 buildlog。


关键函数是干什么的?

prepare():解压后、编译前的「准备工作」

什么时候调? archs 循环里,每个 ARCH 在 build() 之前都会执行(见上一节流程图)。

本库做了两件事:

  1. 统一换行符

    对 aes.c、aes.h、test.c 做 sed 's/\r$//' ,去掉可能的 Windows CRLF 。在 HPK 实践里,CRLF 会导致 source HPKBUILD 报错 、prepare 里 heredoc 异常 或 编译器解析奇怪,属于高频坑。

  2. 重写 CMakeLists.txt (cat <<'EOF')

    • 上游 v1.0.0 自带 CMake 将 target_include_directories 指到不存在的 tiny-AES-c/ 子目录,交叉编译会 找不到 aes.h。
    • 本适配直接写入完整 CMake,实现:静态库 tiny-aes(libtiny-aes.a) 、tiny_aes_test 、CTest 用例名 tiny_aes_upstream_tests 、以及与标准布局一致的 install(...) (与 package() 手动拷贝 语义对齐)。

为何用单引号 heredoc <<'EOF'? 防止 shell 提前展开 ${CMAKE_CURRENT_SOURCE_DIR} 等,应原样交给 CMake。

最后 cd "$OLDPWD" 回到进入 prepare 前的目录(库根)。


build():用 OHOS 工具链跑 CMake + Make

  1. cd "$builddir"。
  2. cmake ... "$@" -B"$ARCH-build" -S. >> "$buildlog" 2>&1。
  3. 失败则 return ;成功则 $MAKE -C "$ARCH-build" ,同样追加到 buildlog。
  4. cd "$OLDPWD" ,返回 make 退出码。

buildlog 文件名 形如 AES-1.0.0-arm64-v8a-lycium_build.log ,在 库根 ;cmake 详细报错、未找到编译器、链接失败等 优先打开此文件。


package():把编好的东西摆到 lycium 标准「安装树」

在 $builddir 下执行:

目标路径 内容
$LYCIUM_ROOT/usr/AES/$ARCH/lib/ libtiny-aes.a
.../include/ aes.h
.../bin/ tiny_aes_test(若生成)

应用链接:-I$LYCIUM_ROOT/usr/AES/$ARCH/include -L.../lib -ltiny-aes (静态库目标名为 tiny-aes ,产物文件 libtiny-aes.a)。


archive():打发布包 + 可选 HNP

  1. mkdir -p "${LYCIUM_ROOT}/output/$ARCH"。
  2. cp "${PWD}/hnp.json" → usr/AES/$ARCH/ (与 lib 同级)。
  3. 在 usr/AES/$ARCH 内 tar -zvcf .../${pkgname}_${pkgver}.tar.gz * ,即 AES_1.0.0.tar.gz ,落在 lycium/output/$ARCH/。
  4. hnpcli pack :若可执行则调用;否则 写 buildlog ,不使整次构建失败。

注意: output 路径相对 LYCIUM_ROOT(lycium 根) ;若你在 独立 git 仓库 thirdparty/AES 里另外维护 output/ 拷贝,属于 发布策略 ,与 lycium 默认 lycium/output 不是同一路径,文档里不要混为一谈。


check():仅提示,不跑测试

打印说明:交叉编译出的测试二进制不能在宿主机上跑 ;设备上 ctest / ./tiny_aes_test 。
HPKCHECK + test.sh 才是设备侧自动化入口。


cleanbuild():清理,方便下次干净构建

rm -rf "${PWD}/$builddir" 、rm -f "${PWD}/$packagename" 。
cleanhpk 还会在校验失败时 删掉坏的 packagename (见 build_hpk.sh ),与 cleanbuild 略有叠加,都是为 可重复构建 服务。


上游 CMake 与本适配的差异(一眼对照)

项目 上游 tiny-AES-c v1.0.0(节选问题) 本 prepare() 写入的 CMake
include 路径 PRIVATE tiny-AES-c/(解压后不存在) PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
库类型 / 测试 仅 add_library,无测试目标 STATIC + tiny_aes_test + CTest
安装 无完整 install 语义 install(TARGETS/FILES ...) 与 package() 对齐

构建成功后,目录「长什么样」(示意)

库根 thirdparty/AES(节选):

text 复制代码
thirdparty/AES/
├── HPKBUILD
├── SHA512SUM
├── tiny-AES-c-1.0.0.tar.gz          # cleanbuild 后可能不存在,需重新下载
├── tiny-AES-c-1.0.0/
│   ├── aes.c, aes.h, test.c
│   ├── CMakeLists.txt               # 已被 prepare 覆盖
│   ├── arm64-v8a-build/             # cmake + make 产物
│   │   ├── libtiny-aes.a
│   │   ├── tiny_aes_test
│   │   └── ...
│   └── armeabi-v7a-build/
└── AES-1.0.0-arm64-v8a-lycium_build.log

lycium 安装树(节选):

text 复制代码
lycium/usr/AES/arm64-v8a/
├── bin/tiny_aes_test
├── include/aes.h
├── lib/libtiny-aes.a
└── hnp.json                         # archive 前复制进来

排错速查(和 HPKBUILD 强相关)

现象 建议排查
ERROR during : download download.log 、网络、URL;可改 source 为 codeload(本库已用)。
SHA512SUM 校验失败 下载包是否更新、SHA512SUM 是否与新包一致。
cmake 报找不到编译器 / sysroot OHOS_SDK 是否设置、SDK 是否完整。
prepare / source HPKBUILD 奇怪语法错误 CRLF :对 HPKBUILD 本身 也应用 LF(本技能常见要求)。
pack: command not found(旧问题) archive 里应对 hnpcli 做 -x 判断(本仓库已处理)。
设备上 ctest 找不到目录 HPKCHECK 必须 cd "${builddir}/${ARCH}-build" ,与 -B"$ARCH-build" 一致。

库根 last_error 文件在 sure 失败时由 build_hpk.sh 写入一行错误信息,可与 buildlog 对照。


升级上游或改架构时:建议核对清单

  • pkgver 、source 中的版本片段、builddir 、packagename 一致。
  • SHA512SUM 已用新 tarball 更新。
  • hnp.json 的 version 、README.OpenSource 的 Version Number、文档中的版本号。
  • archs 增删后,HPKCHECK 的 cd 仍指向 ${builddir}/${ARCH}-build (若你改成嵌套 $builddir/ohos_build/${ARCH}-build 等,两边必须一起改)。
  • 上游 test.c / aes.c 文件名变更 时,prepare 里 CRLF 列表 与 CMake add_library 源文件 同步。

内嵌的 CMake 片段(在 prepare 里)在说什么?

  • add_library(tiny-aes STATIC aes.c):单文件静态库。
  • target_include_directories(... PUBLIC ...):对外暴露头文件路径,修正上游错误。
  • tiny_aes_test :链接 tiny-aes,跑上游自测。
  • enable_testing + add_test :注册 CTest ,与 HPKCHECK 中 ctest 对应。
  • install(...) :与 package() 的 lib/include/bin 布局一致,便于以后若改为 cmake --install 时少改脚本。

总结

  • HPKBUILD = 变量(谁、版本、从哪下、编哪些架构、依赖谁) + 函数(准备、编译、安装、打包、提示、清理) ;真正 下载/校验/多架构循环 在 build_hpk.sh 里,HPKBUILD 只声明「做什么」。
  • build() 的 "$@" 来自 cmakedependpath ,核心是指定 OHOS toolchain、安装前缀、OHOS_ARCH ;本库 无 depends ,故无 CMAKE_FIND_ROOT_PATH 拼接。
  • prepare 解决 CRLF + 上游 CMake 路径错误 ,并打通 CTest ;package 把产物落到 usr/AES/$ARCH ;archive 做 tar + 可选 HNP。
  • 排错优先看 库根 *-lycium_build.log 、download.log、last_error ;升级时 版本号与 SHA512SUM、hnp.json、OpenSource 一并改。

更偏「流程叙述」的图文可继续阅读仓库内 鸿蒙PC tiny-AES-c三方库适配实践.md。


相关文档

相关推荐
_upupup6 小时前
Linux的调试工具——gdb/cgdb
linux·服务器
Android系统攻城狮10 小时前
Linux Gstreamer深度解析之gst_audio_sink_get_type调用流程与实战(六十五)
linux·运维·服务器·音视频·gstreamer音视频·音视频进阶·gstreamer音视频进阶
程序猿追11 小时前
HarmonyOS 6 上做个极简浏览器:Web 组件 + 前进后退 + 加载进度
前端·华为·harmonyos
程序猿追11 小时前
HarmonyOS 6 音视频实战:用 AVPlayer 做一个本地音乐播放器
华为·音视频·harmonyos
威哥爱编程11 小时前
HarmonyOS 7 多设备 UX 自动检测实战:AppAnalyzer 多设备体检 + 一多工程底线,提前拦截截断重叠大图大字
harmonyos
威哥爱编程11 小时前
HarmonyOS 7 安全相机 2.0 实战:数字内容溯源,为拍摄内容提供来源保护
harmonyos
威哥爱编程11 小时前
HarmonyOS 7 弱网优化实战:Network Boost Kit 场景加速 + QUIC 长连接 + 弱网直播优化
harmonyos
威哥爱编程11 小时前
HarmonyOS 7 应用故障智能诊断实战:APMS 故障总览 + Profiler 跨语言泄漏 + Operation Analyzer 冻屏分析
harmonyos
zyseo811 小时前
谷歌SEO 站内搜索优化实战:把站内搜索词变成关键词金矿
java·服务器·数据库
暖风熏人醉11 小时前
Expo 鸿蒙双 SDK 时代:我把适配鸿蒙做成了工程
harmonyos