目录

NDK工程编译时提示找不到SO文件

问题现象

Native工程导入库以及编译的时候,遇到找不到库文件或者引用的函数符号。

报错日志参考如下:

Cause: Can't find any .so file in the xxx
CMake Error at CMakeLists.txt:XXX (find_package):
find a package configuration file provided by XXX
but it set XX_FLAG to false so package is considered to be NOT FOUND

背景知识

HarmonyOS上使用DevEco Studio模板构建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。

    $ 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库时要将其依赖项同步链接到工程中。

常见FAQ

Q:编译的第三方库SONAME必须是libxxx.so.x或者libxxx.so格式的么?

A:三方SO库并没有强制要求必须是libxxx.so.x或者libxxx.so格式。但出于规范性和安全性考虑,避免出现文件内SO信息和文件名一致性等问题,建议按照libxxx.so标准格式设计SONAME,也方便出错时可以快速定位。