田海立@CSDN 2020-11-25html
Android NDK(Native Development Kit)提供了一套基於c/c++開發Android應用的工具。基於c/c++開發須要STL (Standard Template Library/標準模版庫),本文描述Android NDK中提供的STL。android
- Android NDK開發是基於Android的,可是不綁定具體某一個Android版本,一個NDK發佈版能夠支持多個Android版本。
- NDK開發不管靜態庫仍是動態庫,libc++都是用NDK裏的發佈版本打包在應用裏:動態庫直接在apk裏帶上libc++_shared.so;靜態庫已經把程序須要的STL的代碼直接打到應用程序或其所用的native庫裏。
1、Android NDK中的c++運行庫
Android NDK中提供下列c++運行庫。c++
其中的各個運行庫:bash
- libc++:是LLVM c++標準庫。從NDK r18以後是惟一的STL(GNU stl和stlport從 r18開始從NDK中被移除)
NDK裏提供了libc++的動態庫和靜態庫:
- 動態庫: libc++_shared.so
- 靜態庫: libc++_static.a
注意: 雖然都是LLVM的c++ STL,此處NDK裏的libc++不是Android源碼中編譯出的c++系統STL(libc++.so),此處的libc++是基於NDK開發時,NDK中已經編譯好的庫。若是NDK開發的應用用到libc++_shared.so, .so會被打包到編譯出的APK裏;用到libc++_static.a, .a裏被用到的程序會被打到使用者的程序中的。也就是發佈應用時,會帶着stl一塊兒發佈,不依賴Android版本內部的stl。 - system:非徹底stl,徹底stl需使用上面的libc++。這是與Android發佈綁定的庫。
System運行庫指的是Android版本里的/system/lib/libstdc++.so,提供基本的c++運行支持, 提供new/delete支持,僅提供c標準庫的c++封裝,好比<cstdio>。
也不提供Exception Handling和RTTI支持。 - none:沒有標準庫支持。
【注】以上是Android NDK r18以後的c++運行庫。在以前的NDK中還提供了gnustl,是GNU的c++ STL,一樣包含了動態庫"gnustl_shared"(libgnustl_shared.so)以及靜態庫"gnustl_static"(libgnustl_static.a)支持。在那些版本的NDK裏有多於一種的真正徹底STL可供選擇。ide
2、NDK開發時選擇STL
NDK開發時,能夠用下面方式指定c++運行庫。工具
運行庫在「c++_shared」,「
c++_static」,「
none」或「system」中選擇其一,其中
「c++_shared」,「
c++_static」分別對應libc++的動態庫和靜態庫。
gradle
2.1 cmake編譯指定STL
不經過ANDROID_STL指定STL的狀況下缺省是c++_static。ui
能夠在Module級別的build.gradle文件中經過變量ANDROID_STL變量指定一個運行庫:「c++_shared」,「
c++_static」,「
none」或「system」中選擇其一。
google
ANDROID_STL 可選:none / system / c++_static / c++_shared 若是未設置,默認爲c++_static
2.2 ndk-build裏指定STL
不經過APP_STL指定STL的狀況下缺省是nonespa
能夠在Application.mk文件中經過變量APP_STL變量指定一個運行庫:「c++_shared」,「
c++_static」,「
none」或「system」中選擇其一。
APP_STL 可選:none / system / c++_static / c++_shared 若是未設置,默認爲none
2.3 clang編譯指定STL
clang編譯能夠直接指定link flag。缺省是c++_shared。若是要指定靜態庫,用「-static-libstdc++」【這裏只是連接選項,不是源碼編譯時的libstdc++,這裏選擇的實際是c++_static】
3、 c++特性支持
libc++這個STL支持Exception處理和RTTI。
3.1 Exception
缺省ndk-build裏Exception處理機制是關閉的;缺省cmake編譯Exception處理機制是打開的。
能夠用下面方式打開Exception處理:
1) 整個程序範圍打開,在Application.mk裏添加:
APP_CPPFLAGS := -fexceptions
2) 在一個Module級別,在Android.mk裏添加:
LOCAL_CPP_FEATURES := exceptions # or LOCAL_CPPFLAGS := -fexceptions
3.2 RTTI
缺省ndk-build裏RTTI是關閉的;缺省cmake編譯RTTI是打開的。
能夠用下面方式打開RTTI:
1) 整個程序範圍打開,在Application.mk裏添加:
APP_CPPFLAGS := -frtti
2) 在一個Module級別,在Android.mk裏添加:
LOCAL_CPP_FEATURES := rtti # or LOCAL_CPPFLAGS := -frtti
4、NDK版本變化
目前Android SDK裏能夠直接下載到的NDK的版本(r16 ~r21)裏的STL、支持的Android 版本及其變化總結以下:
NDK | Release Date | STL | Supported SDK (API) | Arch | |||||
gabi++ | gnustl | libc++ | libc++abi | stlport | system | ||||
16b | 2017-12 | √ | √ | √ (preferred) | √ | √ | √ | 14, 15, 16, 17, 18, 19, |
MIPS deprecated |
r17c | 2018-06 | √ (deprecated) | √ (deprecated) | √ (default) | √ | √ (deprecated) | √ | 14, 15, 16, 17, 18, 19, |
MIPS removed |
r18b | 2018-08 | √ | √ | √ | require 64-bit support | ||||
r19c | 2019-01 | √ | √ | √ | |||||
r20b | 2019-06 | √ | √ | √ | |||||
r21d | 2020-06 | √ | √ | √ |
重大變化(表中已經明確以顏色/刪除線等方式標註)總結以下:
STL變化:
- r16開始優選libc++;r17開始libc++是缺省的stl,
- gnustl在r17開始被標註過期而且在r18中被移除;
NDK支持Android版本的變化:
- Android9(API 28)在NDK r17開始支持;
- Android10(API 29)在NDK r20開始支持;
- Android11(API 30)在NDK r21開始支持;
Android4.0.x(API 14/15)從NDK r18開始再也不支持
5、總結
總結一下:
- Android NDK開發是基於Android的,可是不綁定具體某一個Android版本,一個Android NDK發佈版能夠支持多個Android版本。
- NDK開發不管靜態庫仍是動態庫,libc++都是用NDK裏的發佈版本打包在應用裏:動態庫直接在apk裏帶上libc++_shared.so;靜態庫已經把程序須要的STL代碼直接打到應用程序或其所用的native庫裏。
- Android NDK中的STL:libc++_shared / libc++_static / system,其中libc++是完整的STL;
- NDK開發,cmake和ndk-build方式均可以指定其所用的STL;
- libc++支持Exception處理和RTTI,ndk-build須要編譯時打開;
- NDK歷史上在r18前還支持gnustl;
- 對Android新版本的支持隨着NDK版本更新不斷加入;過期的Android支持也會移除。
附:參考及進一步閱讀
- NDK c++ Library Support https://developer.android.google.cn/ndk/guides/cpp-support
官方介紹 - Android源碼中的STL https://haili-tian.blog.csdn.net/article/details/109864831
Android源碼中的STL:內置的libc++/libc++_static/system;內置的NDK版本中的libc++_shared/libc++_static/system(system也就是android源碼中的libstdc++) - Android源碼中STL的namespace https://haili-tian.blog.csdn.net/article/details/109920740 namespace in libc++【頭文件: external/libcxx/include/】:std::__1 namespace in libc++_shared【頭文件: prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/include/】:std::__ndk1