android studio 使用CMAKE

原文地址

前言

以前,每次须要边写C++代码的时候,个人心里都是拒绝的。 
1. 它没有代码提示!!!这意味着咱们必须本身手动敲出全部的代码,对于一个新手来讲,要一个字母都不错且大小写也要正确,甚至要记得住全部的jni函数等,真是太折磨人了…平时写Java代码的时候都是写几个字母会出来一大堆提示而后选择的,这样还有一个好处就是不少时候咱们不知道有那些函数,可是咱们能够经过obj.,而后就能够看到它有哪些方法函数了。 
2. 不少地方会显示为红色,就像是错误提示的那种,固然,若是没错的话仍是能编译运行的,可是若是像编写java代码同样,写错的地方才给我红色显示不是更好吗? 
这两个问题可折磨死我这个强迫症了…在网上百度了好久如何可以使用Android Studio编写C++代码时有代码提示自动补全功能,可是一直没有找到有效的(不使用CMake的状况下,如有人知道,麻烦告知)。好在一次偶然的机会,在网上看到在 Android Studio 2.2 中愉快地使用 C/C++这篇文章,看到上面说Android Studio2.2版本完善了对C/C++的支持,还说起到CMAKE,赶忙把Android Studio从2.0版本升级到了2.2版本,按照介绍新建了一个NDK工程,发现里面竟然有我求之不得的C++代码自动补全提示!!!喜大普奔!!! 
赶忙了解学习下Android Studio2.2版本提供的CMAKE方式。打算之后都使用这种方式了,别的不说,就冲能够有C++代码自动补全提示这个功能我就爱上它了。java

工具安装

Android Studio升级到2.2以后,咱们能够先配置好NDK开发的一些所需工具,如图,在SDK Tools中勾选安装CMake、LLDB、NDK。 
这里写图片描述android

CMake: 外部构建工具。若是你准备只使用 ndk-build 的话,能够不使用它。  
LLDB: Android Studio上面调试本地代码的工具。shell

Android Studio自带DEMO了解CMAKE

Android Studio升级到2.2版本以后,在建立新的project时,界面上多了一个Include C++ Support的选项。勾选它以后将会建立一个默认的C++与JAVA混编的Demo程序。就让咱们先来看看这个官方标准Demo吧。api

开始以前最好先下载好NDK,见NDK开发 从入门到放弃(一:基本流程入门了解),即在Project Structure界面Android NDK location处下载或选择正确的路径。或者使用上方提供的工具安装方法来进行下载。不然,建立的新project也会报错,须要配置好后clean。app

File -> New -> New Project,在以下界面中勾选Include C++ Support,而后一路 Next,直到 Finish 为止便可。 
这里写图片描述
项目打开后咱们查看目录结构,与常规项目不一样的是多了.externalNativeBuild文件夹、cpp文件夹、CMakeLists.txt文件,以下图: 
这里写图片描述 
这三个东西都是NDK部分: 
1. .externalNativeBuild文件夹:cmake编译好的文件, 显示支持的各类硬件等信息。系统生成。 
2. cpp文件夹:存放C/C++代码文件,native-lib.cpp文件是该Demo中自带的,可更改。须要本身编写。 
3. CMakeLists.txt文件:CMake脚本配置的文件。须要本身配置编写。ide

Gradle中也有两处不一样: 
这里写图片描述函数

java代码:工具

 
  1. public class MainActivity extends AppCompatActivity {学习

  2.  
  3. @Overridegradle

  4. protected void onCreate(Bundle savedInstanceState) {

  5. super.onCreate(savedInstanceState);

  6. setContentView(R.layout.activity_main);

  7.  
  8. // Example of a call to a native method

  9. TextView tv = (TextView) findViewById(R.id.sample_text);

  10. tv.setText(stringFromJNI());

  11. }

  12.  
  13. /**

  14. * A native method that is implemented by the 'native-lib' native library,

  15. * which is packaged with this application.

  16. */

  17. public native String stringFromJNI();

  18.  
  19. // Used to load the 'native-lib' library on application startup.

  20. static {

  21. System.loadLibrary("native-lib");

  22. }

  23. }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

