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.。

相關文章
相關標籤/搜索