文档章节

Android Studio NDK CMake 指定so输出路径以及生成多个so的案例与总结

shzwork
 shzwork
发布于 07/06 14:57
字数 1647
阅读 3
收藏 0

前文
注意:此文的所有配置都是mac电脑下 
一直想用Android Studio的新方式Cmake来编译JNI 代码,之前也尝试过,奈何有两个难题挡住了我 
1. 只能生成一个 so库,不能一次性生成多个 so库,之前的mk是可以有子模块的。 
2. 每次生成的so所在的目录不是在 jniLibs下,虽然知道如果打包,会将它打包进去,但就是觉得看不见它,想提供给别人用,还要去某个目录找。

经过尝试,这两个问题都可以解决了。

生成单个so的案例
demo下载地址: http://download.csdn.net/detail/b2259909/9766081

直接看CMakeLists.txt文件:

#指定需要CMAKE的最小版本
cmake_minimum_required(VERSION 3.4.1)


#C 的编译选项是 CMAKE_C_FLAGS
# 指定编译参数,可选
SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")

#设置生成的so动态库最后输出的路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})

#设置头文件搜索路径(和此txt同个路径的头文件无需设置),可选
#INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/common)

#指定用到的系统库或者NDK库或者第三方库的搜索路径,可选。
#LINK_DIRECTORIES(/usr/local/lib)


add_library( native-lib
             SHARED
             src/main/cpp/native-lib.cpp )

target_link_libraries( native-lib
                       log )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
其中 各个设置都有说明。主要看这个:

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
1
它将会把生成的so库按照你在 build.gradle 指定的 abi分别放置在 jniLibs下 


非常好,先解决了第二个问题了。

生成多个so案例
还是上面那个demo,重新建一个module。

cpp的目录结构:

直接看CMakeLists.txt文件:

#指定需要CMAKE的最小版本
cmake_minimum_required(VERSION 3.4.1)


#C 的编译选项是 CMAKE_C_FLAGS
# 指定编译参数,可选
SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")

#设置生成的so动态库最后输出的路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})

#设置头文件搜索路径(和此txt同个路径的头文件无需设置),可选
#INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/common)

#指定用到的系统库或者NDK库或者第三方库的搜索路径,可选。
#LINK_DIRECTORIES(/usr/local/lib)


#添加子目录,将会调用子目录中的CMakeLists.txt
ADD_SUBDIRECTORY(one)
ADD_SUBDIRECTORY(two)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
不同的地方是改为添加子目录:

#添加子目录,将会调用子目录中的CMakeLists.txt
ADD_SUBDIRECTORY(one)
ADD_SUBDIRECTORY(two)
1
2
3
这样就会先去跑到子目录下的 one 和 two 的CmakeLists.txt,执行成功再返回。 
此时子目录one下的CmakeLists.txt:

#继承上一层的CMakeLists.txt的变量,也可以在这里重新赋值
#C 的编译选项是 CMAKE_C_FLAGS
# 指定编译参数,可选
#SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")

#生成so动态库
ADD_LIBRARY(one-lib SHARED one.cpp)

target_link_libraries(one-lib log)
1
2
3
4
5
6
7
8
9
子目录two下的CmakeLists.txt:

#继承上一层的CMakeLists.txt的变量,也可以在这里重新赋值
#C 的编译选项是 CMAKE_C_FLAGS
# 指定编译参数,可选
#SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")

#生成so动态库
ADD_LIBRARY(two-lib SHARED two.cpp)

target_link_libraries(two-lib log)
1
2
3
4
5
6
7
8
9
最后生成了以下两个so文件,并自动按照abi分别放置在了 jniLibs下:

第一个问题也成功了。

总结
最后,除了 设定abiFilters 必须在 build.gradle 
主要是发现CmakeLists.txt里 其实可以指定很多东西: 
1. so输出路径 CMAKE_LIBRARY_OUTPUT_DIRECTORY 
2. .a 静态库输出路径 CMAKE_ARCHIVE_OUTPUT_DIRECTORY 
2. 获取当前编译的abi , ANDROID_ABI 
3. 编译选项: 
CMAKE_C_FLAGS 
CMAKE_CXX_FLAGS 
CMAKE_CXX_FLAGS_DEBUG/CMAKE_CXX_FLAGS_RELEASE 
4. 子目录编译: ADD_SUBDIRECTORY 
5. #设置.c文件集合的变量

#当前cmakelists.txt所在目录的所有.c .cpp源文件
AUX_SOURCE_DIRECTORY(. SRC_LIST)

#增加其他目录的源文件到集合变量中
list(APPEND SRC_LIST
        ../common/1.c
        ../common/2.c
        ../common/3.c
        ../common/4.c
        ../common/5.c
        ../common/WriteLog.c
    )

#生成so库,直接使用变量代表那些.c文件集合
add_library(mylib SHARED ${SRC_LIST})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
6._执行自定义命令:

# copy头文件到 静态库相同文件夹下
add_custom_command(TARGET myjni
  PRE_BUILD
  COMMAND echo "executing a copy command"
  COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/myjni.h ${PROJECT_SOURCE_DIR}/../../../build/outputs/staticLib/myjni/${ANDROID_ABI}
  COMMENT "PRE_BUILD, so This command will be executed before building target myjni"
 )