从native-lib.cpp的代码中咱们能看到它使用的是静态注册的方式,动态注册的方式代码同传统JNI。

 
  1. #include <jni.h>

  2. #include <string>

  3.  
  4. extern "C"

  5. jstring

  6. Java_com_example_person_myapplication_MainActivity_stringFromJNI(

  7. JNIEnv* env,

  8. jobject /* this */) {

  9. std::string hello = "Hello from C++";

  10. return env->NewStringUTF(hello.c_str());

  11. }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

CMakeLists.txt文件中咱们须要注意的是下面这三个地方。两个library的名字(需一致)以及一个cpp文件的路径,彼此须要对应一致,当咱们本身定义library以及本身建立cpp文件时须要对应修改。 
这里写图片描述

运行代码,就能看到效果,调用了C++方法在界面上显示了Hello from C++字符串。这就是CMake方式进行NDK开发的Demo。 
还记得传统JNI方式中吗?咱们使用了ndk -build来编译C/C++文件为so文件,对于使用过第三方库的开发者来讲,对so确定不陌生。咱们只能使用别人给的so文件,而没法看到C/C++源码,更别说去修改了。可是在这里咱们好像一直没看到so文件的影子,那么,咱们安装运行的apk中,有对应的so文件吗?若是想验证一下apk是否有so文件,咱们可使用 APK Analyzer:

  1. 选择 Build > Analyze APK。
  2. 选择 apk,并点击 OK。
  3. 以下图,在 APK Analyzer 窗口中,选择 lib/x86/,能够看见 libnative-lib.so 。 
    这里写图片描述

Tips:Instant Run 并不兼容使用了 native code 的项目。Android Studio 会自动禁止 Instant Run 功能。

可是我我的目前更关注的问题是C++代码自动补全提示的功能,当在cpp文件中写代码时,里面再也不是一大片的红色,输入若干个字母的时候,也能给出提示了,简直叼渣天,至于缘由…我就不清楚了,为何在这里就有这个强大的功能了呢?哪位大神能解释下… 
这里写图片描述

CMake编译so文件

在Android Studio的Terminal中输入cmake,会提示:

'cmake' 不是内部或外部命令,也不是可运行的程序或批处理文件。
  • 1
  • 1

须要在下载配置好CMake的环境变量,若没这个问题可跳过这个步骤。在以下网址中下载好对应的文件: 
https://cmake.org/download/ 
这里写图片描述

下载zip包后,解压缩。而后将cmake.exe所在的路径,添加到path环境变量中。cmake就成为有效命令了。


在CMakeLists.txt文件上级目录下执行cmake .命令,报错,暂未解决:

 
  1. -- Building for: NMake Makefiles

  2. -- The C compiler identification is unknown

  3. -- The CXX compiler identification is unknown

  4. CMake Error in CMakeLists.txt:

  5. The CMAKE_C_COMPILER:

  6.  
  7. cl

  8.  
  9. is not a full path and was not found in the PATH.

  10.  
  11. To use the NMake generator with Visual C++, cmake must be run from a shell

  12. that can use the compiler cl from the command line. This environment is

  13. unable to invoke the cl compiler. To fix this problem, run cmake from the

  14. Visual Studio Command Prompt (vcvarsall.bat).

  15.  
  16. Tell CMake where to find the compiler by setting either the environment

  17. variable "CC" or the CMake cache entry CMAKE_C_COMPILER to the full path to

  18. the compiler, or to the compiler name if it is in the PATH.

  19.  
  20.  
  21. CMake Error in CMakeLists.txt:

  22. The CMAKE_CXX_COMPILER:

  23.  
  24. cl

  25.  
  26. is not a full path and was not found in the PATH.

  27.  
  28. To use the NMake generator with Visual C++, cmake must be run from a shell

  29. that can use the compiler cl from the command line. This environment is

  30. unable to invoke the cl compiler. To fix this problem, run cmake from the

  31. Visual Studio Command Prompt (vcvarsall.bat).

  32.  
  33. Tell CMake where to find the compiler by setting either the environment

  34. variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path

  35. to the compiler, or to the compiler name if it is in the PATH.

  36.  
  37.  
  38. -- Configuring incomplete, errors occurred!

  39. See also "E:/AndroidDemo_XY/app/CMakeFiles/CMakeOutput.log".

  40. See also "E:/AndroidDemo_XY/app/CMakeFiles/CMakeError.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
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

