1.cmake是什么? CMake是一個(gè)跨平臺(tái)的安裝(編譯)工具,可以用簡(jiǎn)單的語(yǔ)句來(lái)描述所有平臺(tái)的安裝(編譯過(guò)程)。他能夠輸出各種各樣的makefile或者project文件,能測(cè)試編譯器所支持的C++特性,類似UNIX下的automake。
谷歌從AndroidStudio2.2以上就添加了Cmake方式來(lái)編譯NDK代碼,并從NDK例子看出,默認(rèn)編譯的方式就是cmake方式。
2.谷歌官方的用cmake方式編譯NDK的教程
谷歌從AndroidStudio2.2以上就添加了Cmake方式來(lái)編譯NDK代碼,并從NDK例子看出,默認(rèn)編譯的方式就是cmake方式。 如果您希望向現(xiàn)有項(xiàng)目添加原生代碼,請(qǐng)執(zhí)行以下步驟:
配置完項(xiàng)目后,您可以使用 JNI 框架從 Java 代碼中訪問(wèn)您的原生函數(shù)。要構(gòu)建和運(yùn)行應(yīng)用,只需點(diǎn)擊 Run 。Gradle 會(huì)以依賴項(xiàng)的形式添加您的外部原生構(gòu)建流程,用于編譯、構(gòu)建原生庫(kù)并將其隨 APK 一起封裝。 創(chuàng)建新的原生源文件要在應(yīng)用模塊的主源代碼集中創(chuàng)建一個(gè)包含新建原生源文件的
創(chuàng)建 CMake 構(gòu)建腳本如果您的原生源文件還沒(méi)有 CMake 構(gòu)建腳本,則您需要自行創(chuàng)建一個(gè)并包含適當(dāng)?shù)?CMake 命令。CMake 構(gòu)建腳本是一個(gè)純文本文件,您必須將其命名為 注:如果您的項(xiàng)目使用 ndk-build,則不需要?jiǎng)?chuàng)建 CMake 構(gòu)建腳本。提供一個(gè)指向您的 要?jiǎng)?chuàng)建一個(gè)可以用作 CMake 構(gòu)建腳本的純文本文件,請(qǐng)按以下步驟操作:
現(xiàn)在,您可以添加 CMake 命令,對(duì)您的構(gòu)建腳本進(jìn)行配置。要指示 CMake 從原生源代碼創(chuàng)建一個(gè)原生庫(kù),請(qǐng)將 # Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.
cmake_minimum_required(VERSION 3.4.1)
# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add.library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.
add_library( # Specifies 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 )
使用 add_library(...)
# Specifies a path to native header files.
include_directories(src/main/cpp/include/)
CMake 使用以下規(guī)范來(lái)為庫(kù)文件命名:
例如,如果您在構(gòu)建腳本中指定“native-lib”作為共享庫(kù)的名稱,CMake 將創(chuàng)建一個(gè)名稱為 static {
System.loadLibrary(“native-lib”);
}
注:如果您在 CMake 構(gòu)建腳本中重命名或移除某個(gè)庫(kù),您需要先清理項(xiàng)目,Gradle 隨后才會(huì)應(yīng)用更改或者從 APK 中移除舊版本的庫(kù)。要清理項(xiàng)目,請(qǐng)從菜單欄中選擇 Build > Clean Project。 Android Studio 會(huì)自動(dòng)將源文件和標(biāo)頭添加到 Project 窗格的 cpp 組中。使用多個(gè) 添加 NDK APIAndroid NDK 提供了一套實(shí)用的原生 API 和庫(kù)。通過(guò)將 NDK 庫(kù)包含到項(xiàng)目的 預(yù)構(gòu)建的 NDK 庫(kù)已經(jīng)存在于 Android 平臺(tái)上,因此,您無(wú)需再構(gòu)建或?qū)⑵浞庋b到 APK 中。由于 NDK 庫(kù)已經(jīng)是 CMake 搜索路徑的一部分,您甚至不需要在您的本地 NDK 安裝中指定庫(kù)的位置 - 只需要向 CMake 提供您希望使用的庫(kù)的名稱,并將其關(guān)聯(lián)到您自己的原生庫(kù)。 將 find_library( # Defines the name of the path variable that stores the
# location of the NDK library.
log-lib
# Specifies the name of the NDK library that
# CMake needs to locate.
log )
為了確保您的原生庫(kù)可以在 find_library(...)
# Links your native library against one or more other native libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the log library to the target library.
${log-lib} )
NDK 還以源代碼的形式包含一些庫(kù),您在構(gòu)建和關(guān)聯(lián)到您的原生庫(kù)時(shí)需要使用這些代碼。您可以使用 CMake 構(gòu)建腳本中的 以下命令可以指示 CMake 構(gòu)建 add_library( app-glue
STATIC
${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c )
# You need to link static libraries against your shared native library.
target_link_libraries( native-lib app-glue ${log-lib} )
添加其他預(yù)構(gòu)建庫(kù)添加預(yù)構(gòu)建庫(kù)與為 CMake 指定要構(gòu)建的另一個(gè)原生庫(kù)類似。不過(guò),由于庫(kù)已經(jīng)預(yù)先構(gòu)建,您需要使用 add_library( imported-lib
SHARED
IMPORTED )
然后,您需要使用 某些庫(kù)為特定的 CPU 架構(gòu)(或應(yīng)用二進(jìn)制接口 (ABI))提供了單獨(dú)的軟件包,并將其組織到單獨(dú)的目錄中。此方法既有助于庫(kù)充分利用特定的 CPU 架構(gòu),又能讓您僅使用所需的庫(kù)版本。要向 CMake 構(gòu)建腳本中添加庫(kù)的多個(gè) ABI 版本,而不必為庫(kù)的每個(gè)版本編寫多個(gè)命令,您可以使用 add_library(...)
set_target_properties( # Specifies the target library.
imported-lib
# Specifies the parameter you want to define.
PROPERTIES IMPORTED_LOCATION
# Provides the path to the library you want to import.
imported-lib/src/${ANDROID_ABI}/libimported-lib.so )
為了確保 CMake 可以在編譯時(shí)定位您的標(biāo)頭文件,您需要使用 include_directories( imported-lib/include/ ) 注:如果您希望封裝一個(gè)并不是構(gòu)建時(shí)依賴項(xiàng)的預(yù)構(gòu)建庫(kù)(例如在添加屬于 要將預(yù)構(gòu)建庫(kù)關(guān)聯(lián)到您自己的原生庫(kù),請(qǐng)將其添加到 CMake 構(gòu)建腳本的 target_link_libraries( native-lib imported-lib app-glue ${log-lib} ) 在您構(gòu)建應(yīng)用時(shí),Gradle 會(huì)自動(dòng)將導(dǎo)入的庫(kù)封裝到 APK 中。您可以使用 APK 分析器驗(yàn)證 Gradle 將哪些庫(kù)封裝到您的 APK 中。如需了解有關(guān) CMake 命令的詳細(xì)信息,請(qǐng)參閱 CMake 文檔。
導(dǎo)入.a靜態(tài)庫(kù) 自 android studio 2.2 +后就集成了ndk開(kāi)發(fā), 自帶cmake 編譯器. 編寫ndk時(shí)候,配置很簡(jiǎn)單。再也不需要用android.mk配置文件。 新建一個(gè)帶ndk開(kāi)發(fā)項(xiàng)目的結(jié)構(gòu)是這樣的,
言歸正傳,那么要添加第三方的xx.a鏈接庫(kù)呢? 通常我們把第三方提供的h文件夾,放在cpp的include里面。這是規(guī)范,不是必須。而xxx.a庫(kù)放在src/main/jniLibs/armeabi目錄下。 本文章以添加libjsoncpp.a連接庫(kù)做例子 首先在cpp目錄下建立一個(gè)include文件夾,把jsoncpp官方提供的頭文件文件夾拷貝到include里面(我這個(gè)項(xiàng)目有3個(gè)鏈接庫(kù),jsoncpp, curl , openssl,另外2個(gè)僅做參考作用,與其無(wú)關(guān))
第二步, 在app的src目錄的main下,建立一個(gè)文件夾,jniLibs,然后在jniLibs里面再建立一個(gè)armeabi文件夾。 然后把libjsoncpp.a鏈接庫(kù)拷貝進(jìn)去。
第三步, 動(dòng)態(tài)庫(kù)與頭文件拷貝進(jìn)去時(shí)候,是需要告訴編譯器做關(guān)聯(lián)的。在app目錄的src文件夾下有個(gè)CMakeLists.txt文件,我們通過(guò)它編寫配置信息。 將jsoncpp頭文件所在目錄告訴編譯,在里面添加
如果有多個(gè)鏈接庫(kù),那么可以這樣
然后告訴編譯器,libjsoncppp.a在哪個(gè)目錄下,并指定鏈接庫(kù)的名稱 接著添加
然后修改target_link_libraries,加多一行jsoncpp
如果有多個(gè),那么可以多次添加。如
將 Gradle 關(guān)聯(lián)到您的原生庫(kù)要將 Gradle 關(guān)聯(lián)到您的原生庫(kù),您需要提供一個(gè)指向 CMake 或 ndk-build 腳本文件的路徑。在您構(gòu)建應(yīng)用時(shí),Gradle 會(huì)以依賴項(xiàng)的形式運(yùn)行 CMake 或 ndk-build,并將共享的庫(kù)封裝到您的 APK 中。Gradle 還使用構(gòu)建腳本來(lái)了解要將哪些文件添加到您的 Android Studio 項(xiàng)目中,以便您可以從 Project 窗口訪問(wèn)這些文件。如果您的原生源文件沒(méi)有構(gòu)建腳本,則需要先創(chuàng)建 CMake 構(gòu)建腳本,然后再繼續(xù)。 將 Gradle 關(guān)聯(lián)到原生項(xiàng)目后,Android Studio 會(huì)更新 Project 窗格以在 cpp 組中顯示您的源文件和原生庫(kù),在 External Build Files 組中顯示您的外部構(gòu)建腳本。 注:更改 Gradle 配置時(shí),請(qǐng)確保通過(guò)點(diǎn)擊工具欄中的 Sync Project 應(yīng)用更改。此外,如果在將 CMake 或 ndk-build 腳本文件關(guān)聯(lián)到 Gradle 后再對(duì)其進(jìn)行更改,您應(yīng)當(dāng)從菜單欄中選擇 Build > Refresh Linked C++ Projects,將 Android Studio 與您的更改同步。 使用 Android Studio UI您可以使用 Android Studio UI 將 Gradle 關(guān)聯(lián)到外部 CMake 或 ndk-build 項(xiàng)目:
手動(dòng)配置 Gradle要手動(dòng)配置 Gradle 以關(guān)聯(lián)到您的原生庫(kù),您需要將 android {
...
defaultConfig {...}
buildTypes {...}
// Encapsulates your external native build configurations.
externalNativeBuild {
// Encapsulates your CMake build configurations.
cmake {
// Provides a relative path to your CMake build script.
path "CMakeLists.txt"
}
}
}
注:如果您想要將 Gradle 關(guān)聯(lián)到現(xiàn)有 ndk-build 項(xiàng)目,請(qǐng)使用 指定可選配置您可以在模塊級(jí) 例如,如果您的 CMake 或 ndk-build 項(xiàng)目定義多個(gè)原生庫(kù),您可以使用 android {
...
defaultConfig {
...
// This block is different from the one you use to link Gradle
// to your CMake or ndk-build script.
externalNativeBuild {
// For ndk-build, instead use ndkBuild {}
cmake {
// Passes optional arguments to CMake.
arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"
// Sets optional flags for the C compiler.
cFlags "-D_EXAMPLE_C_FLAG1", "-D_EXAMPLE_C_FLAG2"
// Sets a flag to enable format macro constants for the C++ compiler.
cppFlags "-D__STDC_FORMAT_MACROS"
}
}
}
buildTypes {...}
productFlavors {
...
demo {
...
externalNativeBuild {
cmake {
...
// Specifies which native libraries to build and package for this
// product flavor. If you don't configure this property, Gradle
// builds and packages all shared object libraries that you define
// in your CMake or ndk-build project.
targets "native-lib-demo"
}
}
}
paid {
...
externalNativeBuild {
cmake {
...
targets "native-lib-paid"
}
}
}
}
// Use this block to link Gradle to your CMake or ndk-build script.
externalNativeBuild {
cmake {...}
// or ndkBuild {...}
}
}
要詳細(xì)了解配置產(chǎn)品風(fēng)味和構(gòu)建變體,請(qǐng)參閱配置構(gòu)建變體。如需了解您可以使用 指定 ABI默認(rèn)情況下,Gradle 會(huì)針對(duì) NDK 支持的 ABI 將您的原生庫(kù)構(gòu)建到單獨(dú)的 android {
...
defaultConfig {
...
externalNativeBuild {
cmake {...}
// or ndkBuild {...}
}
ndk {
// Specifies the ABI configurations of your native
// libraries Gradle should build and package with your APK.
abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a',
'arm64-v8a'
}
}
buildTypes {...}
externalNativeBuild {...}
}
在大多數(shù)情況下,您只需要在 為了進(jìn)一步降低 APK 的大小,請(qǐng)考慮配置 ABI APK 拆分,而不是創(chuàng)建一個(gè)包含原生庫(kù)所有版本的大型 APK,Gradle 會(huì)為您想要支持的每個(gè) ABI 創(chuàng)建單獨(dú)的 APK,并且僅封裝每個(gè) ABI 需要的文件。如果您配置 ABI 拆分,但沒(méi)有像上面的代碼示例一樣指定
谷歌從AndroidStudio2.2以上就添加了Cmake方式來(lái)編譯NDK代碼,并從NDK例子看出,默認(rèn)編譯的方式就是cmake方式。
|
|