前言
自Android Studio 2.2發(fā)布之后梢莽,AS開始支持CMake構(gòu)建工具編譯構(gòu)建原生代碼庫,谷歌推薦使用CMake來構(gòu)建新建的原生庫奸披,不過為了兼顧老項(xiàng)目昏名,AS還是支持ndk-build構(gòu)建,除此之外源内,谷歌還推出了實(shí)驗(yàn)性Gradle插件來構(gòu)建原生庫葡粒,至此AS工具支持3種方式來構(gòu)建原生庫。
實(shí)驗(yàn)性Gradle插件由于依賴開發(fā)中的Gradle API膜钓,所以它是不穩(wěn)定的嗽交,不過谷歌稱Android Studio團(tuán)隊(duì)會繼續(xù)支持實(shí)驗(yàn)性Gradle插件,谷歌希望將來該插件能取代當(dāng)前的Gradle插件颂斜,因?yàn)槠渚o密集成的特性對于C/C++開發(fā)者更為便利夫壁,例如,更靈活的依賴管理沃疮。因此盒让,對于想在IDE與構(gòu)建系統(tǒng)之間建立最靈活的接口的開發(fā)者,可以嘗試使用實(shí)驗(yàn)性Gradle插件司蔬。
這里主要介紹下谷歌推薦的方式—Cmake邑茄。
PS:以下內(nèi)容主要來自谷歌官方文檔。
1俊啼、CMake
1.1肺缕、構(gòu)建工具準(zhǔn)備
- 下載NDK:Android C/C++代碼工具集
- 下載Cmake:外部構(gòu)建工具
- 下載LLDB:Android Studio 上面調(diào)試本地代碼的工具
使用 SDK Manager 來安裝上述組件:
- 打開一個(gè)項(xiàng)目,從菜單欄中選擇 Tools > Android > SDK Manager。
- 點(diǎn)擊 SDK Tools 選項(xiàng)卡同木。
- 勾選 LLDB浮梢,CMake 和 NDK。如圖:
1.2 創(chuàng)建 CMake 構(gòu)建腳本
創(chuàng)建一個(gè)CMakeList.txt構(gòu)建腳本文件彤路,然后用CMake命令來配置腳本文件秕硝。
為了讓 CMake 將源代碼(native source code)編譯成 native library。需要在編譯文件中添加 cmake_minimum_required() 和 add_library() 命令:
# 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 )
當(dāng)使用 add_library()洲尊,將一個(gè)源文件(source file)或庫添加到 CMake 構(gòu)建腳本远豺,同步項(xiàng)目,然后 Android studio 將關(guān)聯(lián)的頭文件也顯示了颊郎。然而憋飞,為了讓 CMake 在編譯時(shí)期能定位到頭文件,需要在 CMake 構(gòu)建腳本中添加 include_directories() 命令姆吭,并指定頭文件路徑:
add_library(...)
# Specifies a path to native header files.
include_directories(src/main/cpp/include/)
1.3榛做、添加 NDK APIs
Android NDK 提供了一些有用的 native APIs。將 NDK librarys 添加到 CMakeLists.txt 腳本文件中内狸,就可以使用這些 API 了检眯。
預(yù)編譯的 NDK librarys 已經(jīng)存在在 Android 平臺中了,所以你不需要編譯它們昆淡,或者是將其打包到你的 APK 中锰瘸。因?yàn)檫@些 NDK librarys 已經(jīng)是 CMake 搜索路徑的一部分,你甚至不需要提供你本地安裝的 NDK 路徑昂灵。你只需要向 CMake 提供你想使用的 library 名字避凝。
將 find_library() 命令添加到你的 CMake 構(gòu)建腳本中,這樣就可以定位 NDK library 的位置眨补,并將其位置存儲在一個(gè)變量之中管削。你可以在構(gòu)建腳本的其他地方使用這個(gè)變量,來代指 NDK library撑螺。下面的示例代碼將 Android-specific log support library 的位置存儲到變量 log-lib 中:
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 )
NDK 同樣也包含一些只包含源碼的 library含思,這些就需要你去編譯,然后鏈接到你的本地庫(native library)甘晤。你可以在 CMake 構(gòu)建腳本中使用 add_library() 命令將源碼編譯進(jìn)本地庫含潘。這時(shí)就需要提供你的本地 NDK 安裝路徑,通常將該路徑保存在 ANDROID_NDK 變量中线婚,這樣 Android Studio 可以自動為你識別
下面的命令告訴 CMake 去構(gòu)建 android_native_app_glue.c遏弱,這個(gè)命令可以管理 NativeActivity 的生命周期以及點(diǎn)擊輸入,并將其導(dǎo)入靜態(tài)庫中塞弊,然后將其鏈接至 native-lib:
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} )
1.4腾窝、添加其他的預(yù)編譯庫
添加預(yù)編譯庫和添加本地庫(native library)類似缀踪。由于預(yù)編譯庫是已經(jīng)構(gòu)建好的,你想就要使用 IMPORTED 標(biāo)志去告訴 CMake 虹脯,你只需要將其導(dǎo)入到你的項(xiàng)目中即可:
add_library( imported-lib
SHARED
IMPORTED )
然后你需要使用 set_target_properties()
命令去指定庫的路徑,就像下面的代碼那樣奏候。
一些庫會根據(jù)不同的 CPU 使用不同的包循集,或者是 Application Binary Interfaces(ABI)
,并且將他們歸類到不同的目錄中蔗草。這樣做的好處是咒彤,可以充分發(fā)揮特定的 CPU 架構(gòu)。你可以使用 ANDROID_ABI
路徑變量咒精,將多個(gè) ABI 版本的庫添加到你的 CMake 構(gòu)建腳本中镶柱。這個(gè)變量使用了一些 NDK 默認(rèn)支持的 ABI,以及一些需要手動配置到 Gradle 的 ABI模叙,比如:
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í)期能找到你的頭文件歇拆,你需要使用 include_directories() 命令,并且將你的頭文件地址傳進(jìn)去:
nclude_directories( imported-lib/include/ )
在 CMake 構(gòu)建腳本中使用 target_link_libraries() 命令范咨,將預(yù)構(gòu)建庫與你本地庫相關(guān)聯(lián):
target_link_libraries( native-lib imported-lib app-glue ${log-lib} )
當(dāng)你構(gòu)建你的 APP 的時(shí)候故觅,Gradle 會自動將導(dǎo)入的庫打包到你的 APK 中。你可以使用 APK Analyzer 來檢查渠啊。
1.5输吏、關(guān)聯(lián)本地庫與 Gradle
為了將本地庫與 Gradle 相關(guān)聯(lián),你需要在 CMake 或 ndk-build 構(gòu)建腳本中提供一個(gè)路徑地址替蛉。當(dāng)你構(gòu)建你的 APP 時(shí)贯溅,Gradle 會將 CMake 或 ndk-build 作為一個(gè)依賴運(yùn)行,然后將共享庫(.so 文件)打包到你的 APK 中躲查。
1.5.1它浅、使用 Android Studio 圖形化界面
- 打開 IDE 左邊的 Project 面板,選擇 Android 視圖熙含。
- 右鍵點(diǎn)擊你想鏈接本地庫的 module罚缕,比如 app module,然后從菜單中選擇 Link C++ Project with Gradle怎静。你應(yīng)該能看見一個(gè)和下圖很像的對話框邮弹。
- 在下拉菜單中,選擇 CMake 或者 ndk-build蚓聘。
a. 如果你選擇 CMake腌乡,需要在 Project Path 中指定 CMakeLists.txt 腳本文件的路徑。
b. 如果你選擇 ndk-build夜牡,你需要在 Project Path 中指定 Android.mk 腳本文件的路徑与纽。
1.6侣签、手動配置 Gradle
如果要手動將 Gradle 與你的本地庫相關(guān)聯(lián),你需要在 module 層級的 build.gradle 文件中添加 externalNativeBuild {} 代碼塊急迂,并且在該代碼塊中配置 cmake {} 或 ndkBuild {}:
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"
}
}
}
1.6.1影所、可選配置
你可以在你的 module 層級的 build.gradle 文件中的 defaultConfig {} 代碼塊中,添加 externalNativeBuild {} 代碼塊僚碎,為 CMake 或 ndk-build 配置一些額外參數(shù)猴娩。當(dāng)然,你也可以在你的構(gòu)建配置中勺阐,為其他每一個(gè)生產(chǎn)渠道重寫這些屬性卷中。
比如,如果你的 CMake 或者 ndk-build 項(xiàng)目中定義了多個(gè)本地庫渊抽,你想在某個(gè)生產(chǎn)渠道使用這些本地庫中的幾個(gè)蟆豫,你就可以使用 targets 屬性來構(gòu)建和打包。下面的代碼展示了一些你可能會用到的屬性:
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 "-DCMAKE_VERBOSE_MAKEFILE=TRUE"
// 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"
}
}
}
}
// You use this block to link Gradle to your CMake or ndk-build script.
externalNativeBuild {
cmake {...}
// or ndkBuild {...}
}
}
1.6.2懒闷、指定 ABI
如果你想 Gradle 構(gòu)建并打包某個(gè)特定的 ABI 十减。你可以在你的 module 層級的 build.gradle 文件中使用 ndk.abiFilters 標(biāo)簽來指定他們:
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ù)情況,你只需要像上面的代碼那樣毛雇,在 ndk {} 代碼塊中指定 abiFilters 即可嫉称。如果你想控制 Gradle 構(gòu)建、依賴你希望的東西灵疮,你就需要在 defaultConfig.externalNativeBuild.cmake {} 代碼塊或 defaultConfig.externalNativeBuild.ndkBuild {} 代碼塊中织阅,配置其他的 abiFilters 標(biāo)簽。Gradle 會構(gòu)建這些 ABI 配置震捣,但是只會將 defaultConfig.ndk {} 代碼塊中指定的東西打包到 APK中荔棉。
官方文檔:
https://developer.android.com/studio/projects/add-native-code.html#create-cmake-script
推薦一篇不錯(cuò)的相關(guān)文章:
http://blog.csdn.net/mabeijianxi/article/details/68525164
2、ndk-build
ndk-build這里不做詳細(xì)介紹蒿赢,請自行查看官方文檔:
https://developer.android.com/ndk/guides/ndk-build.html
3润樱、experimental-gradle-plugin
experimental-gradle-plugin這里不做詳細(xì)介紹,請自行查看官方文檔:
http://tools.android.com/tech-docs/new-build-system/gradle-experimental
官方網(wǎng)址可能打不開羡棵,可查看轉(zhuǎn)載網(wǎng)址:
http://www.cnblogs.com/tanlon/p/4731283.html