【鸿蒙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 编写完成后,执行构建命令:

shell 复制代码
cd lycium
./build.sh mylib

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

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

1.2 构建流程全解析

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

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

shell 复制代码
# 查看构建日志(快速定位错误)
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 triple clang 不认识架构 检查 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 found OHOS SDK 路径未配置 使用 SDK 自带的 cmake ${OHOS_SDK}/native/build-tools/cmake/bin/cmake
wget: command not found 缺少 wget apt install wget
sha512sum: command not found 缺少校验工具 Linux: apt install coreutils,macOS: brew install coreutils

2.4 日志调试技巧

shell 复制代码
# 实时查看构建输出(不等待构建完成)
./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 手动指定多库构建

shell 复制代码
# 同时构建多个库
./build.sh libA libB libC

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

3.3 依赖构建的注意事项

  1. 依赖顺序不重要:框架会自动按拓扑排序,先构建被依赖的库
  2. 共享依赖:多个库依赖同一个库时,只构建一次
  3. 循环依赖:A 依赖 B、B 依赖 A 会导致死循环,需要检查依赖设计
  4. 架构超集规则 :被依赖库的 archs 必须是当前库 archs超集
bash 复制代码
# 正确: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-config lycium/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 产物验证

shell 复制代码
# 检查产物结构
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 集成示例

cmake 复制代码
# 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 集成方式

cmake 复制代码
# 使用 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 编写建议

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

markdown 复制代码
# 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 三者之间的交互关系,并总结各环节的角色职责。

相关推荐
SHARK_pssm5 小时前
【数据结构——复杂度】
c语言·数据结构·经验分享·笔记
Hello:CodeWorld5 小时前
μC/OS vs FreeRTOS:嵌入式实时操作系统深度对比
c语言·开发语言·单片机
xmdy58666 小时前
Flutter+开源鸿蒙实战|企业级工具APP Day2 全局网络封装与 Dio 拦截器实战(鸿蒙兼容版)
flutter·开源·harmonyos
xmdy58666 小时前
Flutter+开源鸿蒙实战:企业级工具类APP开发教程(含第三方库适配)
flutter·开源·harmonyos
努力努力再努力wz6 小时前
【Qt入门系列】深入理解信号与槽:从事件响应到自定义信号机制
c语言·开发语言·数据结构·数据库·c++·qt·mysql
Sakuyu434686 小时前
C语言基础--基本数据类型
c语言·开发语言
萧戈6 小时前
C/C++ 运行时库概念详解
c语言·c++
richard_yuu6 小时前
鸿蒙Stage模型实战|心晴驿站分层架构与隐私安全设计
安全·架构·harmonyos
Byte Wizard7 小时前
C语言指针深入浅出5
c语言·开发语言
Swift社区7 小时前
Flutter / React / ArkUI:在鸿蒙 PC 上怎么选?
flutter·react.js·harmonyos