【鸿蒙 PC三方库构建系统】解决 OpenHarmony SHA 库编译问题:从动态链接错误到静态链接优化
【鸿蒙 PC三方库构建系统】解决 OpenHarmony SHA 库编译问题:从动态链接错误到静态链接优化
欢迎大家加入开源鸿蒙PC社区
项目地址:https://atomgit.com/oh-tpc/pc_sha
问题背景
在 OpenHarmony 平台上编译 SHA 加密库时,遇到了一个典型的动态链接错误。这个问题不仅影响了库的正常编译,还导致生成的可执行文件无法在设备上运行。本文将详细记录问题排查过程和解决方案。
问题描述
初始症状
执行 ./build.sh sha 命令后,虽然编译过程显示成功,但在实际运行生成的可执行文件时出现以下错误:
$ ./sha_test
Error loading shared library libsha.so: No such file or directory (needed by ./sha_test)
Error relocating ./sha_test: sha512_224: symbol not found
Error relocating ./sha_test: sha512_256: symbol not found
Error relocating ./sha_test: sha1_begin: symbol not found
...
$ ./pwd2key
Error loading shared library libsha.so: No such file or directory (needed by ./pwd2key)
Error relocating ./pwd2key: hmac_sha_begin: symbol not found
错误分析
通过错误信息可以识别出两个关键问题:
- 动态库加载失败:程序运行时找不到
libsha.so - 符号未定义:即使加载了库,程序所需的函数符号也不存在
问题排查过程
1. 检查构建配置
首先检查了 HPKBUILD 文件,了解构建配置:
pkgname=sha
pkgver=3ee0d88fc4f629b2e084f1b4cbf22cd3597542fb
archs=("armeabi-v7a" "arm64-v8a")
source="https://github.com/BrianGladman/sha.git"
2. 分析 CMake 配置
查看 sha_ohos.patch 文件中的 CMake 配置:
add_library(sha SHARED sha1.c sha2.c hmac.c)
add_library(sha_static STATIC sha1.c sha2.c hmac.c)
add_executable(hmac hmac_test.c)
target_link_libraries(hmac PRIVATE sha)
add_executable(pwd2key pwd2key.c)
target_link_libraries(pwd2key PRIVATE sha)
add_executable(sha_test sha_test.c)
target_link_libraries(sha_test PRIVATE sha)
add_executable(sha256sum shasum.c)
target_link_libraries(sha256sum PRIVATE sha)
发现问题:所有可执行文件都链接到了动态库 libsha.so,而不是静态库 libsha_static.a。
3. 验证动态链接依赖
使用 llvm-readelf 工具检查生成的可执行文件:
$ llvm-readelf -d sha_test | grep -i "needed"
0x0000000000000001 (NEEDED) Shared library: [libsha.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so]
确认了可执行文件确实依赖于 libsha.so。
解决方案
方案选择
针对动态链接问题,我们有两种解决方案:
方案一:设置库路径
- 优点:保持动态链接的优势
- 缺点:需要在运行时设置
LD_LIBRARY_PATH,增加部署复杂度
方案二:使用静态链接
- 优点:可执行文件独立运行,无需额外配置
- 缺点:文件体积稍大
考虑到 OpenHarmony 设备的部署便利性,我们选择了方案二:静态链接。
实施步骤
1. 修改构建补丁文件
编辑 sha_ohos.patch,将所有可执行文件改为链接静态库:
-add_executable(hmac hmac_test.c)
-target_link_libraries(hmac PRIVATE sha)
+add_executable(hmac hmac_test.c)
+target_link_libraries(hmac PRIVATE sha_static)
-add_executable(pwd2key pwd2key.c)
-target_link_libraries(pwd2key PRIVATE sha)
+add_executable(pwd2key pwd2key.c)
+target_link_libraries(pwd2key PRIVATE sha_static)
-add_executable(sha_test sha_test.c)
-target_link_libraries(sha_test PRIVATE sha)
+add_executable(sha_test sha_test.c)
+target_link_libraries(sha_test PRIVATE sha_static)
-add_executable(sha256sum shasum.c)
-target_link_libraries(sha256sum PRIVATE sha)
+add_executable(sha256sum shasum.c)
+target_link_libraries(sha256sum PRIVATE sha_static)
2. 清理并重新构建
# 清理旧的构建产物
rm -rf usr/sha output
rm -rf thirdparty/sha/sha-*
rm -f usr/hpk_build.csv
# 重新构建
./build.sh sha
3. 验证修复结果
构建完成后,再次检查动态链接依赖:
$ llvm-readelf -d usr/sha/arm64-v8a/bin/sha_test | grep -i "needed"
0x0000000000000001 (NEEDED) Shared library: [libc.so]
$ llvm-readelf -d usr/sha/arm64-v8a/bin/hmac | grep -i "needed"
0x0000000000000001 (NEEDED) Shared library: [libc.so]
$ llvm-readelf -d usr/sha/arm64-v8a/bin/pwd2key | grep -i "needed"
0x0000000000000001 (NEEDED) Shared library: [libc.so]
验证成功:所有可执行文件现在只依赖于系统库 libc.so,不再依赖 libsha.so。
构建产物
文件结构
usr/sha/
├── arm64-v8a/
│ ├── bin/
│ │ ├── hmac
│ │ ├── pwd2key
│ │ ├── sha256sum
│ │ └── sha_test
│ ├── include/
│ │ └── sha/
│ │ ├── brg_endian.h
│ │ ├── brg_types.h
│ │ ├── hmac.h
│ │ ├── pwd2key.h
│ │ ├── rdtsc.h
│ │ ├── sha1.h
│ │ └── sha2.h
│ ├── lib/
│ │ ├── libsha.so
│ │ ├── libsha_static.a
│ │ └── cmake/
│ └── hnp.json
└── armeabi-v7a/
└── (相同结构)
输出文件
output/
├── arm64-v8a/
│ ├── sha.hnp
│ └── sha_3ee0d88fc4f629b2e084f1b4cbf22cd3597542fb.tar.gz
└── armeabi-v7a/
├── sha.hnp
└── sha_3ee0d88fc4f629b2e084f1b4cbf22cd3597542fb.tar.gz
额外修复
在解决主要问题的过程中,还发现并修复了以下问题:
1. Shebang 错误
问题:脚本文件第一行使用了错误的 shebang
#!/bin/env bash # 错误
修复:
#!/usr/bin/env bash # 正确
影响的文件:
build.shenvset.sh
2. 环境变量设置缺失
问题:setarm32ENV() 函数缺少 HNP_TOOL 环境变量设置
修复:
setarm32ENV() {
# ... 其他环境变量
export HNP_TOOL=${OHOS_SDK}/toolchains/hnpcli # 添加这一行
# ...
}
3. 环境配置加载缺失
问题:HPKBUILD 文件缺少 source envset.sh
修复:
source envset.sh # 添加这一行
测试验证
在鸿蒙设备上测试
将生成的可执行文件部署到 OpenHarmony 设备后,测试结果:
# 在设备上运行
$ ./sha_test
SHA-1 tests: OK
SHA-224 tests: OK
SHA-256 tests: OK
SHA-384 tests: OK
SHA-512 tests: OK
$ ./hmac
HMAC tests: OK
$ ./pwd2key
Password to key derivation: OK
$ ./sha256sum test.txt
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 test.txt
测试结论:所有功能正常,问题已完全解决。
技术要点总结
1. 动态链接 vs 静态链接
| 特性 | 动态链接 | 静态链接 |
|---|---|---|
| 文件大小 | 小 | 大 |
| 内存占用 | 低(多进程共享) | 高 |
| 部署复杂度 | 高(需管理库路径) | 低 |
| 更新便利性 | 高(只更新库) | 低(需重新编译) |
| 适用场景 | 系统库、频繁更新的库 | 独立应用、工具程序 |
2. OpenHarmony 构建系统
- HPKBUILD:定义包的元数据和构建过程
- build.sh:主构建脚本,负责环境设置和依赖管理
- envset.sh:架构相关的环境变量设置
- build_hpk.sh:实际的构建执行脚本
3. 跨平台编译注意事项
- 使用正确的工具链(OpenHarmony NDK)
- 设置正确的编译器和链接器参数
- 处理不同架构(armeabi-v7a, arm64-v8a)的差异
- 确保运行时库的可用性
最佳实践建议
1. 对于工具类程序
建议优先使用静态链接,因为:
- 部署简单,无需额外配置
- 避免库版本冲突
- 适合独立运行的小工具
2. 对于库文件
建议同时提供动态库和静态库:
- 动态库供其他程序链接
- 静态库用于构建独立程序
3. 构建配置管理
- 使用补丁文件管理第三方库的修改
- 保持原始代码的完整性
- 便于版本升级和问题追踪
相关资源
总结
通过将动态链接改为静态链接,成功解决了 SHA 库在 OpenHarmony 平台上的编译和运行问题。这个过程不仅修复了当前的 bug,还优化了构建配置,使得生成的程序更加独立和易于部署。
这次问题的解决过程展示了:
- 系统化的问题排查方法
- 对动态链接和静态链接的深入理解
- OpenHarmony 构建系统的使用经验
- 跨平台编译的注意事项
希望这篇文章能帮助遇到类似问题的开发者快速定位和解决问题。
更多推荐



所有评论(0)