AndroidNDK編譯選項(xiàng)設(shè)置-創(chuàng)新互聯(lián)

在Android NDK開發(fā)中,有兩個(gè)重要的文件:Android.mk和Application.mk,各盡其責(zé),指導(dǎo)編譯器如何編譯程序,并決定編譯結(jié)果是什么。本文將詳細(xì)說明幾個(gè)常見的NDK選項(xiàng)的配置,幫助大家理解相應(yīng)的配置選項(xiàng)。

Android NDK編譯選項(xiàng)設(shè)置

創(chuàng)新互聯(lián)專注于九臺(tái)企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,商城網(wǎng)站建設(shè)。九臺(tái)網(wǎng)站建設(shè)公司,為九臺(tái)等地區(qū)提供建站服務(wù)。全流程按需求定制開發(fā),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

   一、Application.mk

    Application.mk實(shí)際上是輕量級Makefile,通常在$PROJECT/jni目錄下,用于配置所有modules的編譯變量,例子如下:

APP_ABI := armeabi arm64-v8a x86_64 x86 armeabi-v7a
NDK_TOOLCHAIN_VERSION := clang3.5
APP_STL := stlport_static
APP_OPTIM:= debuge

   1、APP_ABI(目標(biāo)平臺(tái)ABI類型)

    NDK編譯中,APP_ABI默認(rèn)選擇armeabi ABI,可通過設(shè)置APP_ABI設(shè)置一個(gè)或者多個(gè)ABI,表一為不同的APP_ABI所對應(yīng)的指令集。

Instrunction setValue
ARMv5TE based CPUAPP_ABI := armeabi
ARMv7 based CPUAPP_ABI := armeabi-v7a
ARMv8 AArch74APP_ABI := arm64-v8a
IA-32APP_ABI := x86
Intel64APP_ABI := x86_64
MIPS32APP_ABI := mips
MIPS64(r6)APP_ABI := mips64
All supported instruction setsAPP_ABI := all

表一:ABI類型

    在開發(fā)時(shí)可根據(jù)需求選擇APP_ABI,對于ABI的選擇需要考慮到效率和APK大小。由于armeabi-v7a指令集兼容armeabi;市面上的x86手機(jī)為了兼容性,基本都使用libhoudini模塊,兼容arm指令集;64位機(jī)型默認(rèn)支持32位abi的so,因此在對大小要求比較高的情況下,可以只選擇市面上設(shè)備基本兼容的armeabi ABI,如果對性能有些許要求,可以再添加x86 ABI。

   2、 NDK_TOOLCHAIN_VERSION(編譯器類型、版本)

    默認(rèn)采用的是GCC編譯器,對于GCC版本的選擇與NDK版本有關(guān)系,本人使用的是NDK R12,在64位ABI默認(rèn)是GCC 4.9,32位ABI默認(rèn)是GCC 4.8,當(dāng)然也可以像上面例子中給出的設(shè)置一樣,設(shè)置clang編譯器。

   3、 APP_STL(運(yùn)行庫類型)

    Android NDK 默認(rèn)使用的是最小支持的C++運(yùn)行庫,如果你需要你的NDK程序中使用STL,則可以設(shè)置APP_STL := stlport_static,APP_STL有表二中的幾種取值。

NameExplanation
system(default)系統(tǒng)默認(rèn)的C++運(yùn)行庫
stlport_static以靜態(tài)鏈接方式使用的sttport版本的STL
stlport_shared以動(dòng)態(tài)鏈接方式使用的sttport版本的STL
gnustl_static以靜態(tài)鏈接方式使用的gnustl版本的STL
gnustl_shared以動(dòng)態(tài)鏈接方式使用的gnustl版本的STL
gabi++_static以靜態(tài)鏈接方式使用的gabi++
gabi++_shared以動(dòng)態(tài)鏈接方式使用的gabi++
c++_static以靜態(tài)鏈接方式使用的LLVM libc++
c++_shared以動(dòng)態(tài)鏈接方式使用的LLVM libc++

