Android NDK 編譯工具CMake的使用
-
- 1. 建立新 Android 項目
- 2.自定義C++的配置
- 3.分析項目結構
-
- 3.1 so庫/native方法
- 3.2 原生源檔案
- 3.3 建構配置
- 3.4 腳本配置
- 3.5 運作流程
- 參考資料
- Author
Android Studio 用于建構原生庫的預設工具是 CMake。由于很多現有項目都使用建構工具包編譯其原生代碼,Android Studio 還支援 ndk-build。不過,如果您在建立新的原生庫,則應使用 CMake。
建立支援原生代碼的項目與建立任何其他 Android Studio 項目類似,不過前者還需要額外幾個步驟:
1. 建立新 Android 項目
建立新的 Android 項目,需要選中 Include C++ Support 複選框,即支援C++的。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuUUQlIUOlcTRlkjQlETQlkTRlQDOlEUOlcTRlAjQlYTOlYTRlEkQlIkQlUTRlIUOlgDOlUTRlU2ah10Qvw1cjl2chJ0LcRWavJHZuF0LcJXZ0NXYt9CXjlGUkV3bsN0LcdmYulWYyJ0Lc12bj5CduVGdu92YyV2c1JWdoRXan5ydhJ3Lc9CX6MHc0RHaiojIsJye.png)
2.自定義C++的配置
依次
Next
後,
Create Android project
>
Target Android Devices
>
Add an Activity to Mobile
>
Configure Activity
>
Customize C++ Support
為了友善分析,Exceptions Support、Runtime Type Information Support 我們也同時勾選上,不過一般情況下可以不勾選。
在 Customize C++ Support中,我們可以自定義一下内容:
- C++ Standard :使用下拉清單選擇你希望使用哪種 C++ 标準。選擇 Toolchain Default 會使用預設的 CMake 設定。
- Exceptions Support :如果你希望啟用對 C++ 異常處理的支援,請選中此複選框。如果啟用此複選框,Android Studio 會将
标志添加到子產品級 build.gradle 檔案的 cppFlags 中,Gradle 會将其傳遞到 CMake。-fexceptions
- Runtime Type Information Support :如果你希望支援 RTTI,請選中此複選框。如果啟用此複選框,Android Studio 會将
标志添加到子產品級 build.gradle 檔案的 cppFlags 中,Gradle 會将其傳遞到 CMake。-frtti
3.分析項目結構
先切換視圖到
Project
友善檢視。
對比普通建立項目的内容,可以發現示例有4個地方發生了變化:
- 添加了
目錄,裡面有示例 C++ 源檔案cpp
,它的代碼裡面提供了一個簡單的 C++ 函數 stringFromJNI(),此函數可以傳回字元串“Hello from C++”。native-lib.cpp
-
中添加了兩個部分,一個負責加載so庫;一個則為native方法。MainActivity.java
-
中也添加了兩個部分,一個為C++添加異常處理、RTTI的處理的支援;一個則為CMake封裝建構配置,同時也提供一個相對路徑給CMake的建構腳本build.gradle
;CMakeLists.txt
- 添加了
腳本檔案,它的主要作用是定義了哪些檔案需要編譯以及和其他庫的關系,即輔助Cmake進行系列的操作。CMakeLists.txt
注:native相關方法去掉報紅
取消檢測即可,打開 Settings>Editor>Inspections>Android>Missing JNI function 去掉勾選。
新的項目完成建立後,我們可以清晰地看到結構及内容上的變化:
3.1 so庫/native方法
MainActivity.java
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}
下面說明一下相關的内容:
- System.loadLibrary(“native-lib”)負責加載動态的原生庫檔案,
為native-lib
中定義的library。CMakeLists.txt
CMake 使用以下規範來為庫檔案命名:
格式: lib庫名稱.so
注:如果你在建構腳本中指定“native-lib”作為共享庫的名稱,CMake 将建立一個名稱為
libnative-lib.so
的檔案。不過,在 Java 代碼中加載此庫時,請使用你在 CMake 建構腳本中指定的名稱。
- stringFromJNI為native方法與
的Java_com_brainbg_nkdcmakeall_MainActivity_stringFromJNI的相對應的。native-lib.cpp
3.2 原生源檔案
native-lib.cpp
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_brainbg_nkdcmakeall_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
其中
Java_com_brainbg_nkdcmakeall_MainActivity_stringFromJNI
是根據
MainActivity.java
的
stringFromJNI()
生成的,其格式如下:
格式:Java_包名_類名_方法名
3.3 建構配置
這部分主要是關于Cmake、C++相關的建構配置。
build.gradle
android {
defaultConfig {
......
//Exceptions Support(-fexceptions)、Runtime Type Information (-frtti) 建構關聯
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
}
}
}
//封裝CMake建構配置
externalNativeBuild {
//提供一個相對路徑給CMake建構腳本
cmake {
path "CMakeLists.txt"
}
}
}
對比ndk-build和CMake的配置
//CMake需要關聯CMakeLists.txt
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
//ndk-build需要關聯Android.mk
externalNativeBuild {
ndkBuild {
path file('jni/Android.mk')
}
}
3.4 腳本配置
CMakeLists.txt
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
上面的配置簡單說明下:
- cmake_minimum_required:CMake所需的最低版本要求,目前為3.4.1。
- add_library:
- Sets the name of the library:設定庫的名稱。例如指定
作為共享庫的名稱,那麼CMake 将建立一個名稱為native-lib
的庫檔案。libnative-lib.so
- Sets the library as a shared library:将庫設定為共享庫.
- Provides a relative path to your source file(s):提供源檔案的相對路徑
- Sets the name of the library:設定庫的名稱。例如指定
- find_library:
- target_link_libraries:
更多關于Cmake的用法可以檢視CMake文檔
3.5 運作流程
下面為官方NDK文檔的流程說明:
-
調用您的外部建構腳本Gradle
。CMakeLists.txt
-
按照建構腳本中的指令将 C++ 源檔案CMake
編譯到共享的對象庫中,并命名為native-lib.cpp
,Gradle 随後會将其打包到 APK 中。libnative-lib.so
- 運作時,應用的
會使用MainActivity
加載原生庫。現在,應用可以使用庫的原生函數System.loadLibrary()
。stringFromJNI()
-
調用MainActivity.onCreate()
,這将傳回“Hello from C++”并使用這些文字更新stringFromJNI()
。TextView
根據本人的了解,制作了一張簡單流程圖:
參考資料
https://github.com/googlesamples/android-ndk/tree/master/hello-libs
https://github.com/android-ndk/ndk
https://developer.android.google.cn/studio/projects/add-native-code.html#link-gradle
https://cmake.org/cmake/help/latest/index.html#
Author
作者:Brainbg(白雨)
GitHub:https://github.com/Brainbg
部落格:https://www.brainbg.com/
CSDN:https://blog.csdn.net/u014720022
簡書:https://www.jianshu.com/u/94518ede7100