1 前言
本文檔描述了c和c++編寫的程序用Android NDK編譯時,編譯文件Android.mk的語法結構。為了便於理解下面的內容,假設你已經閱讀了前面OVERVIEW部分,了解了它們的作用和用法。
2 概要
Android.mk是用來描述源文件是如何進行編譯的。更具體的:-Android.mk實際上是一個輕量級的Makefile,它會被編譯系統解析一次或多次。因此,你應該盡可能少的聲明變量,同時不要假定在解析過程中沒有定義任何東西。-Android.mk是用來允許你將源文件組織在一個‘modeles’中。一個modele是以下兩種形式之一:
- a static library 靜態庫
- a shared library 動態庫
只有動態庫才會安裝或者拷貝到你的應用程序包中,但是靜態庫可以用來生成動態庫。你可以在每個Android.mk中定義一個或多個modeles,你也可以在多個modeles中使用相同的源文件。
-編譯系統為你處理了很多細節。例如,你不需要在Android.mk中列出頭文件,也不需要顯示的列出文件之間的依賴關系。NDK編譯系統將會自動為你計算這些東西。這同樣意味著,當你升級到新的NDK版本時,你可以得到新的交叉工具和平台的支持,而不需要修改你的Android.mk文件。
簡單例子:
在介紹語法細節之前,讓我們看一下“hello JNI”這個簡單的例子,文件如下:
apps/hello-jni/project
這裡我們可以看到:
-‘src’目錄包含了Android工程的所有java源文件。
-‘jni’目錄包含了本地源文件。例如,‘jni/hello-jni.c’。這個源文件實現了一個簡單的動態庫,而這個動態庫實現了一個native方法,這個方法返回一個string給VM應用。
-‘jni/Android.mk’文件描述了NDK編譯系統的動態庫。包括:
----------------------分割線----------------------------------
LOCAL_PATH :=$(call my-dir)
include$(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include$(BUILD_SHARED_LIBRARY)
----------------------分割線----------------------------------
現在,我們解釋一下:
LOCAL_PATH := $(callmy-dir)
Android.mk文件必須先定義LOCAL_PATH變量,它用來定位開發樹中的源文件。在本例中,編譯系統提供的宏‘my-dir’,用來返回當前目錄(即這個目錄包含了Android.mk文件自身)。
include$(CLEAR_VARS)
CLEAR_VARS變量由編譯系統提供,它指向一個特殊的GNU Makefile,這個Makefile會為你清除很多LOCAL_XXX這樣的變量(如LOCAL_MODULE,LOCAL_SRC_FIELS, LOCAL_STATIC_LIBARIES, 等等),當然LOCAL_PATH除外。這樣做是必須的,因為所有的編譯控制文件都是在單一的GNU Make可執行上下文環境中解析的,而在這個上下文環境中所有的變量都是全局的。
LOCAL_MODULE := hello-jni
LOCAL_MODULE變量用來唯一標示Android.mk文件中的每個module。這個名字必須是唯一的,並且不能包含任何空白字符。編譯系統會根據生成的文件自動添加前綴和後綴。換句話說,一個叫‘foo’的動態庫module,會生成‘libfoo.so’。
重要提示:
如果你的module命名為‘libfoo’,編譯系統將不會另外添加‘lib’前綴,同樣會生成libfoo.so。(注:為了養成統一習慣,個人建議不要自行加lib前綴了)
LOCAL_SRC_FILES := hello-jni.c
LOCAL_SRC_FILES變量必須包含c和c++源文件列表,這些源文件會被編譯和組裝到一個module中。注意這裡你不必列出頭文件和包含文件,因為編譯系統會自動為你計算出它們之間的依賴關系;你只需要列出源文件,這些源文件將直接傳遞給編譯器。
注意,默認的c++源文件的擴展名是‘.cpp’,當然你可以通過定義變量LOCAL_CPP_EXTENSION指定不同的擴展名,但是要記住不能忘記前面的那個點(即‘.cxx’可以工作,但是‘cxx’不行的)。
include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY是編譯系統提供的一個變量,它指向一個GNU Makefile腳本,這個腳本負責收集從最近的‘include $(CLEAR_VARS)’,在LOCAL_XXX變量中定義的所有信息,同時決定編譯什麼,以及怎麼編譯。顯然,BUILD_STATIC_LIBRARY是用來生成靜態庫的。
在samples目錄中,還有很多復雜的例子,在Android.mk文件中都有注釋,可以自行查看。
參考:
------------
在Android.mk中還有一序列的變量,你要麼依賴於它,要麼要定義它。你可以根據自己的用法,定義其他變量,但是NDK編譯系統保留了以下變量名字:
-以LOCAL_開頭的名稱(如,LOCAL_MODULE)
-以PRIVATE_ , NDK_ , APP_ 開頭的名稱(內部使用)
-小寫的名稱(內部使用,如‘my-dir’)
如果你需要在Android.mk中定義自己的變量,推薦用MY_作為前綴,一個簡單的例子:
----------------------分割線----------------------------------
MY_SOURCES :=foo.c
Ifneq($(MY_CONFIG_BAR), )
MY_SOURCES += bar.c
endif
LOCAL_SRC_FILES += $(MY_SOURCES)
----------------------分割線----------------------------------
NDK提供的變量:
----------------------
在Android.mk文件解析之前,編譯系統定義了這些GNU Make變量。注意在某些特定的環境下,NDK可能會多次解析Android.mk文件,對於以下這些變量每次可能會使用不同的定義:
CLEAR_VARS
指向一個編譯腳本,這個腳本會清除在“Module-descrption”section下面列出的所有LOCAL_XXX變量。在你開始聲明一個新的module之前,你必須包含這個腳本,如:
include $(CLEAR_VARS)
BUILD_SHARED_LIBRARY
指向一個編譯腳本,這個腳本會搜集你在module中提供的LOCAL_XXX變量的所有信息,以及決定如何從你列出的源文件中編譯目標動態庫。注意在包含這個文件之前,你必須至少先定義LOCAL_MODULE和LOCAL_SRC_FILES。如:
include$(BUILD_SHARED_LIBRARY)
記住,這會生成一個lib$(LOCAL_MODULE).so文件
BUILD_STATIC_LIBRARY
BUILD_STATIC_LIBRARY用來編譯目標靜態庫。靜態庫不會拷貝到你的工程或者應用包中,但是它可以用來編譯動態庫(參考下面的LOCAL_STATIC_LIBRARIES 和LOCAL_WHOLE_STATIC_LIBRARIES)。
使用示例:
include $(BUILD_STATIC_LIBRARY)
注意,這會生成一個lib$(LOCAL_MODULE).a文件。
PREBUILT_SHARED_LIBRARY
指向一個編譯腳本,這個腳本用來指定一個預編譯動態庫。不像BUILD_SHARED_LIBRARY和BUILD_STATIC_LIBRARY,LOCAL_SRC_FILES的值必須是一個編譯好的動態庫的路徑(如foo/libfoo.so),而不是源文件。
你可以使用LOCAL_PREBUILTS變量引用另外一個module中編譯好的庫(請查看PREBUILTS中的相關內容)。
PREBUILT_STATIC_LIBRARY
這個和PREBUILT_SHARED_LIBRARY相同,只是表示一個靜態庫而已。同樣請查看PREBUILTS中的相關內容。
TARGET_ARCH
它是由整個Android開源編譯指定的目標CPU架構的名稱。這個值為為‘arm’,表示兼容任何ARM的編譯,並獨立於CPU架構的修訂。
TARGET_PLATFORM
當Android.mk文件解析的時候,Android目標平台的名稱。如,‘android-3’對應Android1.5 系統鏡像。如果想要了解平台名稱和對應Android系統鏡像的完整信息,請查看STABLE-APIS相關內容。
TARGET_ARCH_ABI
當Android.mk文件解析的時候,目標CPU+ABI的名稱。目前支持兩個值:
armabi
For ARMv5TE
Armabi-v7a
注意:升級到Android NDK1.6_r1,這個變量僅僅用‘arm’來定義。但是,現在這個值已經被重新定義,以便更好的匹配Android的內部使用。
想要了解更多關於ABI架構和相關的兼容性問題,請閱讀CPU-ARCH-ABIS相關部分。
在未來的NDK發布版本中,其他目標的ABIs可能會被引入,並且可能會有不同的名字。注意所有基於ARM的ABIs都會將‘TARGET_ARCH’定義為‘arm’,但是可能會有不同的‘TARGET_ARCH_ABI’。
TARGET_ABI
目標平台和ABI的關聯,實際上被定義為$(TARGET_PLATFORM)-$(TARGET_ARCH_ABI)。這個是非常有用的,當你想要為一個真實的設備測試一個指定的目標系統鏡像。
默認情況下,它的值為‘android-3-armeabi’。
(更新到Android NDK 1.6_r1,默認值為‘android-3-arm’)
NDK提供的宏:
----------------------
以下是GNU Make的‘function’宏,通過‘$(call
)‘來調用。它們返回文本信息:
my-dir
返回最近一次包含Makefile文件的路徑,通常是當前Android.mk所在目錄。在Android.mk開頭用來定義LOCAL_PATH是非常有用的:
LOCAL_PATH := $(call my-dir)
重要提示:由於GNU Make的工作方式,在解析編譯腳本過程中,它實際上返回的是最近一次包含Makefile文件的路徑。不要在包含另一個文件後調用my-dir。
例如,考慮下面的例子:
LOCAL_PATH := $(call my-dir)
… 聲明一個module
include$(LOCAL_PATH)/foo/Android.mk
LOCAL_PATH := $(callmy-dir)
… 聲明另一個module
在第二次調用my-dir的時候,由於在它前面包含了$(LOCAL_PATH)/foo/Android.mk,因此LOCAL_PATH被定義為$PATH/foo,而不是$PATH。
因為這樣,比較好的做法是,在Android.mk的最後再包含其他文件,例如:
LOCAL_PATH := $(call my-dir)
... declare one module
LOCAL_PATH := $(call my-dir)
... declare another module
# extra includes at the end of the Android.mk
include $(LOCAL_PATH)/foo/Android.mk
如果這樣不方便的話,把第一次調用my-dir的值保存到一個變量中。如:
MY_LOCAL_PATH := $(call my-dir)
LOCAL_PATH := $(MY_LOCAL_PATH)
... declare one module
include $(LOCAL_PATH)/foo/Android.mk
LOCAL_PATH := $(MY_LOCAL_PATH)
... declare another module
all-subdir-makefiles
返回當前‘my-dir’目錄以及所有子目錄中所有Android.mk文件位置的列表。例如,考慮下面的層次結構:
sources/foo/Android.mk
sources/foo/lib1/Android.mk
sources/foo/lib2/Android.mk
如果sources/foo/Android.mk包含這一行:
include $(call all-subdir-makefiles)
那麼它會自動的包含sources/foo/lib1/Android.mk 和 sources/foo/lib2/Android.mk。
這個函數主要用來為編譯系統提供更深層次的源代碼目錄結構。注意默認情況下,NDK僅僅查找sources/*/Android.mk中的文件。
this-makefiles
返回當前Makefile所在路徑(即函數被調用的位置)。
parent-makefile
返回目錄樹結構中parentMakefile的路徑。即被當前Makefile包含的那個Makefile文件的路徑。
grand-parent-makefile
你猜。。。(汗。。。)
import-module
允許你通過名字來查找和包含另一個module中的Android.mk文件。一個典型的例子是:
$(call import-module, )
它會在NDK_MODULE_PATH環境變量引用的目錄列表中,查找所有標記為的mudule,並自動為你包含它的Android.mk文件。
請閱讀IMPORT-MODULE相關內容,了解更多細節。
Module-description變量:
----------------------------------
下面的這些變量,用來描述編譯系統中的module。你必須在'include $(CLEAR_VARS)' 和 'include $(BUILD_XXXXX)'之間來定義一些變量。根據前面的描述,$(CLEAR_VARS)會清除所有這些變量的定義,除非在它們的描述中顯示的指出來。
LOCAL_PATH
這個變量表示當前文件的路徑。你必須在Android.mk的開始的時候定義:
LOCAL_PATH := $(call my-dir)
這個變量不會被$(CLEAR_VARS)清除,因此每一個Android.mk只需要定義一次(即使一個文件裡面定義了很多個modules)。
LOCAL_MODULE
這個是module的名稱。在所有modules中,它必須是唯一的,不能包含空白字符。你必須在包含$(BUILD_XXXX)腳本之前定義它。
默認情況下,module name決定了生成文件的名稱,如module的名稱是,那麼共享庫的名字是lib.so。但是,在NDK編譯腳本中(Android.mk或者Application.mk),你要引用其他module,只需要通過普通的名稱(如)引用即可。
你可以通過LOCAL_MODULE_FILENAME覆蓋這個默認值(see below)。
LOCAL_MODULE_FILENAME
這個變量是可選的,允許你重新定義生成文件的名稱。默認,module 總是生成lib.a的靜態庫或者lib.so的動態庫,這些都是Unix的約定。
你可以用LOCAL_MODULE_FILENAME覆蓋掉這個默認值,例如:
LOCAL_MODULE := foo-version-1
LOCAL_MODULE_FILENAME := libfoo
注意:在你的LOCAL_MODULE_FILENAME不需要添加路徑或者文件後綴,這些編譯系統會自動幫你處理好。
LOCAL_SRC_FILES
這個是編譯module的源文件列表。只有在這些列表中的源文件才能傳遞給編譯器,編譯系統會自動為你計算依賴關系。
注意這些源文件都是相對於LOCAL_PATH,你可以使用path components,如:
LOCAL_SRC_FILES := foo.c \
toto/bar.c
注意:在編譯文件中,總是要用Unix風格的正斜槓(/),而不要使用windows風格的反斜槓。
LOCAL_CPP_EXTCEPTION
這是一個可選的變量,用來定義C++源文件的後綴。必須要以一個點開頭,默認的是‘.cpp’,但是你可以修改它。如:
LOCAL_CPP_EXTCEPTION := .cxx
從NDK r7開始,你可以在這個變量中定義一序列的後綴,如:
LOCAL_CPP_EXTCEPTION := .cxx .cpp .cc
LOCAL_CPP_FEATURES
這是一個可選的變量,可以讓你的代碼使用一些c++的特性。為了讓你的代碼使用RTTI(RunTime Type Information),可以使用:
LOCAL_CPP_FEATURES := rtti
為了讓你的代碼支持c++異常,可以使用:
LOCAL_CPP_FEATURES := exceptions
你可以同時使用它們(順序不重要)
LOCAL_CPP_FEATURES := rtti features
這個變量的作用是,當從源代碼編譯module的時候,可以啟用正確的compiler/linker標志。對於預編譯二進制文件,這同樣有助於聲明二進制文件所依賴的特性,從而確保最終的鏈接器能正確工作。
建議你使用這個變量,代替在LOCAL_CPPFLAGS中直接定義-frtti、-fexceptions這種用法。
LOCAL_C_INCLUDES
相對於NDK根目錄的一個可選路徑列表,當編譯所有源代碼時(c,c++或者兩者的組合),將會添加到包含搜索路徑中。如:
LOCAL_C_INCLUDES := sources/foo
或者甚至:
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../foo
這些要放在LOCAL_CFLAGS / LOCAL_CPPFLAGS中對應包含的flag的前面。
當用ndk-gdb啟動本地調試的時候,LOCAL_C_INCLUDES 同樣會自動使用。
LOCAL_CFLAGS
當編譯c和c++源代碼的時候,傳遞給編譯器的可選的標志集合。
對於指定附加宏的定義或者編譯選項,是非常有幫助的。
重要:在Android.mk中不要試圖改變optimization/debugging的級別,通過在Application.mk中指定合適的信息,系統會幫你自動處理,而且在debug過程中,NDK會生成有用的數據文件。
注意:在android-ndk-1.5_r1中,相應的標志只能應用在c文件上,不能用在c++上。這個問題已經被修正,從而匹配整個Android編譯系統的行為。(你可以使用LOCAL_CPPFLAGS為c++源文件指定標志)
你可以通過LOCAL_CFLAGS += -I來指定額外的包含路徑,但是,對於這個使用LOCAL_C_INCLUDES會更好,因為這些路徑可能在用ndk-gdb本地調試的時候會被用到。
LOCAL_CXXFLAGS
LOCAL_CPPFLAGS的別名。注意在後面的版本中,這個標志可能會被移除掉。
LOCAL_CPPFLAGS
當編譯c++源文件的時候(只編譯c++),傳遞給編譯器的可選的標志集合。它們出現在LOCAL_CFLAGS之後的編譯器的命令行上。
注意:在android-ndk-1.5_r1中,相應的flag同時運用於c和c++源代碼。這些已經得到修正,以匹配整個Android編譯系統。(現在你可以使用LOCAL_CFLAGS來指定c和c++源代碼的標志)。
LOCAL_STATIC_LIBRARIES
應該鏈接到這個module的靜態庫modules(用BUILD_STATIC_LIBRARY編譯)列表。這在共享庫模塊才有意義。
LOCAL_SHARED_LIBRARIES
運行時這個module依賴的動態共享庫‘modules’列表。這個在鏈接的時候是有必要的,同時會在生成的文件中嵌入相應的信息。
LOCAL_WHOLE_STATIC_LIBRARIES
它是LOCAL_STATIC_LIBRARIES(用來表達相應library module)的一個變體,對於鏈接器它應該使用‘whole archives’。可以查看GNU 鏈接器的文檔來了解–whole-archive這個標志。
當很多靜態庫之間中有環形依賴的時候,這個通常是非常有用的。注意當用它來編譯動態庫的時候,會強制將你的整個靜態庫中的所有對象文件添加到最終的二進制文件中。雖然在生成可執行文件的時候是不正確的。
LOCAL_LDLIBS
當編譯module時,被使用的附加的鏈接器標志列表。使用“-l”前綴來傳遞指定系統庫的名稱是非常有用的。例如,下面這些將告訴鏈接器生成一個module,在加載的時候鏈接到/system/lib/libz.so。
LOCAL_LDLIBS := -lz
查看STABLE-APIS相關內容,了解這個NDK版本能夠鏈接的系統庫列表。
LOCAL_ALLOW_UNDEFINED_SYMBOLS
默認情況下,當試圖編譯動態庫時,如果沒有定義任何引用,將會導致“undefined symbol”的錯誤。這對在代碼中捕捉bug是非常有幫助的。
然而由於某些原因你需要禁用這個檢查,設置這個值為‘true’。注意對應的動態庫可能在運行時會加載失敗。
LOCAL_ARM_MODE
默認情況下,ARM目標二進制文件將生成在‘thumb’模式,其中每個指令是16位寬。如果你想強制生成‘arm’(32位指令)模式下module的對象文件,你可以定義這個變量為‘arm’。例如:
LOCAL_ARM_MODE := arm
注意你也可以在源文件加上後綴‘.arm’來告訴編譯系統,你只想對某個源文件使用arm指令。例如:
LOCAL_SRC_FILES :=foo.c bar.c.arm
告訴編譯系統總是用ARM模式編譯‘bar.c’,根據LOCAL_ARM_MODE的值編譯foo.c。
注意:在Application.mk設置APP_OPTM為‘debug’,同樣會強制生成ARM二進制文件。這是因為工具鏈調試器存在的一個bug,並沒有很好的處理thumb代碼。
LOCAL_ARM_NEON
定義這個變量為‘true’,允許在c和c++代碼中使用ARM Advanced SIMD (又名 NEON)GCC指令,在組織文件中使用NEON指令。
只有目標為‘armeabi-v7a’ABI(對應於ARMv7指令集),才應該定義它。注意並不是所有基於ARMv7的CPUs都支持NEON指令集擴展,比較安全的做法是在運行時檢測是否能夠使用這個代碼。如果要了解更多細節,請閱讀CPU-ARM-NEON和CPU-FEATURES相關內容。
你也可以使用‘.neon’後綴指定某個特定的源文件支持NEON指令編譯,例如:
LOCAL_SRC_FILES =foo.c.neon bar.c zoo.c.arm.neon
在這個例子,‘foo.c’在thumb+neon模式下編譯,‘bar.c’在‘thumb’模式下編譯,‘zoo.c’在‘arm+neon’模式下編譯。
注意‘.neon’後綴必須出現在‘.arm’的後面,如果你同時使用的話。(如foo.c.arm.neon可以工作,但是foo.c.neon.arm不行!)
LOCAL_DISABLE_NO_EXECUTE
Android NDK r4為“NX bit”的安全功能提供支持。默認這個是啟用的,如果你確實需要禁用,可以設置這個變量為‘true’。
注意:這個功能不會修改ABI,只是在內核目標ARMv6+CPU的設備上啟用。
想要了解更多信息,請看:
http://en.wikipedia.org/wiki/NX_bit
http://www.gentoo.org/proj/en/hardened/gnu-stack.xml
LOCAL_DISABLE_RELRO
默認情況下,NDK編譯後的代碼是只讀的進行移動位置並得到GOT保護。這個會指示運行時鏈接器標記特定的內存區是只讀的,在移動位置之後。這樣會使得某些安全漏洞(如GOT覆蓋)更難執行。
默認它是啟用的,但是如果你確實需要,你可以禁用它通過設置變量為‘true’。
注意:這些保護只對新的Android設備有效("JellyBean" 和更高的版本)。代碼依然能夠運行在舊版本上(盡管沒有內存保護)。
想要了解更多信息,請看:
http://isisblogs.poly.edu/2011/06/01/relro-relocation-read-only/ http://www.akkadia.org/drepper/nonselsec.pdf (section 6)
LOCAL_EXPORT_CFLAGS
定義這個變量是為了記錄c/c++編譯器flags的集合,這些flags會被添加到任何其他module定義的LOCAL_CFLAGS中,而這個module通過LOCAL_STATIC_LIBRARIES 或者LOCAL_SHARED_LIBRARIES使用它。
例如,考慮module‘foo’下面的定義:
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_EXPORT_CFLAGS := -DFOO=1
include $(BUILD_STATIC_LIBRARY)
另一個module‘bar’,依賴於它:
include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.c
LOCAL_CFLAGS := -DBAR=2
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)
當編譯bar.c的時候,標志'-DFOO=1 -DBAR=2'將會傳遞給編譯器。
Exported flags被加在你module的LOCAL_CFLAGS中,所以你可以簡單的覆蓋它們。它們也可以傳遞:如果‘zoo’依賴‘bar’,‘bar’依賴‘foo’,那麼‘zoo’將繼承‘foo’導出的所有flags。
最後,當編譯的module導出它們時,exported flags不會被使用。在上面的例子中,當編譯foo/foo.c時,-DFOO=1不會傳遞給編譯器。
LOCAL_EXPORT_CPPFLAGS
和LOCAL_EXPORT_CFLAGS相同,但是只針對c++標志。
LOCAL_EXPORT_C_INCLUDES
和LOCAL_EXPORT_CFLAGS相同,但是它是針對c包含路徑的。這是非常有用的,如果‘bar.c’想要包含module‘foo’提供的頭文件。
LOCAL_EXPORT_LDLIBS
和LOCAL_EXPORT_CFLAGS相同,但是它是針對鏈接器標志的。注意由於Unix鏈接器的工作方式,被導入的鏈接器標志將append到你module的LOCAL_LDLIBS中。
這是非常有用的,當module‘foo’是一個靜態庫和它有代碼依賴於系統庫的時候。LOCAL_EXPORT_LDLIBS可以用來導出這個依賴關系。例如:
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_EXPORT_LDLIBS := -llog
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.c
LOCAL_STATIC_LIBRARIES :=foo
這裡,libbar.so在鏈接器命令的尾部會使用-llog進行編譯,表明它依賴於系統日志庫,因為它依賴於‘foo’。
LOCAL_SHORT_COMMANDS
設置這個變量為‘true’,當你的module有很多的源文件,或者依賴很多的靜態或動態庫。這會強制編譯系統使用一個中間的列表文件,並通過@$(listfile) 語法和library archiver 或者 static linker一起使用。
這在Windows上是非常有用的,因為它的命令行只接收最大8191個字符,這對於復雜的工程來說太小了。
這同樣也會影響單個源文件的編譯,如果將所有的編譯器選項放在列表文件裡面。
注意如果設置了‘true’以外的值,都會恢復成默認行為。你也可以在Android.mk文件中定義APP_SHORT_COMMANDS來強制使你的工程中的所有modules使用這項功能。
注意:默認我們不推薦啟用這個功能,因為它會使得編譯變慢。
LOCAL_FILTER_ASM
為shell命令定義這個變量,將會過濾從你的LOCAL_SRC_FILES匯編或生成的文件。
當它被定義時,將發生下面的事情:
- 所有的c或者c++會生成到一個臨時匯編文件(而不是編譯進對象文件中)。
- 任何臨時的、在LOCAL_SRC_FILES列出的匯編文件通過LOCAL_FILTER_ASM命令發送來生成另一個臨時的匯編文件。
- 這些被過濾後的匯編文件被編譯到對象文件中。
換句話說,如果你有:
LOCAL_SRC_FILES := foo.c bar.S
LOCAL_FILTER_ASM := myasmfilter
foo.c --1--> $OBJS_DIR/foo.S.original --2--> $OBJS_DIR/foo.S--3-->$OBJS_DIR/foo.o
bar.S --2--> $OBJS_DIR/bar.S --3-->$OBJS_DIR/bar.o
“1”對應編譯器,“2”對應過濾器,“3”對應匯編。過濾器必須是獨立的shell命令,把輸入文件的名稱作為第一個參數,輸出文件的名稱作為第二個參數,例如:
myasmfilter$OBJS_DIR/foo.S.original $OBJS_DIR/foo.S
myasmfilter bar.S $OBJS_DIR/bar.S
http://android.mk