文章目錄
I . NDK platforms 目錄下的 函數庫
platforms 目錄下的函數庫:
1 . Android 版本目錄 : platforms 中存儲了各個 Android 版本編譯時需要的動態庫與靜態庫資源 , 如 android-29 中就是該版本對應的本地庫資源 ;
2 . CPU 架構目錄 :
在版本目錄下存儲的是不同的 CPU 處理器對應的庫版本 , 如 arm , x86 處理器 , 32 位 與 64 位 等不同版本對應的本地庫 ;
CPU 不同 , 其對應的指令集不同 , 相應編譯出的動態庫或靜態庫就不同 ;
3 . 函數庫目錄 :
在對應 CPU 目錄下的 usr\lib 目錄下 , 存儲了該 Android 版本對應的 CPU 版本的動態庫 與 靜態庫 ;
開發高性能音頻時使用的 libOpenSLES.so , 打印日誌使用的 liblog.so 庫 , 就是在該目錄下 ; 引入的 #include <android/log.h> 頭文件對應的方法邏輯實現就在 liblog.so 庫中 ;
II . Ubuntu 配置 NDK 交叉編譯環境
獨立使用 NDK 提供的交叉編譯工具 , 需要在 Ubuntu Linux 下執行 , 因此這裏我們下載 Linux 版本的 NDK ;
1 . NDK 下載地址 : https://developer.android.google.cn/ndk/downloads
歷史版本的 NDK 下載地址 : https://developer.android.google.cn/ndk/downloads/older_releases.html
2 . 下載完畢會後在 Ubuntu 中解壓文件 :
3 . 配置臨時環境變量 :
① 目的 : 該臨時環境變量 就是 NDK 中的交叉編譯工具的路徑 , 目的是方便調用 ;
② 執行指令 : export CC=/home/book/NDK/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc
③ CC 環境變量作用 : CC 是變量名 , 調用的時候使用 $CC main.c 即可調用上述路徑中的 arm-linux-androideabi-gcc 工具編譯 main.c 源文件 ;
④ 交叉編譯 : 上述路徑的編譯器就是在 Linux 中編譯 ARM CPU 指令集的函數庫 , 由於是在 X86 芯片上編譯 ARM 芯片的函數庫 , 因此該操作叫做交叉編譯 ;
4 . 嘗試交叉編譯 :
① main.c 源文件 :
#include <stdio.h>
int main(){
printf("main : test");
return 0;
}
② 嘗試編譯 : 調用 $CC main.c
命令嘗試編譯 main.c 程序 , 發現如下問題 ;
book@book-virtual-machine:~/NDK$ $CC main.c
main.c:1:19: fatal error: stdio.h: No such file or directory
#include <stdio.h>
^
compilation terminated.
book@book-virtual-machine:~/NDK$
③ 分析原因 : 此處需要提供 stdio.h 對應的頭文件與函數庫 , 上面連頭文件都沒有找到 , 需要我們來指定 ;
下面開始說明如何指定頭文件與庫文件 ;
III . 同時指定編譯的頭文件和庫文件
1 . 庫文件 : 交叉編譯需要的庫文件就是上述 NDK platforms 目錄下的 函數庫 ;
2 . --sysroot 頭文件與庫文件查找目錄設定 : 使用 --sysroot=XX
參數設置 ;
指定本次編譯的 頭文件 與 庫文件 , 系統會自動到 XX/usr/include 目錄下查找頭文件 , 到 XX/usr/lib 目錄下查找庫文件 ;
IV . 指定編譯的頭文件
1 . -isysroot 頭文件查找目錄設定 : 使用 -isysroot YY
參數設置 ;
指定頭文件查找目錄 , 系統還會自動到 YY/usr/include 目錄下查找頭文件 ;
注意 : 該配置會覆蓋 --sysroot=XX
參數查找頭文件的配置 ;
2 . 同時設置 --sysroot=XX -isysroot=YY
情況 :
如果同時設置了 --sysroot=XX -isysroot=YY
兩個參數 ,
會去 XX/usr/lib 目錄下找庫文件 ,
到 YY/usr/include 目錄下查找頭文件 ;
( 此時不再去 XX/usr/include 目錄下查找頭文件 )
3 . -isystem 設置頭文件查找路徑 : 使用 -isystem ZZ
參數設置 ;
設置後系統會直接去 ZZ 目錄下查找頭文件 ;
4 . -isysroot 與 -isystem 區別 :
兩種參數配置的查找路徑不同 ,
-isysroot 設定會去設定的目錄下的 usr/include 目錄下查找 .
-isystem 會直接到設置的目錄下查找 ;
5 . -I 頭文件查找目錄 : 使用 -isystem KK
參數設置 ;
設置後系統會直接去 KK 目錄下查找頭文件 ;
6 . 頭文件目錄查找優先級 :
優先級從高到底 : -I > -isystem > -isysroot
V . 指定編譯的庫文件
1 . -L 指定庫文件查找目錄 : 使用 -L AA
參數設置 ;
設置該參數後 , 編譯時系統會自動到 AA 目錄下查找函數庫 ;
2 . -l 指定鏈接的庫名稱 : 使用 -l libxxx.so
參數設置 ;
設置該參數後 , 系統會按照該路徑加載該 libxxx.so 函數庫 ;
VI . 指定編譯的頭文件與庫文件 示例
1 . 設置臨時環境變量 :
export CC=/home/book/NDK/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc
2 . NDK 頭文件與庫文件的目錄 :
( 這裏以 android-21 版本 ARM CPU 爲例 )
① NDK 庫文件目錄 :
/home/book/NDK/android-ndk-r17c/platforms/android-21/arch-arm/user/lib
② NDK 庫頭文件目錄 :
/home/book/NDK/android-ndk-r17c/sysroot/usr/include
/home/book/NDK/android-ndk-r17c/sysroot/usr/include/arm-linux-androideabi/asm
3 . 最終的指定頭文件與函數庫的編譯指令 :
$CC --sysroot=/home/book/NDK/android-ndk-r17c/platforms/android-21/arch-arm -isystem /home/book/NDK/android-ndk-r17c/sysroot/usr/include -isystem /home/book/NDK/android-ndk-r17c/sysroot/usr/include/arm-linux-androideabi -pie main.c
命令解析 :
① $CC : arm-linux-androideabi-gcc 交叉編譯工具的臨時環境變量 , 執行 $CC 相當於執行 /home/book/NDK/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc 命令 ;
② 指定函數庫 :
–sysroot=/home/book/NDK/android-ndk-r17c/platforms/android-21/arch-arm
指定函數庫目錄 , 必須這麼寫 , 因爲真正要查找的是下層目錄中的 usr/lib 目錄 ;
③ 指定頭文件 : 這裏使用的是 -isystem , 不是 -isysroot , 因此目錄可以寫的隨意一些 ;
-isystem /home/book/NDK/android-ndk-r17c/sysroot/usr/include
-isystem /home/book/NDK/android-ndk-r17c/sysroot/usr/include/arm-linux-androideabi
isysroot 指定的頭文件必須在 usr/include 中 , -isystem 不必 ;
④ 指定需要在 Android 手機執行配置 : -pie
4 . 編譯結果 :
該編譯出的 a.out 可執行文件 , 可以在 Android 手機中 , 使用命令行執行 ;
手機必須 root 纔可以執行 , 普通手機不能執行 ;