【鸿蒙PC三方库移植适配框架解读系列】第四篇:构建执行、产物获取与 HAP 集成

系列导读:本文是 Lycium 适配系列的第四篇,介绍 HPKBUILD 编写完成后如何执行构建、分析构建日志、处理多依赖递归编译、获取产物并进行 HAP 集成。


欢迎加入【开源鸿蒙PC社区】,一起共建鸿蒙化C/C++三方库生态。

前言

项目说明
macOS环境配置https://bxming.blog.csdn.net/article/details/159284830
Ubuntu环境配置(或者windows + wsl)https://bxming.blog.csdn.net /article/details/159284760
lycium框架https://atomgit.com/OpenHarmonyPCDeveloper/lycium_plusplus.git
应用平台HarmonyOS PC

系列索引

篇章标题内容
第一篇概述与环境配置Lycium 概念、构建机要求、OHOS SDK 配置
第二篇项目结构与适配目录创建目录结构、community vs thirdparty、创建适配目录
第三篇HPKBUILD 编写详解元数据字段、过程函数、三种构建系统写法
第四篇构建执行与产物获取构建流程、日志分析、多库递归、HAP 集成
第五篇流程图与角色职责完整流程图、各角色职责、协作时序
第六篇关键注意事项与最佳实践依赖管理、架构超集、日志调试、外部适配仓
第七篇快速参考与模板入门步骤、模板、完整案例、检查清单

1. 构建执行

1.1 启动构建

HPKBUILD 编写完成后,执行构建命令:

cd lycium
./build.sh mylib