表二:NDK運(yùn)行庫

    若APK中有多個(gè)SO文件用到STL,建議都使用動(dòng)態(tài)方式鏈接STL,這樣可以減小整個(gè)APK文件大小。
另外需要注意的是官方提供的NDK運(yùn)行庫除了默認(rèn)的以外都支持RTTI和異常,然而默認(rèn)是禁用的,將在下面的Android.mk中說明如何開啟。

   4、APP_OPTIM(編譯模式)

    “release”模式為默認(rèn)的,生成的是優(yōu)化后的二進(jìn)制;也可以設(shè)置為“debug”模式,“debug”模式生成的是未優(yōu)化二進(jìn)制,提供很多BUG信息,便于調(diào)試和分析。
還有其他配置選項(xiàng),有興趣可以查看Application.mk官方文檔。

   二、Android.mk

    Android.mk也是一個(gè)輕量級的Makefile,其將C/C++源碼組織到一個(gè)個(gè)module中,module可以是靜態(tài)庫、共享庫或者獨(dú)立的可執(zhí)行文件, 一個(gè)Android.mk文件可以有一個(gè),也可以是多個(gè)module,modules之間也可以有依賴關(guān)系。

   1、基本概念

    Android.mk中包括NDK提供的宏、變量以及模塊描述變量,這些宏、變量以及變量的賦值共同組成了Android.mk文件,其在NDK編譯中各盡其責(zé),指導(dǎo)著NDK的編譯。
   宏:包括my-dir、all-subdir-makefiles等,通過‘$(call <function>)’來調(diào)用,返回文本信息。
   變量:包括CLEAR_VARS、BUILD_SHARED_LIBRARY、TARGET_ARCH等,由NDK編譯系統(tǒng)提供,并且在Android.mk文件被解析前就已經(jīng)存在。Android.mk文件有可能被多次解析,因此每次解析時(shí)這些變量的值都有可能不同。
   模塊描述變量:Module-description,包括LOCAL_PATH、LOCAL_MODULE、LOCAL_SRC_FILES等LOCAL_前綴變量,這些變量除LOCAL_PATH外,均填寫在語句include $(CLEAR_VARS)和include $(BUILD_XXX)之間。
其他Android.mk配置可以查看Android.mk官方文檔。

   2、基礎(chǔ)

   在Android.mk中包括一些很基礎(chǔ)的變量,下面的栗子包括了基礎(chǔ)的變量,本人將詳細(xì)說明。

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)

    LOCAL_PATH(當(dāng)前目錄)
    LOCAL_PATH為模塊描述變量,一個(gè)Android.mk必須定義LOCAL_PATH,用于定位源文件,在本例中,使用的是編譯系統(tǒng)提供的宏“my-dir”(“my-dir”返回最近一次包括Makefile文件路徑,通常為當(dāng)前Android.mk所在目錄),用于返回當(dāng)前目錄。
此變量不會(huì)被CLEAR_VARS清除,所以每個(gè)Android.mk文件只需要定義一次就可以了。

    CLEAR_VARS(變量清除)
    CLEAR_VARS變量由編譯系統(tǒng)提供,顧名思義,作用是清除模塊變量(在include $(CLEAR_VARS)和include $(BUILD_XXX)之間的LOCAL_XXX模塊變量),當(dāng)然LOCAL_PATH除外。由于所有的編譯控制文件都是單一的GNU Make可執(zhí)行上下文環(huán)境中解析,而這個(gè)上下文環(huán)境中所有的變量都是全局的,所以編譯module前需要清理相應(yīng)變量。

    LOCAL_MODULE(module名稱)
    LOCAL_MODULE是Android.mk文件中module的唯一標(biāo)識,這個(gè)名字必須是唯一的,且中間不能有空格。在默認(rèn)情況下,它決定了生成的文件名,如“hello-jni”對應(yīng)的動(dòng)態(tài)庫名稱為libhello-jni.so,然而要索引它時(shí),需要“hello-jni”即可,也可以通過變量LOCAL_MODULE_FILENAME來覆蓋這個(gè)默認(rèn)名稱。

    LOCAL_SRC_FILES (源碼文件)
    LOCAL_SRC_FILES 變量包括C/C++源文件列表,這些源文件會(huì)被編譯到一個(gè)module中,不過也不必列出頭文件和包括文件,編譯系統(tǒng)會(huì)自動(dòng)為你找打所有需要的依賴關(guān)系。值得注意的是linux下路徑使用順斜杠(/)。

    BUILD_SHARED_LIBRARY(動(dòng)態(tài)庫編譯)
    BUILD_SHARED_LIBRARY是編譯器提供的變量,表示編譯成動(dòng)態(tài)庫,它指向一個(gè)GNU Makefile腳本,這個(gè)腳本收集從include $(CLEAR_VARS)后所有的LOCAL_XXX變量中定義的所有信息,決定編譯什么以及怎么編譯。
