android ndk-build android.mk,關於ndk-build所使用的Android.mk和Application.mk 青旅半醒 2022-10-05 01:56 99阅读 0赞 Android.mk文件 一個Android.mk file用來向編譯系統描述你的源代碼。具體來說:該文件是GNU Makefile的一小部分,會被編譯系統解析一次或多次。你可以在每一個Android.mk file中定義一個或多個模塊,你也可以在幾個模塊中使用同一個源代碼文件。編譯系統為你處理許多細節問題。例如,你不需要在你的Android.mk中列出頭文件和依賴文件。NDK編譯系統將會為你自動處理這些問題。這也意味着,在升級NDK后,你應該得到新的toolchain/platform支持,而且不需要改變你的Android.mk文件。 先看一個簡單的例子:一個簡單的"hello world",比如下面的文件: sources/helloworld/helloworld.c sources/helloworld/Android.mk 相應的Android.mk文件會象下面這樣: LOCAL\_PATH := $(call my-dir) include $(CLEAR\_VARS) LOCAL\_MODULE := helloworld LOCAL\_SRC\_FILES := helloworld.c include $(BUILD\_SHARED\_LIBRARY) 我們來解釋一下這幾行代碼: LOCAL\_PATH := $(call my-dir) 一個Android.mk file首先必須定義好LOCAL\_PATH變量。它用於在開發樹中查找源文件。在這個例子中,宏函數’my-dir’, 由編譯系統提供,用於返回當前路徑(即包含Android.mk file文件的目錄)。 include $( CLEAR\_VARS) CLEAR\_VARS由編譯系統提供,指定讓GNU MAKEFILE為你清除許多LOCAL\_XXX變量(例如 LOCAL\_MODULE, LOCAL\_SRC\_FILES, LOCAL\_STATIC\_LIBRARIES, 等等...),除LOCAL\_PATH 。這是必要的,因為所有的編譯控制文件都在同一個GNU MAKE執行環境中,所有的變量都是全局的。 LOCAL\_MODULE := helloworld LOCAL\_MODULE變量必須定義,以標識你在Android.mk文件中描述的每個模塊。名稱必須是唯一的,而且不包含任何空格。注意編譯系統會自動產生合適的前綴和后綴,換句話說,一個被命名為'foo'的共享庫模塊,將會生成'libfoo.so'文件。 LOCAL\_SRC\_FILES := helloworld.c LOCAL\_SRC\_FILES變量必須包含將要編譯打包進模塊中的C或C++源代碼文件。注意,你不用在這里列出頭文件和包含文件,因為編譯系統將會自動為你找出依賴型的文件;僅僅列出直接傳遞給編譯器的源代碼文件就好。 在Android中增加本地程序或者庫,這些程序和庫與其所載路徑沒有任何關系,只和它們的Android.mk文件有關系。Android.mk和普通的Makefile有所不同,它具有統一的寫法,主要包含一些系統公共的宏。 在一個Android.mk中可以生成多個可執行程序、動態庫和靜態庫。 1,編譯應用程序的模板: \#Test Exe LOCAL\_PATH := $(call my-dir) \#include $(CLEAR\_VARS) LOCAL\_SRC\_FILES:= main.c LOCAL\_MODULE:= test\_exe \#LOCAL\_C\_INCLUDES := \#LOCAL\_STATIC\_LIBRARIES := \#LOCAL\_SHARED\_LIBRARIES := include $(BUILD\_EXECUTABLE) (菜鳥級別解釋::=是賦值的意思,$是引用某變量的值)LOCAL\_SRC\_FILES中加入源文件路徑,LOCAL\_C\_INCLUDES 中加入所需要包含的頭文件路徑,LOCAL\_STATIC\_LIBRARIES加入所需要鏈接的靜態庫(\*.a)的名稱,LOCAL\_SHARED\_LIBRARIES中加入所需要鏈接的動態庫(\*.so)的名稱,LOCAL\_MODULE表示模塊最終的名稱,BUILD\_EXECUTABLE表示以一個可執行程序的方式進行編譯。 2,編譯靜態庫的模板: \#Test Static Lib LOCAL\_PATH := $(call my-dir) include $(CLEAR\_VARS) LOCAL\_SRC\_FILES:= / helloworld.c LOCAL\_MODULE:= libtest\_static \#LOCAL\_C\_INCLUDES := \#LOCAL\_STATIC\_LIBRARIES := \#LOCAL\_SHARED\_LIBRARIES := include $(BUILD\_STATIC\_LIBRARY) 一般的和上面相似,BUILD\_STATIC\_LIBRARY表示編譯一個靜態庫。 3,編譯動態庫的模板: \#Test Shared Lib LOCAL\_PATH := $(call my-dir) include $(CLEAR\_VARS) LOCAL\_SRC\_FILES:= / helloworld.c LOCAL\_MODULE:= libtest\_shared TARGET\_PRELINK\_MODULES := false \#LOCAL\_C\_INCLUDES := \#LOCAL\_STATIC\_LIBRARIES := \#LOCAL\_SHARED\_LIBRARIES := include $(BUILD\_SHARED\_LIBRARY) 一般的和上面相似,BUILD\_SHARED\_LIBRARY表示編譯一個靜態庫。 以上三者的生成結果分別在如下,generic依具體target會變: out/target/product/generic/obj/EXECUTABLE out/target/product/generic/obj/STATIC\_LIBRARY out/target/product/generic/obj/SHARED\_LIBRARY 每個模塊的目標文件夾分別為: 可執行程序:XXX\_intermediates 靜態庫: XXX\_static\_intermediates 動態庫: XXX\_shared\_intermediates 另外,在Android.mk文件中,還可以指定最后的目標安裝路徑,用LOCAL\_MODULE\_PATH和LOCAL\_UNSTRIPPED\_PATH來指定。不同的文件系統路徑用以下的宏進行選擇: TARGET\_ROOT\_OUT:表示根文件系統。 TARGET\_OUT:表示system文件系統。 TARGET\_OUT\_DATA:表示data文件系統。 用法如: CAL\_MODULE\_PATH:=$(TARGET\_ROOT\_OUT) Application.mk文件要將C\\C++代碼編譯為SO文件,光有Android.mk文件還不行,還需要一個Application.mk文件。本文檔是描述你的Android應用程序中需要的本地模塊的Application.mk的語法使用,要明白如下。Application.mk目的是描述在你的應用程序中所需要的模塊(即靜態庫或動態庫)。Application.mk文件通常被放置在$PROJECT/jni/Application.mk下,$PROJECT指的是您的項目。另一種方法是將其放在頂層的子目錄下:$NDK/apps目錄下,例如:$NDK/apps//Application.mk是一個簡稱,用於描述你的NDK編譯系統的應用程序(這個名字不會生成共享庫或者最終的包)下面是Application.mk中定義的幾個變量。APP\_PROJECT\_PATH這個變量是強制性的,並且會給出應用程序工程的根目錄的一個絕對路徑。這是用來復制或者安裝一個沒有任何版本限制的JNI庫,從而給APK生成工具一個詳細的路徑。APP\_MODULES這個變量是可選的,如果沒有定義,NDK將由在Android.mk中聲明的默認的模塊編譯,並且包含所有的子文件(makefile文件)如果APP\_MODULES定義了,它不許是一個空格分隔的模塊列表,這個模塊名字被定義在Android.mk文件中的LOCAL\_MODULE中。注意NDK會自動計算模塊的依賴注意:NDK在R4開始改變了這個變量的行為,再次之前:- 在您的Application.mk中,該變量是強制的- 必須明確列出所有需要的模塊APP\_OPTIM這個變量是可選的,用來定義“release”或"debug"。在編譯您的應用程序模塊的時候,可以用來改變優先級。“release”模式是默認的,並且會生成高度優化的二進制代碼。"debug"模式生成的是未優化的二進制代碼,但可以檢測出很多的BUG,可以用於調試。注意:如果你的應用程序是可調試的(即,如果你的清單文件中設置了android:debuggable的屬性是"true")。默認的是"debug"而不是"release"。這可以通過設置APP\_OPTIM為"release"來將其覆蓋。注意:可以在"release"和"debug"模式下一起調試,但是"release"模式編譯后將會提供更少的BUG信息。在我們清楚BUG的過程中,有一些變量被優化了,或者根本就無法被檢測出來,代碼的重新排序會讓這些帶阿彌變得更加難以閱讀,並且讓這些軌跡更加不可靠。APP\_CFLAGS當編譯模塊中有任何C文件或者C++文件的時候,C編譯器的信號就會被發出。這里可以在你的應用中需要這些模塊時,進行編譯的調整,這樣就不許要直接更改Android.mk為文件本身了重要警告:+++++++++++++++++++++++++++++++++++++++++++++++ + +++ 在這些編制中,所有的路徑都需要於最頂層的NDK目錄相對應。+ 例如,如果您有以下設置:++sources/foo/Android.mk+sources/bar/ Android.mk+ 編譯過程中,若要在foo/Android.mk中指定你要添加的路徑到bar源代碼中,+ 你應該使用+ APP\_CFLAGS += -Isources/bar+ 或者交替:+ APP\_CFLAGS += -I $(LOCAL\_PATH )/../bar++ 使用'-l../bar/'將不會工作,以為它將等同於"-l$NDK\_ROOT/../bar"++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++注意:在Android的NDK 1.5\_r1,只適用於C源文件,而不適合C++。這已得到糾正,以建立完整相匹配的Android系統。APP\_CXXFLAGSAPP\_CPPFLAGS的別名,已經考慮在將在未來的版本中廢除了APP\_CPPFLAGS當編譯的只有C++源文件的時候,可以通過這個C++編譯器來設置注意:在Android NDK-1.5\_r1中,這個標志可以應用於C和C++源文件中。並且得到了糾正,以建立完整的與系統相匹配的Android編譯系統。你先可也可以使用APP\_CFLAGS來應用於C或者C++源文件中。建議使用APP\_CFLAGSAPP\_BUILD\_SCRIPT默認情況下,NDK編譯系統會在$(APP\_PROJECT\_PATH)/jni目錄下尋找名為Android.mk文件:$(APP\_PROJECT\_PATH)/jni/Android.mk如果你想覆蓋此行為,你可以定義APP\_BUILD\_SCRIPT來指定一個備用的編譯腳本。一個非絕對路徑總是被解釋為相對於NDK的頂層的目錄。APP\_ABI默認情況下,NDK的編譯系統回味"armeabi"ABI生成機器代碼。喜愛哪個相當於一個基於CPU可以進行浮點運算的ARMv5TE。你可以使用APP\_ABI來選擇一個不同的ABI。比如:為了在ARMv7的設備上支持硬件FPU指令。可以使用APP\_ABI := armeabi-v7a或者為了支持IA-32指令集,可以使用APP\_ABI := x86或者為了同時支持這三種,可以使用APP\_ABI := armeabi armeabi-v7a x86APP\_STL默認情況下,NDK的編譯系統為最小的C++運行時庫(/system/lib/libstdc++.so)提供C++頭文件。然而,NDK的C++的實現,可以讓你使用或着鏈接在自己的應用程序中。例如:APP\_STL := stlport\_static --> static STLport libraryAPP\_STL := stlport\_shared --> shared STLport libraryAPP\_STL := system --> default C++ runtime library 引用:
还没有评论,来说两句吧...