1. 程式人生 > >AndroidStudio3.0開發除錯安卓NDK的C++程式碼

AndroidStudio3.0開發除錯安卓NDK的C++程式碼

一、新建專案

新建專案,沒有發現Include C++ Support 選項。因為印象中是有過該選項的,找了半天沒找到。

後來無意間拖了下視窗大小,原來是被隱藏了,真特麼坑。

新建一個測試專案,勾選Include C++ Support 選項,看看工程上有哪些不同。

1、gradle

首先看gradle檔案,android節點下新增:

externalNativeBuild {
    cmake {
        path "CMakeLists.txt"
    }
}

defaultConfig節點下新增:

externalNativeBuild {
    cmake {
        cppFlags "-std=c++14"
} }

2、CPP

與Java節點同級多了一個cpp的節點,對應目錄為src\main\cpp,與src\main\java同級,預設只有一個native-lib.cpp檔案,沒有.mk檔案及其他,比較簡單:

#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring

JNICALL
Java_com_bigsing_myapplication_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */
) { std::string hello = "Hello from C++"; return env->NewStringUTF(hello.c_str()); }

3、CMakeLists.txt

在app目錄下多了一個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} )

其中native-lib為最終生成的SO的名稱(libnative-lib.so),預設CPU為armeabi-v7a

預設的工程屬性不用配置,debugger預設為auto會自動適配,直接在cpp裡下斷點,除錯方式執行App,會自動斷下,變數數值均能在除錯狀態下看到。

試用了下AndroidStudio對NDK的除錯支援的還不錯,於是打算把過去的專案也支援起來,方法請看下節。

二、已有專案

1、安裝C++偵錯程式LLDB

由於之前一直沒有使用過AndroidStudio除錯過native的程式碼,網上了解到AndroidStudio除錯NDK是需要一個LLDB的外掛,預設是沒有的,所以先手動安裝一下。

這裡有個另類的方法:“Edit Configurations”開啟程式配置,在debugger裡選擇Native(預設為auto),然後執行App,因為工程之前一直是隻有Java程式碼的,所以這裡選擇了Native,AndroidStudio會提示並沒有安裝C++的偵錯程式,根據提示安裝即可。

可以看出,安裝的偵錯程式是LLDB。

在老專案裡面新增NDK的支援,可以右鍵專案選擇選單:Link C++ Project with Gradle

編譯方式有兩種:CMake和ndk-build,其中ndk-build是傳統方式,AndroidStudio預設推薦CMake方式,也許這是以後的主流方式,所以我們選擇預設的CMake.

然後是指定CMakeLists.txt檔案的路徑,這裡可以複製新建專案的CMakeLists.txt檔案到現有專案的app目錄下,把它放到和proguard-rules.pro相同的資料夾下即可。然後把這個CMakeLists.txt檔案的全路徑輸入進去,點OK。

這個時候會發現gradle檔案自動添加了:

externalNativeBuild {
    cmake {
        path "CMakeLists.txt"
    }
}

但是並未指定C++的版本,可以參考新建專案的內容手動新增:

externalNativeBuild {
    cmake {
        cppFlags "-std=c++14"
    }
}

3、整理C++原始碼的檔案組織形式

新建一個cpp目錄:src\main\cpp,與src\main\java同級,把C++原始碼檔案移動至此目錄下,並有序組織好。

4、修改CMakeLists.txt

由於是複製的demo工程的CMakeLists.txt檔案,比較簡單,不能夠滿足現有工程,需要修改一下。這裡說一下常用的幾個功能:
- 設定其他字尾檔案(例如.S彙編檔案)為可編譯原始檔:

set_property(SOURCE src/main/cpp/art/art_quick_dexposed_invoke_handler.S PROPERTY LANGUAGE C)
  • 設定多個不定數量的原始檔(也即使用*星號萬用字元的方式):
file(GLOB native_srcs "src/main/cpp/*.cpp" "src/main/cpp/dalvik/*.cpp" "src/main/cpp/art/*.cpp" "src/main/cpp/art/*.S")
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).
             ${native_srcs}
            )
  • 連結三方SO庫檔案(例如我需要使用三方的libsubstrate.so庫做測試):
file(GLOB libs src/main/cpp/3rd/libsubstrate.so src/main/cpp/3rd/libsubstrate-dvm.so)
target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${libs}
                       ${log-lib} )

5、恢復debugger為預設的auto

Edit Configurations”開啟程式配置,在debugger裡選擇auto,因為之前修改為了Native。這樣,無論是Java程式碼還是C++程式碼均可以除錯了。

三、CMakeLists.txt配置及學習資源

四、總結

  • 能支援對C++程式碼的動態除錯,無疑是非常強大的功能,關鍵現在AndroidStudio對C++程式碼在編輯器也支援的很好,所以總體是建議遷移過來的。

  • 不足就是編譯速度太慢了,VisualStudio編譯下來秒間就能完成了,AndroidStudio下要十幾秒甚至更長。在除錯的時候啟動LLDB也很慢,有時一直卡在Starting LLDB server

  • 建議VS和本方法結合使用,需要除錯的時候就用AndroidStudio除錯,如果僅僅是編譯C++程式碼則可以使用VS,VS的方法參見:使用VisualStudio高效開發除錯AndroidNDK