框架将自动完成以下工作:

  1. 加载交叉编译环境(envset.sh
  2. 解析依赖关系
  3. 下载源码、校验完整性、解压
  4. 为每个架构循环执行 prepare()build()package()
  5. 记录构建结果

1.2 构建流程全解析

build_hpk.shbuilpackage() 函数的完整执行序列

步骤函数/组件角色与具体工作
1cleanhpk()清理上次构建 — 删除旧的构建目录、校验已缓存的源码包(校验失败则删除)
2builddepends()依赖解析 — 读取 depends[],检查每个依赖库是否已在 usr/ 下构建完成(通过 hpk_build.csv 记录);若未就绪则退出码 101,触发外层递归构建
3checkmakedepends()工具检测 — 检查 makedepends[] 声明的命令是否存在(which),缺失则报错退出
4download()源码下载 — 若 downloadpackage != false,用 wget $source -O $packagename 下载源码
5checksum()完整性校验 — 若存在 SHA512SUM 文件,运行 sha512sum -c SHA512SUM,失败则退出
6unpack()解压 — 若 autounpack != false,自动识别 tar.gz / tgz / tar.xz / tar.bz2 / zip 格式解压
7for arch in ${archs[@]}多架构循环 — 为每个声明的架构顺序执行以下全部子步骤
7.1prepare()预处理 — 创建编译目录、打 patch、设置软链接等
7.2cmakedependpath() / configuredependpath()依赖路径注入 — 计算 $buildargs$pkgconfigpath
7.3build()编译 — 调用 HPKBUILD 中定义的 build() 函数
7.4package()安装 — 调用 HPKBUILD 中定义的 package() 函数
7.5archive()(可选)归档 — 将产物打包为 output/<arch>/<pkgname>_<ver>.tar.gz,或执行 HNP 打包
7.6install_local()(可选)本地安装 — 鸿蒙本机构建时安装到本地系统路径
7.7check()(可选)测试 — 记录测试方法(如果 LYCIUM_BUILD_CHECK=true
7.8recoverpkgbuildenv()(可选)环境还原 — 清理 prepare() 中设置的临时环境变量
7.9recordbuildlibs()记录构建结果 — 将 <arch>,<pkgname>,<ver> 写入 usr/hpk_build.csv

2. 构建日志分析

2.1 日志位置

每个架构生成独立的构建日志。日志文件的默认位置与 HPKBUILD 所在目录对应:

# 如果 HPKBUILD 在 thirdparty/mylib/ 下
thirdparty/mylib/mylib-1.0.0-arm64-v8a-lycium_build.log

# 如果 HPKBUILD 在 community/mylib/ 下
community/mylib/mylib-1.0.0-arm64-v8a-lycium_build.log

格式:<pkgname>-<pkgver>-<arch>-lycium_build.log

同时框架还会在 lycium/script/ 下生成一份日志归档副本,方便集中查看。

2.2 日志内容

日志包含 build() 中通过 >$buildlog 2>&1 重定向的所有输出。典型内容:

# 查看构建日志(快速定位错误)
tail -100 thirdparty/mylib/mylib-1.0.0-arm64-v8a-lycium_build.log

# 搜索报错关键字
grep -i "error\|failed\|undefined reference" thirdparty/mylib/*.log

2.3 常见构建失败排查

错误模式根因解决方案
undefined reference to 'xxx'缺少依赖库或链接参数检查 depends[] 是否完整,或 LDFLAGS 中缺少 -lxxx
cannot find -lxxx链接器找不到依赖库检查依赖库是否已构建,$buildargs 中的 CMAKE_FIND_ROOT_PATH 是否正确
unknown target tripleclang 不认识架构检查 envset.sh 中的 ARCH_TRIPLE 设置,或 archs[] 值拼写错误
fatal error: 'xxx.h' file not found缺少头文件依赖库的头文件未安装到 usr/<dep>/<arch>/include/;或 include_directories 未正确设置
checking for xxx... no(configure 项目)configure 检测失败检查 PKG_CONFIG_PATH 设置,或 --with-xxx 参数
cmake: not foundOHOS SDK 路径未配置使用 SDK 自带的 cmake ${OHOS_SDK}/native/build-tools/cmake/bin/cmake
wget: command not found缺少 wgetapt install wget
sha512sum: command not found缺少校验工具Linux: apt install coreutils,macOS: brew install coreutils

2.4 日志调试技巧

# 实时查看构建输出(不等待构建完成)
./build.sh mylib 2>&1 | tee build.log

# 只查看错误行
grep -E "^(.*error:|.*Error |make:.*\*\*\*)" script/mylib-*.log

# 对比不同架构的日志
diff script/mylib-1.0.0-arm64-v8a-lycium_build.log \
     script/mylib-1.0.0-armeabi-v7a-lycium_build.log | less

# 查看构建记录
cat usr/hpk_build.csv

3. 多库递归构建

3.1 依赖传递机制

当构建的库有依赖(depends 非空)时,框架的依赖处理流程:

./build.sh libA
  → builddepends() 读取 libA/depends=("libB")
  → 检查 libB 是否已构建(查 hpk_build.csv)
  → 未构建 → 退出码 101
  → ./build.sh 捕获退出码 101
  → 将 libB 加入 LYCIUM_DEPEND_PKGNAMES
  → ./build.sh libA libB   # 先构建 libB,待就绪后构建 libA
  → 递归直到所有依赖就绪

3.2 手动指定多库构建

# 同时构建多个库
./build.sh libA libB libC

# 先构建依赖库,再构建目标库
./build.sh libB libC libA

3.3 依赖构建的注意事项

  1. 依赖顺序不重要:框架会自动按拓扑排序,先构建被依赖的库
  2. 共享依赖:多个库依赖同一个库时,只构建一次
  3. 循环依赖:A 依赖 B、B 依赖 A 会导致死循环,需要检查依赖设计
  4. 架构超集规则:被依赖库的 archs 必须是当前库 archs超集
# 正确:libA 依赖 libB,libB 的 archs 覆盖 libA
# libA/HPKBUILD
archs=("arm64-v8a")
depends=("libB")

# libB/HPKBUILD
archs=("armeabi-v7a" "arm64-v8a")  # ✓ 超集,覆盖 arm64-v8a

4. 产物获取

4.1 产物分布

构建完成后,产物分布在以下位置:

产物类型路径说明
头文件 (.h)lycium/usr/<pkgname>/<arch>/include/API 头文件,供 HAP 工程引用
动态库 (.so)lycium/usr/<pkgname>/<arch>/lib/运行时链接库
静态库 (.a)lycium/usr/<pkgname>/<arch>/lib/静态链接库
pkg-configlycium/usr/<pkgname>/<arch>/lib/pkgconfig/.pc 依赖配置文件
可执行文件lycium/usr/<pkgname>/<arch>/bin/工具或测试程序
归档包lycium/output/<arch>/<pkgname>_<ver>.tar.gz全部产物的 tar 压缩包
HNP 包lycium/output/<arch>/<pkgname>.hnp鸿蒙 Native Package
构建记录lycium/usr/hpk_build.csv所有已构建库的清单
构建日志lycium/script/<pkgname>-<ver>-<arch>-lycium_build.log调试用详细日志

4.2 产物验证

# 检查产物结构
ls -la lycium/usr/mylib/arm64-v8a/
# 输出:
# drwxr-xr-x  include/
# drwxr-xr-x  lib/
#   ├── libmylib.so
#   ├── libmylib.a
#   └── pkgconfig/
#       └── mylib.pc

# 查看库文件信息(确认架构正确)
file lycium/usr/mylib/arm64-v8a/lib/libmylib.so
# 输出:ELF 64-bit LSB shared object, ARM aarch64, ...

# 查看导出的符号
llvm-nm -D lycium/usr/mylib/arm64-v8a/lib/libmylib.so | head -20

4.3 产物获取流程

构建完成

产物类型

动态库/静态库

头文件

pkg-config文件

HNP包

复制到 HAP 工程

验证链接参数

直接集成到 HAP


5. HAP 集成

5.1 集成步骤

应用开发者从 usr/ 获取产物后,集成到 HAP 工程:

步骤操作负责方
5.1.so / .a 及头文件复制到 HAP 工程目录应用开发者
5.2在 HAP 工程的 CMakeLists.txt 中配置 target_link_libraries应用开发者
5.3在 HAP 工程中 #include 相应的头文件应用开发者
5.4参考 docs/hap_integrate.md 验证集成正确性应用开发者

5.2 CMakeLists.txt 集成示例

# HAP 工程 CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(MyApp)

# 指定第三方库路径
set(MYLIB_PATH ${CMAKE_CURRENT_SOURCE_DIR}/libs/mylib)

# 添加头文件搜索路径
include_directories(${MYLIB_PATH}/include)

# 添加库文件搜索路径
link_directories(${MYLIB_PATH}/lib)

# 链接库
add_library(myapp SHARED src/main.cpp)
target_link_libraries(myapp mylib)  # 链接 libmylib.so

更规范的 HAP 集成方式

# 使用 target_include_directories 和 target_link_libraries
add_library(myapp SHARED src/main.cpp)

# 直接指定绝对路径(开发阶段)
target_include_directories(myapp PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/libs/mylib/arm64-v8a/include
)
target_link_directories(myapp PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/libs/mylib/arm64-v8a/lib
)
target_link_libraries(myapp PRIVATE
    mylib
    c
    log  # OHOS 日志库
)

5.3 HNP 集成

如果库提供了 HNP 包(output/<arch>/<pkgname>.hnp),集成更简单:

  1. .hnp 文件放入 HAP 工程的 libs/ 目录
  2. build-profile.json5 中配置 native 库路径
  3. 构建工具会自动解包 HNP 并链接

5.4 hap_integrate.md 编写建议

作为适配者,为应用开发者提供清晰的集成文档:

# mylib HAP 集成指南

## 产物文件
- libmylib.so(arm64-v8a / armeabi-v7a)
- include/mylib.h

## 集成步骤
1. 将对应架构的 libmylib.so 复制到 `entry/libs/<arch>/`
2. 将 include/mylib.h 复制到 `entry/src/main/cpp/include/`
3. 在 CMakeLists.txt 中添加:
   ```cmake
   target_link_libraries(entry PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/libs/${OHOS_ARCH}/libmylib.so)

API 说明

  • mylib_init()
  • mylib_process()
  • mylib_cleanup()

6. 本机构建(DevBox)

当在 OpenHarmony 设备(DevBox)上直接构建时,使用 build_local.sh

./build_local.sh mylib

该脚本的特点:

  • 自动识别操作系统为 HarmonyOS
  • 设置 TARGET_HARMONYOS=true
  • 仅构建 arm64-v8a 架构(其他架构自动跳过)
  • 产物安装到设备本地系统路径(而不是 usr/ 目录)

下篇预告

了解了构建流程和产物获取后,下一篇将用一张完整的流程图展示适配者、Lycium 框架和 OHOS SDK 三者之间的交互关系,并总结各环节的角色职责。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值