認識NDK編譯

一. Android ABI

不同的 Android 設(shè)備使用不同的 CPU,而不同的 CPU 支持不同的指令集家破。CPU 與指令集的每種組合都有專屬的應(yīng)用二進制接口 Application Binary Interface ( ABI )抢呆,因此使用 NDK 生成在 Android 運行 .a 或 .so (都是二進制文件)就需要指定 ABI 叫榕。 目前 NDK 支持的 ABI 如下:

ABI 支持的指令集 CPU 架構(gòu) 應(yīng)用
armeabi-v7a armeabi 等 ARM 32 位 手機
arm64-v8a AArch64 等 ARM 64 位 手機
x86 x86 (IA-32) 等 x86 32 位 PC
x86_64 x86-64 等 x86 64 位 PC

NDK 17 前支持 ARMv5 (armeabi) 以及 32 位和 64 位 MIPS混巧,但 NDK r17 和 17 后不再支持细睡。

1. 指定 ABI
Gradle

默認情況下,Gradle(無論是通過 Android Studio 使用忍宋,還是從命令行使用)會針對所有非棄用 ABI 進行構(gòu)建瞄桨。要限制應(yīng)用支持的 ABI 集,可以使用 abiFilters讶踪。例如芯侥,要僅針對 64 位 ABI 進行構(gòu)建,可以在 build.gradle 中設(shè)置以下配置:

android {
    defaultConfig {
        ndk {
            abiFilters 'arm64-v8a', 'x86_64'
        }
    }
}
ndk-build

默認情況下乳讥,ndk-build 會針對所有非棄用 ABI 進行構(gòu)建柱查。可以通過在 Application.mk 文件中設(shè)置 APP_ABI 來定位特定 ABI云石。如下:

APP_ABI := arm64-v8a  # Target only arm64-v8a
APP_ABI := all  # Target all ABIs, including those that are deprecated.
APP_ABI := armeabi-v7a x86_64  # Target only armeabi-v7a and x86_64.

CMAKE

使用 CMake 時唉工,一次只能針對一個 ABI 進行構(gòu)建,并且必須明確指定 ABI汹忠。為此淋硝,如果需要使用 ANDROID_ABI ,則必須在命令行中指定(無法在 CMakeLists.txt 中設(shè)置)宽菜。例如:

$ cmake -DANDROID_ABI=arm64-v8a ...
$ cmake -DANDROID_ABI=armeabi-v7a ...
$ cmake -DANDROID_ABI=x86 ...
$ cmake -DANDROID_ABI=x86_64 ...
2. 在C/C++處理 CPU 功能區(qū)別 ABI

通常谣膳,在構(gòu)建時使用#ifdef 及以下各項確定 ABI 最為方便:

  • 對于 32 位 ARM ,使用 _ _ arm _ _
  • 對于 64 位 ARM,使用 _ _ aarch64 _ _
  • 對于 32 位 X86铅乡,使用 _ _ i386 _ _
  • 對于 64 位 X86继谚,使用 _ _ x86_64 _ _

二. 使用 NDK 構(gòu)建項目

使用 NDK 編譯代碼主要有三種方式:

  • 基于 Make 的 ndk-build。這種方式一般是配合 Android.mk 和 Application.mk 文件 是之前 Android Studio 使用的方式
  • CMake 阵幸。這種方式基于 CMakeLists.txt 文件花履,是現(xiàn)在 Android Studio 默認使用的方式
  • 獨立工具鏈 toolchain。這種方式常用于交叉編譯挚赊,常配合含有 configure 文件的項目的使用诡壁,例如 ffmpeg 編譯 so
1. NDK 主要目錄

NDK 編譯主要與下面幾個目錄有關(guān):

platforms

包含不同的 Android 版本目錄,每個 Android 版本目錄又包含 不同的 ABI 目錄荠割,在 ABI 目錄里面有 /usr/lib 目錄妹卿,包含常用的 .a 或 .so 庫,在 /usr/include 里包含需要的頭文件( ndk 16 后不保留頭文件)涨共。

sysroot

包含需要的 .a 或 .so 庫和頭文件纽帖,在 usr/lib 和 usr/include 和目錄下(ndk 16 后兩者都有,16和16前只有頭文件)举反。

toolchain

包含編譯(交叉編譯)工具鏈的目錄

build/tools

