• NDK编译构建C/CPP工程


    NDK编译系列文章

    1. NDK编译系列:简介及环境搭建,link
    2. NDK编译系列:构建C/CPP工程,link
    3. NDK编译系列:高频编译选项详解,link

    前言


    NDK全称是啥?

    • NDK,Native Developer Kit,原生开发套件
    • 功能:这套工具使我们能在 Android 应用中使用JAVA、 C 和 C++ 代码

    基本流程


    Windows平台编译时,需安装Andriod官网下的NDK工具,并配置相关环境变量。对源码,建议按以下目录结构组织构建:

    目录结构

    • build
      • jni

        • andriod.mk
        • application.mk
        • src
      • libs

      • obj

    jni目录中主要存放编译脚本和代码源文件(放于src目录中)。libs为最终编译构建生成的exe或lib。obj主要存放构建过程中的中间件。

    编译流程

    • 构建jni目录,自动生成libs/objs目录
    • 如果要有符号表等debug信息,建议取用objs目录生成的exe或so,simpleperf仿开销时能看见具体的函数
    • O3优化可能会关掉库里的符号表,最终的无符号表的exe/so文件都在libs
    • 生成库
      • 如果手机上没有相关可执行文件调用对应的so
      • 需要本地再编一个主调demo,调用生成的动态库
    • 生成exe
      • 可直接放入到手机,添加运行权限后,./xx即可运行

    构建脚本


    直接生成EXE的方法

    andriod.mk源码

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE := EXEC_DEMO  # exe name
    CPP_LIST += $(wildcard $(LOCAL_PATH)/src/demo/*.c)
    CPP_LIST += $(wildcard $(LOCAL_PATH)/src/func/*.c)
    LOCAL_SRC_FILES := $(CPP_LIST:$(LOCAL_PATH)/%=%)
    LOCAL_C_INCLUDES := ./src/demo ./src/func
    #cortex-a7, armv7
    #cortex-a53, armv8a
    LOCAL_CFLAGS += -mfpu=neon -mfloat-abi=softfp -mcpu=cortex-a53 -O2 -fPIC -Wall
    LOCAL_CFLAGS += -pie -FPIE
    LOCAL_CFLAGS += -DNDK_TEST        # 程序宏定义
    include $(BUILD_EXECUTABLE)       # 生成可执行EXE
    #include $(BUILD_SHARED_LIBRARY)    # 动态库
    #include $(BUILD_STATIC_LIBRARY)   # 生成静态库
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    application.mk源码

    #APP_ABI := armeabi
    #APP_ABI := armeabi-v7a 
    APP_ABI := arm64-v8a 
    #NDK_TOOLCHAIN_VERSION = 4.9
    
    • 1
    • 2
    • 3
    • 4

    生成动态库再用EXE链接的方法

    生成动态库的andriod.mk源码

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE := demo  # libdemo.so
    CPP_LIST += $(wildcard $(LOCAL_PATH)/src/demo/*.c)
    CPP_LIST += $(wildcard $(LOCAL_PATH)/src/func/*.c)
    LOCAL_SRC_FILES := $(CPP_LIST:$(LOCAL_PATH)/%=%)
    LOCAL_C_INCLUDES := ./src/demo ./src/func
    #cortex-a7, armv7
    #cortex-a53, armv8a
    LOCAL_CFLAGS += -mfpu=neon -mfloat-abi=softfp -mcpu=cortex-a53 -O2 -fPIC -Wall
    LOCAL_CFLAGS += -pie -FPIE
    #LOCAL_CFLAGS += -DNDK_DEMO    # 宏定义
    #include $(BUILD_EXECUTABLE)       # 可执行EXE
    include $(BUILD_SHARED_LIBRARY)    # 动态库
    #include $(BUILD_STATIC_LIBRARY)   # 生成静态库
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    application.mk源码

    #APP_ABI := armeabi
    #APP_ABI := armeabi-v7a 
    APP_ABI := arm64-v8a 
    #NDK_TOOLCHAIN_VERSION = 4.9
    
    • 1
    • 2
    • 3
    • 4

    EXE链接生成的动态库

    将上面生成动态库libdemo.so拷贝到exe构建的jni目录下,与脚本目录同级。

    andriod.mk源码

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE := libso
    # v8a
    LOCAL_SRC_FILES := libdemo.so
    include $(PREBUILT_SHARED_LIBRARY)
    #include $(PREBUILT_STATIC_LIBRARY)
    include $(CLEAR_VARS)
    LOCAL_MODULE := EXEC_DEMO   # 最终生成的可执行文件
    CPP_LIST += $(wildcard $(LOCAL_PATH)/src/demo/*.c)
    CPP_LIST += $(wildcard $(LOCAL_PATH)/src/func/*.c)
    LOCAL_SRC_FILES := $(CPP_LIST:$(LOCAL_PATH)/%=%)
    LOCAL_C_INCLUDES := $(LOCAL_PATH)/src/demo/ \
                        $(LOCAL_PATH)/src/func/ \
    LOCAL_SHARED_LIBRARIES := libso
    #LOCAL_STATIC_LIBRARIES := libso
    # v8a
    LOCAL_CFLAGS += -mfpu=neon -mfloat-abi=softfp -mcpu=cortex-a53 -O3 -fPIC -Wall
    LOCAL_CFLAGS += -pie -FPIE
    LOCAL_LDFLAGS += -pie -FPIE
    include $(BUILD_EXECUTABLE)
    #include $(BUILD_SHARED_LIBRARY)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    application.mk源码 无变化

    #APP_ABI := armeabi
    #APP_ABI := armeabi-v7a 
    APP_ABI := arm64-v8a 
    #NDK_TOOLCHAIN_VERSION = 4.9
    
    • 1
    • 2
    • 3
    • 4

    完成编译


    一切准备就续后,打开cmd,输入指令cd切换到当前jni目录,运行以下指令:

    • ndk-build --version,查看NDK版本
    • ndk-build clean,清理之前编译中间结果
    • ndk-build,在jni目录下开始编译,生成结果在libs/obj中

    之后,将生成的exe或lib库,用adb推送到andriod终端,并赋予相关执行权限,即可正常运行测试。

    参考资料


    1. Android NDK官方说明,link
  • 相关阅读:
    Ant-Design-Vue:a-range-picker组件国际化配置
    【fiddler学习笔记】——安装、原理、使用
    【CV】第 9 章:图像分割
    利用北斗GEO卫星观测监测深圳市周围地区电离层空间环境
    学生宿舍管理系统(前端java+后端Vue)实现-含前端与后端程序
    Apollo 应用与源码分析:CyberRT-日志配置
    在spring中使用Validated和@Valid对参数进行校验
    linux 安装中文字体
    文件管理系统概述
    QT+OSG/osgEarth编译之四十五:osgViewer+Qt编译(一套代码、一套框架,跨平台编译,版本:OSG-3.6.5核心库osgViewer)
  • 原文地址:https://blog.csdn.net/qq_17256689/article/details/126753349