還有BUILD_STATIC_LIBRARY,和BUILD_SHARED_LIBRARY類似,表示編譯成靜態(tài)庫,靜態(tài)庫不會(huì)被拷貝到APK中。

    PREBUILT_SHARED_LIBRARY(預(yù)編譯)
    指向一個(gè)編譯腳本,用來指定一個(gè)預(yù)編譯動(dòng)態(tài)庫.使用此變量時(shí),不像BUILD_SHARED_LIBRARY和BUILD_STATIC_LIBRARY那樣,LOCAL_SRC_FILES的值必須是只能有一個(gè)指向預(yù)編譯動(dòng)態(tài)庫的路徑,如foo/libfoo.so,而不是源文件。如下栗子。

include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libtest.so
include $(PREBUILT_SHARED_LIBRARY)

PREBUILD_STATIC_LIBRARY和PREBUILD_SHARED_LIBRARY一樣,只不過是用于引用靜態(tài)庫。

   TARGET_ARCH_ABI(目標(biāo)ABI名稱)
   如表一所示,目標(biāo)ABI名稱。若定義了多個(gè)ABI,則每次解析Android.mk時(shí),值都不一樣,主要使用場景為根本不同的ABI定義不同的文件等。

   3、其他模塊變量LOCAL_LDLIBS(鏈接庫)

   用于額外鏈接選項(xiàng),所有的庫都有“-l”前綴??赏瑫r(shí)列出多個(gè)庫,用空格隔開,例如:

LOCAL_LDLIBS := -llog -ldl

    Android NDK默認(rèn)鏈接了多個(gè)庫,不需要顯示的添加到LOCAL_LDLIBS中,包括 the standard C libraries,the standard C++ libraries,real-time extensions和 pthread庫。同時(shí)也提供了一些需要顯示添加的庫,這些庫版本有關(guān)系,如表三所示。

Android levelLibExplanation

Android-3
-llogAndroid Log
-lzZlib Compression Library
-ldlDynamic Linker Library
Android-4-lGLESv1_CMOpenGL ES 1.x Library
Android-5-lGLESv2OpenGL ES 2.0 Library
Android-8-ljnigraphicsThe jnigraphics Library

Android-9
-lEGLThe EGL graphics library
-lOpenSLESOpen ES native audio Library
-landroidNatice Android API
Android-14-lOpenMAXALOpenMAX AL natice multimedia Library
Android-18-lGLESv3OpenGL ES 3.0 Library
Android-21-lGLESv3OpenGL ES 3.1 Library

表三:鏈接庫

    LOCAL_CFLAGS、LOCAL_CPPFLAGS和LOCAL_LDFLAGS(編譯、鏈接標(biāo)志)

    LOCAL_CFLAGS定義的是在編譯C/C++時(shí),傳遞給編譯器的標(biāo)志集合,LOCAL_CPPFLAGS只支持C++,作用也是傳遞給編譯器一些信息,LOCAL_LDFLAGS是指傳遞給連接器一些額外的參數(shù)。

