NDK编译系列:常见报错问题解决

NDK编译系列:常见报错问题解决

    • 报错:ld: error: undefined symbol XXX referenced by XX.c
    • 问题:为啥LOCAL_PATH不是当前工作目录而是NDK安装目录?

本文小结NDK编译过程中遇到的高频问题分析与解决方法。

报错:ld: error: undefined symbol XXX referenced by XX.c


编动态库阶段:

  • 可能原因

    • 原因1:c/cpp代码混写,纯c代码在头文件声明中未加extern c
    • 原因2:相关依赖的库未预加载进来
    • 原因3:未正确包含相关头文件
    • 原因4:头文件函数声明形参、库文件实现以及调用处传参是否一致
  • 解决方式

    • 原因1:在相关纯C代码头文件函数声明中,首尾添加:
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    /* ... */
    
    #ifdef __cplusplus
    }
    #endif
    
    • 原因2:
      • 一般是生成动态库时,还依赖其他库的场景,需先将相关库装载进编译空间
      • 若报错undefined symbol: std::__ndk1::cout,cout无法识别,则表示stl标准库未加载进来链接,application.mk完成
      • 若报错显示非标准库的依赖符号未定义,则需要预加载非标准库,andriod.mk完成
    • 原因3:
      • 在Android.mk中添加头文件索引目录,如:
      • LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
      • LOCAL_C_INCLUDES += ./include
    • 原因4:
      • 确保头文件函数声明形参、库文件实现以及调用处传参一致

预加载相关库来编译当前库

可以预加载静态库或动态库,预加载的原因是提前告诉当前这个库,在运行时到底依赖哪个库。

预加载非标准库

在Andriod.mk完成,链接所依赖的非标准库:

include $(CLEAR_VARS)
LOCAL_MODULE := libso1
LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/lib1.so
include $(PREBUILT_SHARED_LIBRARY)
#include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libso2
LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/lib2.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := liba1
LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/lib1.a
include $(PREBUILT_STATIC_LIBRARY)

LOCAL_SHARED_LIBRARIES := libso1 libso2  # 链接依赖的动态库
LOCAL_STATIC_LIBRARIES := liba1          # 链接依赖的静态库

预加载标准库

在Application.mk完成,以下指令二选一

APP_STL := c++_shared  # 使用stl动态库,需同步将标准库放同目录中,减小内存
APP_STL := c++_static  # 使用stl静态库,直接将标准库嵌入到so库中,增大内存

编可执行文件阶段

与上面的处理方式类似,也需要提前预加载相应的依赖库,NDK已通过PREBUILT_STATIC_LIBRARY等方式预加载进来,不用再在LDFLAG中去链接添加库。

问题:为啥LOCAL_PATH不是当前工作目录而是NDK安装目录?

详细报错信息:

make: No rule to make target ‘D:/ProgramData/android-ndk-r23c/build//…/build/core/./src/*.c’, needed by ‘D:/workspace/ndk_project/build_exe/obj/local/arm64-v8a/objs/DEMO/./src/main.o’. Stop.

原因分析:

  • mk文件中,LOCAL_PATH宏变量必须在第一行,且后续不必反复声明
  • CLEAR_VARS清理本地变量时,不会清理到LOCAL_PATH
LOCAL_PATH := $(call my-dir)  # 需在首行才能生效,且后序不用反复调用
include $(CLEAR_VARS)         # 打印CLEAR_VARS变量内容

具体使用方法见NDK的官方指导文档:Andriod.mk。

你可能感兴趣的:(经验总结,前端,javascript,开发语言)