包含獨立編譯工具鏈腳本 make_standalone_toolchain.py 或者 make_standalone_toolchain.sh 懊直,其作用是根據(jù) Android API 和 ABI 集成目標系統(tǒng)庫,目標系統(tǒng)頭文件和編譯器在指定的一個目錄火鼻。當(dāng)然使用這個腳本也是可以的室囊,不過需要指定各個庫雕崩、頭文件的目錄,通常這些都不再一個目錄融撞,比較麻煩盼铁。使用 make_standalone_toolchain 的方式是:

--arch 指定 cpu 架構(gòu)  --api 指定系統(tǒng)版本 --install-dir 生成的編譯工具鏈目錄

例如
./make_standalone_toolchain.py \
        --arch arm --api 21 --install-dir /tmp/android-21-toolchain

在 NDK 19 開始就不需要使用獨立工具鏈了, 在 toolchains/llvm/ 下已經(jīng)提供好了編譯工具, 讀者自行去下載進入目錄看看,和獨立工具鏈編譯出來的結(jié)構(gòu)非常類似尝偎,不過它比較全的是針對不同平臺版本饶火。

2. 用獨立工具鏈編譯代碼

用獨立工具鏈編譯代碼的時需要指定下面幾個地方

  • 目標處理器架構(gòu),可以用 --arch 標記來完成
  • 目標系統(tǒng)頭文件(與 Android API 有關(guān))
  • 目標系統(tǒng)庫 (與 Android API 有關(guān))
  • 編譯器 gcc 還是 clang
    不同的 NDK 版本差異比較大致扯,因此有時候同一個 configure肤寝,替換不同的 NDK 版本就不能編譯,這其實可能是 NDK 差異導(dǎo)致的抖僵。一般的差異主要是
  • 目標系統(tǒng)庫和頭文件的目錄位置變化
  • 是否使用獨立編譯工具鏈腳本 make_standalone_toolchain.py 或者是 make_standalone_toolchain.sh 生成的目錄來指定庫和頭文件
  • ndk 編譯器 gcc or clang 的指定

3. 指定 NDK 提供的頭文件和庫

  • --sysroot=XX
    指定頭文件和庫鲤看,會到 XX/usr/include 目錄下查找頭文件和 XX/usr/lib 目錄下查找 .a 或者 .so 庫
  • -isysroot YY
    指定頭文件,覆蓋--sysroot的設(shè)置耍群,會到 YY/usr/include 目錄下查找頭文件
  • -isystem ZZ
    指定頭文件义桂,作補充,不覆蓋--sysroot的設(shè)置蹈垢,會到 ZZ (全路徑) 下查找頭文件
  • -I XX
    指定頭文件慷吊,優(yōu)先級高,不覆蓋--sysroot的設(shè)置耘婚,回到 XX (全路徑) 下查找頭文件
  • -LXX
    指定庫罢浇,會到 XX 目錄下查找?guī)?/li>
  • -lxx.xo
    指定庫陆赋,直接指定某個 so 庫沐祷。

查找優(yōu)先級 -I > isystem > isysroot

4. 不同 NDK 版本目標系統(tǒng)庫、頭文件和編譯器的差異

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末攒岛,一起剝皮案震驚了整個濱河市赖临,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌灾锯,老刑警劉巖兢榨,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異顺饮,居然都是意外死亡吵聪,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門兼雄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吟逝,“玉大人,你說我怎么就攤上這事赦肋】樵埽” “怎么了励稳?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長囱井。 經(jīng)常有香客問我驹尼,道長,這世上最難降的妖魔是什么庞呕? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任新翎,我火速辦了婚禮,結(jié)果婚禮上住练,老公的妹妹穿的比我還像新娘料祠。我一直安慰自己,他們只是感情好澎羞,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布髓绽。 她就那樣靜靜地躺著,像睡著了一般妆绞。 火紅的嫁衣襯著肌膚如雪顺呕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天括饶,我揣著相機與錄音株茶,去河邊找鬼。 笑死图焰,一個胖子當(dāng)著我的面吹牛启盛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播技羔,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼僵闯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了藤滥?” 一聲冷哼從身側(cè)響起鳖粟,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拙绊,沒想到半個月后向图,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡标沪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年榄攀,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片金句。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡檩赢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出趴梢,到底是詐尸還是另有隱情漠畜,我是刑警寧澤币他,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站憔狞,受9級特大地震影響蝴悉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瘾敢,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一拍冠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧簇抵,春花似錦庆杜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至典蜕,卻和暖如春断盛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背愉舔。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工钢猛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人轩缤。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓命迈,卻偏偏與公主長得像,于是被迫代替她去往敵國和親火的。 傳聞我的和親對象是個殘疾皇子壶愤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348