HarmonyOS 鸿蒙Next中native多so依赖查找符号表出错

HarmonyOS 鸿蒙Next中native多so依赖查找符号表出错 项目有多so模块,napi的so是access,c++核心主入口是platform.so

cke_1651.png

运行时候总是找不到so的符号表,但是命令行查看符号表是存在的?不知道是什么原因?而且为什么总是在platform中找符号表呢?

cke_390.png

cke_15640.png


更多关于HarmonyOS 鸿蒙Next中native多so依赖查找符号表出错的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

【背景知识】

HarmonyOS上使用CMake构建系统来编译NDK库,其核心编译过程如下: 根据CMake配置脚本以及build-profile.json5中配置的externalNativeOptions构建参数,与缓存中的配置比对后,生成CMake命令并执行CMake,按照makefile执行编译和链接,将生成的.so以及运行时依赖的.so同步到输出目录,完成构建过程。

【问题定位】

当遇到编译找不到SO文件的时候,需要做以下几个方向的排查:

  1. 通过错误日志锁定问题SO的名字,并在CMakeLists.txt文件中找到对应的配置项;
  2. 如果配置项语法没有问题,则检查是否存在工程对应的SO存放路径;
  3. 查看是否有编译缓存文件;
  4. 检查预编译SO的SONAME,文件拷贝是否正确;
  5. 检查该预编译的SO中依赖的其他库是否都存在。

【分析结论】

  1. 可能是CMake配置里,对应的SO关联的选项未打开,或者未配置库的搜索路径;
  2. 可能对应的SO文件未拷贝或者未生成到对应的路径下;
  3. 可能之前的编译缓存影响,编译使用了缓存,未刷新成正确的配置;
  4. 应用在引用动态库的时候是通过SONAME来查找的,开发者需要将SONAME对应的库文件拷贝到entry/libs/${OHOS_ARCH}/目录下。

查询命令:llvm-readelf -d xxx.so

$ llvm-readelf -d xxx.so

Dynamic section at offset 0xad00a0 contains 31 entries:
  Tag        Type                         Name/Value
 0x000000000000001d (RUNPATH)            Library runpath: [$ORIGIN/../../../mapi/shared-glapi:/xxx/ohos-sdk/thirdparty/libxxx:/xxx/ohos-sdk/hiviewdfx/hilog]
 0x0000000000000001 (NEEDED)             Shared library: [libglapi.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so]
 0x0000000000000001 (NEEDED)             Shared library: [libhilog.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc++_shared.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
 0x000000000000000e (SONAME)             Library soname: [libaaa.so]
  1. 使用上述命令查看依赖的SO(NEEDED)。需要把依赖的SO添加到工程中并在CMakeLists.txt链接。

【修改建议】

  1. 检查并更正对应的配置选项;
  2. 拷贝SO到对应的路径下;
  3. 删除缓存的.CXX文件夹,重新执行编译;
  4. Native工程引入SO库时需要SONAME对应的库文件拷贝到entry/libs/${OHOS_ARCH}/目录下;
  5. Native工程引入SO库时要将其依赖项同步链接到工程中。

更多关于HarmonyOS 鸿蒙Next中native多so依赖查找符号表出错的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,native多so依赖查找符号表出错通常是由于符号可见性或加载顺序问题导致。需检查依赖so是否在CMakeLists.txt或build-profile.json中正确定义,并确保符号在导出so中已通过__attribute__((visibility("default")))显式声明。动态链接时需注意so加载顺序,被依赖库应优先加载。可通过nm工具验证符号是否存在,或使用链接器参数--no-undefined在编译阶段检测未定义符号。

在HarmonyOS Next中,多个so模块依赖时出现符号表查找失败,通常是由于动态链接器在解析符号时的搜索路径问题。根据你的描述,符号表在命令行中存在,但运行时找不到,这可能是以下原因导致的:

  1. 符号可见性设置问题:确保依赖的so在编译时正确导出符号。检查CMakeLists.txt或编译脚本中是否使用-fvisibility=default或显式声明__attribute__((visibility("default")))。如果符号被隐藏,动态链接器将无法在运行时解析。

  2. 依赖加载顺序:动态链接器按加载顺序解析符号。如果platform.so依赖其他so的符号,但依赖的so未先加载,会导致查找失败。在代码中通过dlopen显式加载依赖so时,需使用RTLD_GLOBAL标志,确保符号全局可见。例如:

    dlopen("libdependency.so", RTLD_NOW | RTLD_GLOBAL);
    
  3. so路径配置:检查应用程序的config.jsonnativeLibraryPath是否包含所有so的正确路径。如果so未放置在标准目录(如libs/arm64-v8a),需确保路径配置正确。

  4. 符号冲突或版本问题:如果多个so定义了相同符号,链接器可能优先绑定到错误模块。使用nm -D验证符号实际所在模块,并确保无重复定义。

关于“总是在platform中找符号表”,这是因为动态链接器默认从当前模块(如platform.so)开始解析符号。若依赖未正确加载,链接器会局限在该模块内查找,导致失败。建议:

  • 在加载platform.so前,通过dlopen预加载所有依赖so,并设置RTLD_GLOBAL
  • 检查编译链接参数,确保依赖so被正确链接(如使用-l指定库)。

通过调整加载顺序和符号导出设置,可解决此问题。

回到顶部