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

原创 2017年02月28日 13:06:08

前文

注意:此文的所有配置都是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 )

其中 各个设置都有说明。主要看这个:

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})

它将会把生成的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)

不同的地方是改为添加子目录:

#添加子目录,将会调用子目录中的CMakeLists.txt
ADD_SUBDIRECTORY(one)
ADD_SUBDIRECTORY(two)

这样就会先去跑到子目录下的 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)

子目录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)

最后生成了以下两个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})

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"
 )

最后,因为很多时候,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打开此文件。

上面逻辑中:

  1. 文件类型 ,IntelliJ IDEA 的plugin开发API中可以获取到
  2. 获取当前行的上下共三行字符串数据 ,IntelliJ IDEA 的plugin开发API中可以获取到
  3. 模块目录的API暂时没找到
  4. 在IDE打开C/C++文件,不知道用什么接口

Android Studio CMakeLists.txt文件配置

关于生成可执行文件时依赖的源文件在当前目录及当前目录子目录中的解决办法: 因为 aux_source_directory (./ EXE_SRC)中只能将当前目录中的源代码文件添加到变量EX...
  • chengkaizone
  • chengkaizone
  • 2016年11月11日 13:07
  • 6202

Android Studio2.2配置MakeList使用cmake编译c文件

初次使用cmake来编译c文件在Android项目中,那个快感能传递到骨髓里,欲罢不能.只能说谁用谁知道.如果还没有使用,请赶快用一次,初次体验一共三部: 第一:studio升级到2.2以后的版本,安...
  • qq_35599978
  • qq_35599978
  • 2017年02月21日 21:59
  • 828

AndroidStudio之NDK开发CMake CMakeLists.txt编写入门

一、CmakeList的编写和参数详解  在linux 下进行开发很多人选择编写makefile 文件进行项目环境搭建,而makefile 文件依赖关系复杂,工作量很大,搞的人头很大。采用自动化的...
  • ab6326795
  • ab6326795
  • 2017年10月27日 14:07
  • 818

Android studio中NDK开发(一):CMakeLists.txt编写入门

自定义变量 主要有隐式定义和显式定义两种。  隐式定义的一个例子是PROJECT指令,它会隐式的定义< projectname >_BINARY_DIR和_SOURCE_DIR两个变量;显...
  • liopo
  • liopo
  • 2017年08月29日 20:12
  • 1115

android studio 2.2 C++ 支持(CMAKE方法)

上次学到了约束布局,现在继续学习android studio 2.2使用CMAKE编译C++,并支持在C++打断点,写C++代码时也支持打断点。学习的时候是使用了国外的一篇博客的代码:http://b...
  • yangzhengqui
  • yangzhengqui
  • 2016年05月31日 12:47
  • 17173

android studio cmake 配置.a连接库

自 android studio 2.2 +后就集成了ndk开发, 自带cmake 编译器.  编写ndk时候,配置很简单。再也不需要用android.mk配置文件。 新建一个带nkd开发项目的结...
  • YoYo_Newbie
  • YoYo_Newbie
  • 2017年07月05日 15:17
  • 2475

Android Studio CMake (二)

前面 Android studio CMake (一),针对简单的项目已经足够。然而,现实中却总不是那么简单,例如可能会包含子目录。 1.同样,创建JNI目录和CMakeLists.tx...
  • hhbgk
  • hhbgk
  • 2016年11月26日 16:03
  • 1271

Android studio 使用Cmake完成C/C++ 的使用以及生成so文件

Android studio 2.2版本以后对C/C++的支持可以说很方便了,当然官方推荐使用Cmake完成对C/C++的支持 2.2版本以上的同学新建一个项目就知道了,步骤如下: File -> N...
  • u014800493
  • u014800493
  • 2017年02月09日 16:04
  • 5905

android 在module内创建CMakeLists.txt来实现生成多个.so文件

公司要做sdk,而且大部分代码都是c++的,这就需要在项目中生成多个.so文件,一个是sdk主体,一个是测试代码,通过网上查了相关资料有不同的方法 没有module的实现方法 AndroidStudi...
  • u010302327
  • u010302327
  • 2017年11月10日 10:34
  • 398

CMake简介,打包so文件,编译实际项目

CMake简介和使用示例          下载LOFTER我的照片书  | CMake是常用的跨平台编译器。图像这块在给服务端做...
  • mango9126
  • mango9126
  • 2016年08月23日 11:35
  • 5297
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android Studio NDK CMake 指定so输出路径以及生成多个so的案例与总结
举报原因:
原因补充:

(最多只允许输入30个字)