Android JNI 开发环境配置

Android JNI 开发环境配置

上一篇:JNI基础
下一篇:JNI 开发与调试流程

Android JNI 开发环境配置的3种方式

1. Android.mk 和Application.mk

编译Android系统源码驱动源码, 老式的Android JNI项目

2.根据ndk提供的工具生成独立运行的工具链, 独立编译so库

针对一下老的或者对Android平台还没有适配的开源库, 这些库一般用configure或automake来检测平台或者手动编写makefile来管理源码

3. gradle和CMakeLists.txt配置(推荐)

  • 可以安装 独立运行的gradle和cmake编译
  • 使用gradlewrapper 和ndk内置的cmake编译

gradle工程脚本

gradle是 groovy 语言编写的工程管理和构建脚本

groovy的特点

  • groovy是运行在 JVM 上的语言, 她会先编译成class文件后再运行,本质上,她可以使用反射调用的Java代码

  • groovy代码里可以使用Java的类库

  • groovy定义的一切类,属性,方法都是反射的,编译是不检查,但是运行时如果方法或属性不存在就会崩溃

  • groovy方法调用可以不写(), 类似shell 脚本的写法如:

    A.fun1 a,b,c  //等效于 A.fun1(a,b,c)
  • groovy 的独立函数叫 Closure , 相当于java的lamda表达式或者函数接口类, 定义如下:

    {int a,String B ->
      //TODO body
    }

    或者没有参数或只有一个参数时,可以不写参数

    {
      //TODO body
    }

    闭包有一个 delegate 对象,闭包内地可以使用delegate` 对象的任何方法或属性不加任何说明,默认情况下为闭包定义处的那个对象

  • 访问一个对象的属性可以应[], 如

    A["abc"] = 1 //等效于 A.abc = 1
  • 字符串单,双,三引号都行,内部填参数用${},如

    int a=12
    String b = 'hello,world'
    String x = "show: ${a}, ${b}"
    String y = '''
     new line
    
     new str
    '''
  • 函数调用可以不按顺序或者全部写参数,但要指定参数定义是的名称.用:分隔,如

    def fun1={ int x, String y ->
    }
    //
    fun1(y:"hello",x:10)
    fun1(y:"hello")
  • -

cmake语言的特点

cmake 是跨平台的 c, c++ 代码工程管理工具,她先将工程脚本编译成makefile, 或者微软的VirsualStudio或者XCode的工程文件后再编译

  • 设置变量

    set(变量名 变量值)

    注意:cmake里有时字符串可以不加引号,如文件路径

  • 设置选项, 作用和变量一样,不同是选项可以在图形界面的cmake或者help中显示

    option(变量名 "提示说明文字" 默认值)
  • 显示信息

    message(STATUS "文字") #相当于 print
    
    message(FATAL_ERROR "文字") #相当于 print, 并停止编译
  • 添加头文件

    include_directories(目录1 目录2 ...)
  • 编译成库

    add_library(库名 SHARED|STATIC  #SHARED=动态库,STATIC=静态库
    源码文件列表 ...
    )
  • 编译可执行程序

    add_executable(库名 SHARED|STATIC  #SHARED=动态库,STATIC=静态库
    源码文件列表 ...
    )
  • 指定库链接依赖关系

    target_link_libraries(目标库或程序
    依赖的库名列表 ...
    )
  • 指定编译的依赖关系(编译的先后顺序)

    add_dependencies(目标库或程序 依赖的库名列表 ...)
    
    # 依赖的库先被编译后,再编译目标库或程序
    
  • 条件语句

    if(条件)
    
    # 执行语句
    
    elseif(另一个条件)
    
    # 执行语句
    
    else()
    
    # 执行语句
    
    endif()

    常见的条件有:

    1. 变量为bool值或不存在, ON,YES,TRUE表示真, OFF,NO,FALSE表示假

    2. 字符串比较,匹配,如

      "" STREQUAL ""  #
      "abc" MATCHES "ab*"
    3. NOT运算

    4. 其他cmake函数的返回值

  • 循环语句

    foreach(元素变量名 元素列表)
    
    #  执行体
    
    endforeach()
  • 定义cmake宏,宏是一段可重复调用的代码

    macros(宏名 参数1 参数2 ...)
    
    # 隐藏的参数 ARGN 表示所有上面没有列出的参数组成的列表
    
    
    # 执行语句
    
    endmacros()
  • 定义cmake函数,功能和宏一样,但是可以往外传参数

    function(宏名 参数1 参数2 ...)
    
    # 隐藏的参数 ARGN 表示所有上面没有列出的参数组成的列表
    
    
    # 执行语句
    
    
    # 通过 set 语句返回
    
    set(返回变量 返回值)
    endfunction()
  • 定义C,C++的宏

    
    # 
    
    add_definitions(-D宏) 
    add_definitions(-D宏=值)
    
    # 
    
    remove_definitions(-D宏)
  • 常用的系统全局变量

    1. APPLE,LINUX,WIN32: 编译平台是否是指定的系统
    2. CMAKE_CURRENT_LIST_DIR,CMAKE_BINARY_DIR:
    3. CMAKE_C_COMPILER,CMAKE_CXX_COMPILER,CMAKE_C_FLAGS,CMAKE_CXX_FLAGS:
    4. 4.
  • 查找库

    find_library(结果变量 库名)
  • 查找文件

    find_file(结果变量 NAMES 文件名列表)
  • 字符串处理

    string(REPLACE 匹配 代替 输出 输入)
  • 列表

    list(APPEND 列表变量 插入值)
  • 引进一个包含CMakelists.txt的子工程

    add_subdirectory(路径 [别名]) #
  • 批量引进源码文件

    aux_source_directory(目录 结果变量) #将目录下的所有.c,.cpp文件生成一个列表
  • 自定义任务

    add_custom_target(目标名
    COMMAND 命令行     #
    WORKING_DIRECTORY       #
    COMMENT "打印的提示信息"
    DEPENDS 依赖列表        #
    
    #SOURCES 加入工程的源文件
    
    )
    
    add_custom_command(TARGET|OUTPUT 目标名称 #OUTPUT一般用于文件
    PRE_BUILD | PRE_LINK| POST_BUILD        #PRE_BUILD - 命令将会在其他依赖项执行前执行
    
    #PRE_LINK - 命令将会在其他依赖项执行完后执行
    
    
    #POST_BUILD - 命令将会在目标构建完后执行。
    
    COMMAND 命令行     #
    WORKING_DIRECTORY       #
    COMMENT "打印的提示信息"
    )
    
    
  • 自定义属性

    set_property([GLOBAL]                            
                DIRECTORY [dir]                   
                TARGET    列表 
                #SOURCE    
                #TEST      
                #CACHE     
               [APPEND] "APPEND_STRING"
               PROPERTY 属性名称 [值列表])
  • abc

详细的cmake语法可参考一下文件

官网手册

CMake构建系统的骨架

Android gradle工程

Android gradle工程目录结构

  • 根目录

    • build.gradle
    //定义gradle插件的来源
    buildscript {
        ext.kotlin_version = '1.2.40'
        repositories {
            google()
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:3.1.3'
            classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        }
    }
    //对所有子工程起作用
    allprojects {
        repositories {
            google()
            jcenter()
            maven { url "https://jitpack.io" }
        }
    }

    注意: 这里的repositories,dependencies不是类或对象定义, 而是函数调用, {}是一个闭包,是前面函数的参数

    • local.properties:
    sdk.dir=xxx
    ndk.dir=xxx
    • gradle

    放gradlewrapper(一个可独立运行的gradle)的jar和配置文件,可调gradle环境的版本

    • .gradle:

    • gradlew, gradle.bat: gradlewrapper的在Unix和Windows系统的启动脚本

    • gradle.properties:

    设置总工程的全局属性, Java虚拟机的属性

    • settings.gradle

    子工程的列表

    include ":ABC" //当前目录下的子工程
    //添加不在当前目录下的子工程
    include ":XYZ"
    project(":XYZ").projectDir=new File("pathxxxx") 
  • 子工程目录

    仅有build.gradle

    apply plugin: 'com.android.library' // === apply(plugin:'com.android.library')
    
    //这里仅展示与JNI相关的调用
    android {
      //cmake工程文件的路径
      externalNativeBuild {
          cmake {
              path "CMakeLists.txt"
          }
      }
      //
      defaultConfig {
        //运行cmake的配置
          externalNativeBuild {
              cmake {
                  arguments("-Dxyz=xyz", ...) //gradle 传给 cmake的变量
                  //传给CMAKE_CXX_FLAGS的变量, 其实也可以在CMakeLists.txt内部在设置
                  cppFlags("-std=c++11", ... ) //
              }
          }
          //
          ndk {
              //注意: 对于多构架来说, cmake 会每个构架运行一遍, 每次运行时 ANDROID_ABI 变量都不一样
              abiFilters('armeabi-v7a', ...)  //设置编译成的 so 库构架 'arm64-v8a', 'x86', 'x86_64'
              stl 'gnustl_static' //
          }
      }
      //
    
      //
      sourceSets {
          main {
              //要打包进aar里的so文件目录
              jniLibs.srcDirs("${projectDir}/libs/jniLibs", ... ) 
          }
      }
    }
    

Android JNI中的CMakeLists.txt

语法和全局变量与标准cmake相似, 但是多了一些特殊的全局变量和函数, 具体定义可以查看 android SDK 目录下的 cmake –> androidtoolchain.cmake

  • 与Android相关的全局变量

    1. ANDROID_NDK
    2. ANDROID_TOOLCHAIN
    3. ANDROID_ABI
    4. ANDROID_PLATFORM
    5. ANDROID_STL STL库的类型,默认为portstl
    6. ANDROID_PIE
    7. ANDROID_CPP_FEATURES
    8. ANDROID_ALLOW_UNDEFINED_SYMBOLS
    9. ANDROID_ARM_MODE
    10. ANDROID_ARM_NEON
    11. ANDROID_DISABLE_NO_EXECUTE
    12. ANDROID_DISABLE_RELRO
    13. ANDROID_DISABLE_FORMAT_STRING_CHECKS
    14. ANDROID_CCACHE
  • 引进Android标准库

    find_library(结果变量 库名称)
    
    # 如果没找到库, 变量 库名称_NOTFOUND 为 TRUE
    

    常用的标准库有

    1. log:
    2. GLESv2:
    3. 3.
  • 引进本地库

    add_library(库名称  SHARED IMPORTED)
    
    # 设置库文件的本地路径
    
    set_target_properties(库名称 PROPERTIES IMPORTED_LOCATION  库文件的本地路径)

Demo

主cmake文件

cmake_minimum_required(VERSION 3.0) # 支持高级的语法

include_directories(src/main/cpp
src/main/cpp/usbdevice
)

add_definitions(-D__android=1 -D__DEBUG=1)
## 定义引进本地so库的宏
set(ALG_DEP)
macro(add_alg_libs ROOT_DIR1)
    foreach(one ${ARGN})
        message(STATUS "Add ${one}")
        add_library(${one}  SHARED IMPORTED)
        set_target_properties(${one} PROPERTIES IMPORTED_LOCATION  ${ROOT_DIR1}/${ANDROID_ABI}/lib${one}.so )
        #
        list(APPEND ALG_DEP ${one})
    endforeach(one)
endmacro()
## 引进Android内置的库
find_library(log-lib log)
find_library(glv2-lib GLESv2)

add_alg_libs(${CMAKE_CURRENT_LIST_DIR}/libs
ImiCamera iminect)

#  定义引进一个外部cmake的宏
set(ALL_TEST_LIB)
macro(ADD_TEST_LIB DIR)
    include_directories(${DIR})
    add_subdirectory(${DIR} test)
    list(APPEND ALL_TEST_LIB ${ARGN})
endmacro()

## 引进一个外部的cmake
ADD_TEST_LIB(src/main/cpp/demo demo)
## 添加主库
add_library(testsuit_jni SHARED
 src/main/cpp/testsuit_jni.cpp
 src/main/cpp/testsuit_framework.cpp
 )

 target_link_libraries(testsuit_jni ${log-lib} ${glv2-lib} ${ALG_DEP} ${ALL_TEST_LIB})

外部cmake文件

cmake_minimum_required(VERSION 3.0)

add_library(demo
test_list.cpp
my_test.cpp)

参考文档

  1. cmake 常用变量和常用环境变量查表手册
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值