待完成


CMake和传统 JNI在目录结构和配置文件上的区别

如今咱们有了CMake和传统JNI两种开发NDK的方法,它们在目录结构和Gradle上有所区别,下面咱们将分别介绍目录区别和Gradle配置的区别。 
1、目录结构 
传统JNI 
这里写图片描述 
CMake 
这里写图片描述

这两种方式在目录上的区别就是两点: 
1. 之前的jni目录改为cpp,名字更换了,下面仍是存放C/C++文件。  
2. 以前对C/C++文件的编译配置Android.mk、Application.mk文件放在jni目录下,如今改为CMakeLists.txt文件。(事实上这些文件的位置是可任意存放的,只须要配置好就行。但最好仍是按照默认习惯放置。)

2、Gradle 
传统JNI 
这里写图片描述

CMake 
这里写图片描述

事实上,咱们在使用传统JNI方式的时候,上面的两处地方咱们都省略了,也不会形成什么异常(若Android.mk存放位置在其余地方则须要配置)。CMake方式中第一处也可省略,可是第二处不能省略(一样,位置路径要写对),由于没有它将没法Build生成.externalNativeBuild文件夹。

另外,传统JNI开发还须要在项目根目录下的gradle.properties文件中配置

android.useDeprecatedNdk=true
  • 1
  • 1

不然Build项目的时候会报错。

CMake的优点

  1. 能够直接的在C/C++代码中加入断点,进行调试
  2. java引用的C/C++中的方法,能够直接ctrl+左键进入
  3. 对于include的头文件或者库,也能够直接进入
  4. 不须要配置命令行操做,手动的生成头文件,不须要配置android.useDeprecatedNdk=true属性

普通Android项目转NDK开发项目

咱们以前说了,在建立新project时若勾选了Include C++ Support选项(需Android Studio版本不低于2.2),则该项目就已是一个NDK开发项目了。那么,若项目已经存在,该如何再转为NDK开发项目呢?

Tips: 在配置好NDK的前提下。且各类地方的配置均再也不赘述。如Android.mk中如何配置、CMakeLists.txt文件中的配置、各个地方的统一等。

传统JNI方式,在NDK开发 从入门到放弃(一:基本流程入门了解)中咱们了解过:

  1. 新建jni目录,写好C/C++代码。静态注册JNI时咱们使用了javah -jni对JAVA类进行操做自动生成了jni目录以及对应的头文件(事实上,当咱们有必定经验后能够本身写,而再也不须要使用该辅助命令来保证不写错,另外动态注册也是一个很值得提倡的方式),而后根据头文件写了C/C++代码。但在动态注册JNI时咱们能够本身先建立好jni目录且写好C/C++代码。
  2. 在jni目录下建立且配置好Android.mk和Application.mk两个文件。
  3. build.gradle文件中根据状况进行配置,可不进行配置使用默认值。
  4. 经过ndk-build操做,咱们能获得对应的so文件,放置在相应位置,java代码中便可调用C/C++代码,运行程序。

回顾前面提到的CMake方式的NDK开发,咱们获得以下步骤:

  1. 新建cpp目录,写好C/C++代码。
  2. 建立且配置CMakeLists.txt文件。
  3. build.gradle文件中根据状况进行配置,CMakeLists.txt文件的路径必须配置。
  4. java代码中便可调用C/C++代码,运行程序。
  5. project的build.gradle文件中,gradle版本不能低于2.2,不然会报错。

Error: Could not find method externalNativeBuild() for arguments  [build_e8k5d0w74qu1ajxjrrcr9snog$_run_closure1$_closure6@1398219d] on  project ‘:app’ of type org.gradle.api.Project.。

相关文章
相关标签/搜索