在NDK開發(fā)中難免會(huì)用到這些標(biāo)志位,特別是在優(yōu)化編譯時(shí),下面的是本人在開發(fā)中遇到的編譯選項(xiàng)。

    ① LOCAL_CPPFLAGS += -fexceptions
    由于NDK編譯從R5開始才支持C++異??刂?,為了通用性,異常處理默認(rèn)是禁用的(-fno-exceptions),因此需要在指定module中添加LOCAL_CPPFLAGS += -fexceptions編譯選項(xiàng)方可編譯帶異常處理的C++代碼。也可以直接在Application.mk中配置APP_CPPFLAGS += -fexceptions。

    ② LOCAL_CPPFLAGS += -frtti
    從NDK R5開始,NDK也開始支持C++ RTTI了,但為了通用性,所有的C++源文件被構(gòu)建的時(shí)候默認(rèn)是不支持RTTI的(-fno-rtti),可以通過在Android.mk中添加:LOCAL_CPPFLAGS += -frtti或者在Application.mk添加APP_CPPFLAGS += -frtti來開啟RTTI。

    ③ LOCAL_CFLAGS += -fvisibility=hidden
    在NDK開發(fā)中,源文件的函數(shù)都有一個(gè)默認(rèn)的visibility屬性為public,編譯生成的so文件中幾乎所有的函數(shù)名、全局變量名均被導(dǎo)出,其實(shí)只需要導(dǎo)出java_com開頭的jni函數(shù)即可,其他函數(shù)不需要暴露出來,在Android.mk中設(shè)置LOCAL_CFLAGS += -fvisibility=hidden,就可以隱藏不需要導(dǎo)出的函數(shù),若某個(gè)函數(shù)需要導(dǎo)出,則添加JNIEXPORT或者_(dá)_attribute__ ((visibility ("default")))即可。
除了安全,不導(dǎo)出不必要的函數(shù)外,還能減小so體積。

    ④ LOCAL_CFLAGS += -ffunction-sections
    不添加此參數(shù)時(shí),編譯文件.o中代碼部分只有.text段,使用此參數(shù),會(huì)使每個(gè)函數(shù)單獨(dú)有一個(gè)段,舉個(gè)栗子,函數(shù)func1()會(huì)編譯成.text.func1段,雖然段多了,但對鏈接后代碼大小并沒有影響。

    ⑤ LOCAL_CFLAGS += -fdata-sections
    同上,每個(gè)data都有一個(gè)單獨(dú)的段。

    ⑥ LOCAL_LDFLAGS += -Wl --gc-sections
    -Wl,<option>選項(xiàng)是告訴編譯器,將后面選項(xiàng)<option>傳遞給連接器,-Wl,--gc-sections的意思是使用連接器ld鏈接時(shí)刪除不用的段。若使用LOCAL_CFLAGS += -ffunction-sections -fdata-sections,則代碼和數(shù)據(jù)均被分割成不同的段,若某個(gè)函數(shù)或數(shù)據(jù)未被任何函數(shù)調(diào)用,則ld不會(huì)鏈接未被調(diào)用的函數(shù),從而減小so文件體積,達(dá)到優(yōu)化so的目的。

    ⑦ LOCAL_LDFLAGS += -fPIC
    PIC(position independent code)用于編譯位置無關(guān)代碼,生成可用于共享庫的位置獨(dú)立代碼。若不添加-fPIC,則加載.so文件的代碼段時(shí),代碼段引用的數(shù)據(jù)對象需要重定位,重定位會(huì)修改代碼段內(nèi)容,這樣就導(dǎo)致沒使用這個(gè).so,代碼段的進(jìn)程在內(nèi)核中就會(huì)生成這個(gè)文件的拷貝。

    ⑧ LOCAL_LDFLAGS += -Wall
    這個(gè)的意思是wring all 意思在編譯和鏈接過程中顯示所有警告信息。

    ⑨其他
    若需要了解其他編譯標(biāo)志,可以查看GCC Command Options 文檔。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

網(wǎng)站標(biāo)題:AndroidNDK編譯選項(xiàng)設(shè)置-創(chuàng)新互聯(lián)
轉(zhuǎn)載源于:http://muchs.cn/article46/dhioeg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管定制網(wǎng)站、企業(yè)網(wǎng)站制作外貿(mào)建站、網(wǎng)站設(shè)計(jì)、面包屑導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營