1
2
3
4
5
6
7
最后,因为很多时候,JNI的参数还要转为C的方式,当我们在JAVA层写了native方法,android IDE自动提示红色,这时按下 ALT + ENTER 可以自动生成JNI下的方法声明,并且入参也帮我们转换好了。不过有时候这个插件不生效。

所以我写了一个JNI 的入参转为 C/C++的代码插件: JNI-Convert-Var,直接在 plugin 的仓库搜就有了。 
最近尝试实现android studio的ALT + ENTER 可以自动生成JNI下的方法声明,结果发现好多IntelliJ IDEA的接口不熟悉。 只能先放弃了,以下是我的逻辑:

当鼠标点击在 Native声明方法上时: 
1. 检查文件类型,如果为java就继续 
2. 获取当前行的上下共三行字符串数据,使用正则表达式获取native声明的完整方法。 
3. 检查当前模块目录下的jni或者cpp目录下的.c或者.cpp文件。 
4. 如果没有文件,弹窗让用户创建一个C/C++文件,并追加转换后(如何转换会有一个专门的类)的Java2C方法在文件末尾. 在IDE打开此文件。 
5. 如果JNI或者cpp目录有一个以上的C/C++文件, 弹窗让用户选择一个C/C++文件或者创建,之后打开文件追加转换后(如何转换会有一个专门的类)的Java2C方法在文件末尾. 。 在IDE打开此文件。

上面逻辑中:

文件类型 ,IntelliJ IDEA 的plugin开发API中可以获取到
获取当前行的上下共三行字符串数据 ,IntelliJ IDEA 的plugin开发API中可以获取到
模块目录的API暂时没找到
在IDE打开C/C++文件,不知道用什么接口
--------------------- 
作者:zhangbh2014 
来源:CSDN 
原文:https://blog.csdn.net/b2259909/article/details/58591898/ 
版权声明:本文为博主原创文章,转载请附上博文链接!

本文转载自:https://blog.csdn.net/b2259909/article/details/58591898/

shzwork
粉丝 15
博文 828
码字总数 18401
作品 0
厦门
私信 提问
一篇好文之Android 调用C代码及生成调试so库

版权声明:本文为博主原创文章,转载请声明。 https://blog.csdn.net/qq_32175491/article/details/83588167 不靠谱的朱先生又来了,今天是周五,我又出现了!好了,不为自己多解释,上周没发...

aserbao
2018/11/02
0
0
AndroidStudio用Cmake方式编译NDK代码(cmake配置.a库)

AndroidStudio用Cmake方式编译NDK代码(cmake配置.a库) 1.cmake是什么? CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的mak...

shzwork
06/05
122
0
Android JNI学习(二)——实战JNI之“hello world”

本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Native相互调用 Android JNI学习(四)——JNI的常用方法...

隔壁老李头
2018/05/09
0
0
Android:随笔——新的 NDK/JNI 调用方式

转载请标明地址 QuincySx: http://www.jianshu.com/p/c6108131ba0f 众所周知现在 Android 开发已经到了 Android Studio 的时代,那么 JNI 的调用方式也经过了好几代 在eclipse 时代就存在的...

quincy
2017/04/05
0
0
android studio 使用CMAKE

原文地址 前言 之前,每次需要边写C++代码的时候,我的内心都是拒绝的。 1. 它没有代码提示!!!这意味着我们必须自己手动敲出所有的代码,对于一个新手来说,要一个字母都不错且大小写也要...

shzwork
05/20
19
0

没有更多内容

加载失败,请刷新页面

加载更多

好程序员Java教程分享Zookeeper基本原理与运用场景

好程序员Java教程分享Zookeeper基本原理与运用场景一、什么是Zookeeper? zookeeper是一个分布式的一致性协调服务。 换句话说,也可以把zookeeper看成一个小型的分布式文件系统。但是和FastD...

好程序员官网
21分钟前
6
0
mysql表情符

1 修改表字段为utf8md4 ALTER table property_info MODIFY `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL 2 MySQL数据库服务器配置文件mysqld.cn......

干死it
40分钟前
4
0
正则表达式的基本语法

本文摘自LTP.NET知识库。 正则表达式的形式一般如下: /love/ 其中位于“/”定界符之间的部分就是将要在目标对象中进行匹配的模式。 用户只要把希望查找匹配对象的模式内容放入“/”定界符之...

木庄
42分钟前
4
0
java 框架有哪些?

十大常用框架: 一、SpringMVC 二、Spring 三、Mybatis 四、Dubbo 五、Maven 六、RabbitMQ 七、Log4j 八、Ehcache 九、Redis 十、Shiro 延展阅读: 一、SpringMVC Spring Web MVC是一种基于J...

java框架开发者
43分钟前
10
0
细谈Mysql事务

文章原创于公众号:程序猿周先森。本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号。 上一篇着重谈到了MySQL锁的概念,里面谈到了事务的概念,其实大部分开发者对于事务肯定不陌生,...

程序猿周先森
51分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部