編輯:關於Android編程
譯者注:第一次做這樣的翻譯,自己感覺還是很多不足,有些概念沒有很好的理解,所以翻譯過來的中文可能也會有問題。這篇文章主要是用來記錄自己的學習所得。所以網友們若要根據下面的譯文來學習,不是不行,但是請謹慎。
這篇文章描述了Android.mk文件的語法,這個文件將Android NDK與你的c/c++代碼聯系到一起。
這個Android.mk文件存在於你的project下的jni目錄的子目錄中,它向編譯系統描述了你的源碼和共享庫。這個文件是GNU makefile的一個小的片段,編譯系統會讀取它一次或者多次。The Android.mk file is useful for defining project-wide settings that Application.mk, the build system, and your environment variables leave undefined。 It can also override project-wide settings for specific modules.
你可以利用Android.mk的語法將你的源碼分為多個module。一個module可以是一個靜態庫,或者是一個共享庫,又或者是一個獨立的可執行文件。你可以在每個android.mk文件中定義一個或者多個module,而且你還可以在不同的module中使用相同的源文件。編譯系統只會將共享庫放到你的應用的包中。另外,靜態庫是可以生成共享庫的。
為了打包這些庫,編譯系統為你處理了大量的細節。例如,你不必要在android.mk中列出頭文件,也不必列出生成的文件之間的明確的依賴關系。NDK編譯系統已經為你自動的計算好了這些關系。因此,你應該從未來的支持新的toolchain/platform的NDK版本中獲得便利,不用去編輯Android.mk文件。
此android.文件的語法與Android Open Source Project中使用的 Android.mk文件非常接近。While the build system implementation that uses them is different, their similarity is an intentional design decision aimed at making it easier for application developers to reuse source code for external libraries。
在開始探索Android.mk文件的語法之前,先理解Android.mk的基本組件會非常有用。這章裡面使用了Hello-JNI 示例工程裡面的Android.mk,並且解釋了這個文件中的每一行所扮演的角色。
一個Android.mk文件必須以定義LOCAL_PATH 開始:
LOCAL_PATH := $(call my-dir)
這個變量指示了源碼文件在development tree中的位置。這裡,my-dir這個宏函數使用編譯系統提供的,返回了當前目錄的路徑(這個目錄包含了 Android.mk文件本身)。
接下來的一行定義了CLEAR_VARS 這個變量的是由編譯系統提供的。
include $(CLEAR_VARS)
CLEAR_VARS這個變量指向了一個特殊的 GNU Makefile,這個Makefile會為你清除很多類似於LOCAL_XXX 的變量,例如LOCAL_MODULE,LOCAL_SRC_FILES,以及LOCAL_STATIC_LIBRARIES。注意,這裡並沒有清除LOCAL_PATH。這個變量必須保持它的值因為the system parses all build control files in a single GNU Make execution context where all variables are global。你必須在描述每個module之前都要聲明一下這個變量。
然後,LOCAL_MODULE 這個變量用來存你想要編譯的module的名字。在你的應用的每個module中都要使用一次這個變量。
LOCAL_MODULE := hello-jni
每個module的名字都必須是唯一的並且不能包含空格。當編譯系統生成最終的共享庫時,會自動把你賦予LOCAL_MODULE 的值加上前綴和後綴,例如,上面的例子會生成一個名字為libhello-jni.so的庫。
注意:如果你的module的名字的前綴已經加上了lib,編譯系統就不會再為你加前綴了,它會直接以這個module的名字為共享庫的名字,並加上.so的擴展名。所以,假如一個源文件的名字本來就叫libfoo.c,那麼產生的共享庫的名字就是libfoo.so。這種特性是為了支持 Android platform sources通過Android.mk產生的共享庫;像這樣的庫的名字都會以lib開頭。
接下來的一行列出源文件,使用空格隔離不同的源文件:
LOCAL_SRC_FILES := hello-jni.c
LOCAL_SRC_FILES 必須包括你想要包含進module的c/c++的源文件的列表。
最後一行幫助系統把每件事物聯系起來。
include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY 這個變量指向一個GNU Makefile腳本,這個腳本會收集自你定義的從最近的include之後的每個LOCAL_XXX變量的信息。這個腳本確定了build什麼東西,以及怎麼build.
這裡還有更加復雜的示例代碼,在samples 文件夾裡面,這些代碼都包含有帶注釋的Android.mk文件。除此以外,Sample: native-activity 提供了很詳細的關於 Android.mk 文件的解釋。最後,Variables and Macros提供了對這章中的變量的更深入的解釋。
編譯系統提供了很多可以在 Android.mk 裡面使用的變量。大部分變量都是預先指定好了值。其他的變量的值你來指定。
除了這些變量以外,你還可以定義自己的變量。如果你打算這樣做,記住NDK系統保留了以下變量名:
以LOCAL_開頭的名字,例如LOCAL_MODULE。
以PRIVATE_、NDK_或者APP開頭的。編譯系統在內部使用這些變量名。
小寫的變量名,例如my-dir。編譯系統同樣在內部使用這些變量名。
如果你想要在 Android.mk中定義自己的變量,我們建議你在名字前面加上MY_ 。
這一章我們討論 GNU Make 變量,這些變量是在編譯系統解析Android.mk 文件之前就定義好了的。在某些情況下,NDK會多次解析你的Android.mk文件,每一次使用不同的定義去解析其中一些變量。
這個變量指向一個構建腳本,這個腳本的作用是清除幾乎所有的在上一章提到的LOCAL_XXX 變量。在描述一個新的module之前使用這個變量去引用這個腳本使用它的語法是:
include $(CLEAR_VARS)
這個變量指向了一個腳本,這個腳本會收集你在每個module定義的LOCAL_XXX變量信息,而且這個變量還確定了怎樣使用你的源碼去編譯一個共享庫。注意,使用這個變量需要你至少已經定義了LOCAL_MODULE 和LOCAL_SRC_FILES。(如需查看更多信息,參考 Module-Description Variables)
使用這個變量的語法如下:
include $(BUILD_SHARED_LIBRARY)
一個這樣的變量會使編譯系統生成一個以.so結尾的庫。
這個變量是BUILD_SHARED_LIBRARY 的一個變體,是用來生成一個靜態庫。構建系統並不會把靜態庫包含進你的工程裡面,但是可以利用靜態庫生成共享庫(參考 LOCAL_STATIC_LIBRARIES 和 LOCAL_WHOLE_STATIC_LIBRARIES,在下面)。這個變量的語法是:
include $(BUILD_STATIC_LIBRARY)
這樣的一個變量會使編譯系統生成一個以.a結尾的庫。
指向一個腳本,這個腳本被用來指定一個預構建的共享庫。與BUILD_SHARED_LIBRARY 和 BUILD_STATIC_LIBRARY 不同,LOCAL_SRC_FILES 的值不能是一個源文件,它必須是一個單獨的指向預構建的共享庫的路徑,例如foo/libfoo.so。使用這個變量的語法是:
include $(PREBUILT_SHARED_LIBRARY)
你也可以在另一個module裡面使用LOCAL_PREBUILTS 變量來引用一個預構建的庫。更多信息查看 Using Prebuilt Libraries。
與 PREBUILT_SHARED_LIBRARY 相同,只是指向的一個預構建的靜態庫。更多信息請見 Using Prebuilt Libraries。
這個變量是目標CPU架構的名字,就像 Android Open Source Project 裡面指定了目標CPU架構。這個變量用於任意的ARM兼容的構建,或者ARM,或者是獨立於CPU結構的修訂,或者ABI (見下方 TARGET_ARCH_ABI)。
這個變量的值是從你在 Android.mk 文件定義的APP_ABI 中得到的,系統會在解析Android.mk 文件之前讀取APP_ABI 。
這個變量代表系統構建的目標Android API 的數字。例如,Android 5.1對應Android API 22:android-22。想要知道完整的系統和api對應的關系,請參考 Android NDK Native APIs。下面的例子展示了如何使用這個變量:
TARGET_PLATFORM := android-22
當編譯系統解析Android.mk文件的時候,這個變量存儲CPU和架構的名字。你可以指定一個或者多個下面列出的名字,使用空格分隔兩個名字,Table 1 展示了使用每種CPU和架構時ABI的設置。
Table 1. 對於不用的CPU和架構,ABI的設置。
下面的例子展示了如何設置ARMv8 AArch64 為目標架構:
TARGET_ARCH_ABI := arm64-v8a
注意: Android NDK 1.6_r1之前這個這個變量被定義為arm。
如需了解更多關於架構ABIs和相關問題,參考 ABI Management;
未來出現的新的架構ABI會有不同的值。
將API的級別和ABI聯系在一起,當你在真機上調試系統的時候特別有用。例如,指定一個64位的搭載Android 22的ARM設備:
TARGET_ABI := android-22-arm64-v8a
注意: 直到 Android NDK 1.6_r1,默認的值是android-3-arm。
這章的這些變量用於描述你的module用於系統構建。每一條module的描述都應遵從以下原則:
如需初始化或者去掉與此module相關的變量,使用CLEAR_VARS 。 通過給這些變量賦值的方式來描述module。 如需設置NDK使用合適的腳本編譯module,使用BUILD_XXX 。這個變量的作用是給出當前文件的路徑。你必須在 Android.mk文件的開頭定義它。下面的例子展示了怎樣使用:
LOCAL_PATH := $(call my-dir)
指向CLEAR_VARS的腳本不會清除這個變量。因此,即使你的Android.mk文件裡面定義了幾個module,你仍然只需要定義一次這個變量。
這個變量存儲你的module的名字。在所有定義的module中這個變量的值必須是唯一的,並且不能包含空格。你必須在包含任何腳本文件之間就要定義它(除了 CLEAR_VARS)。你不必要添加lib前綴或者.so和.a後綴。編譯系統會自動添加前綴和後綴。在 Android.mk和Application.mk文件裡面都是通過引用module的名字來表示該module的。(Throughout your Android.mk and Application.mk files, refer to your module by its unmodified name)。例如,下面這句會生成一個名為libfoo.so 的共享庫module:
LOCAL_MODULE := "foo"
如果你希望生成的庫的名字不是lib加上LOCAL_MODULE 的值,你可以使用LOCAL_MODULE_FILENAME 來設置你想要的名字。
這個變量是可選的,允許你通過這個變量來設置生成的庫的名字而不是采用系統默認的名字。例如,你的LOCAL_MODULE 的值是foo,你可以強制讓系統生成的庫的名字為 libnewfoo。下面的一行展示了如何做:
LOCAL_MODULE := foo
LOCAL_MODULE_FILENAME := libnewfoo
如果是生成一個共享庫,那麼文件的名字會是 libnewfoo.so。
注意: 你i無法做到修改文件路徑或者後綴名。
這個變量包含你想要組成module的源文件的列表。只要列出需要編譯器編譯的源文件就可以了,編譯系統會自動計算出依賴關系。
注意絕對路徑和相對路徑你都可以使用。
我們建議你避免使用絕對路徑,這樣可以使你的 Android.mk文件更加輕便。
注意: 在構建文件裡面應只使用unix風格 的正斜槓(/)。構建系統不識別Windows風格的反斜槓(\)。
你可以使用這個可選的變量來指定你的C++源文件的除了.cpp以外其他的後綴名。例如,下面的例子將後綴名變成了 .cxx (必須包含前面的‘.’):
LOCAL_CPP_EXTENSION := .cxx
自從 NDK r7 以後,你可以使用這個變量指定多個後綴名。例如:
LOCAL_CPP_EXTENSION := .cxx .cpp .cc
你可以使用這個可選的變量來指明你的代碼依賴於特別的C++特性。它會在構建的過程中使用對應的編譯器和鏈接器。這個變量還可以定義那些預構建的二進制文件所依賴的特性,以幫助最後的鏈接過程變正確。我們建議你使用這個變量而不是使用LOCAL_CPPFLAGS 直接打開frtti 和 fexceptions 特性。使用這個變量可以幫助編譯系統為每個module設一個單獨的合適的信號值(flags )。使用 LOCAL_CPPFLAGS 會導致編譯器為所有的module設置所有的指定的信號值,而不管真正需要的是什麼。
例如,指定你的代碼使用RTTI(運行時類型信息),寫下:
LOCAL_CPP_FEATURES := rtti
指定你的代碼使用C++異常:
LOCAL_CPP_FEATURES := exceptions
你也可以指定多個值:
LOCAL_CPP_FEATURES := rtti features
值的先後順序並不重要。
你可以使用這個變量去指定NDK編譯代碼(C,C++,匯編)的時候include的路徑。例如:
LOCAL_C_INCLUDES := sources/foo
甚至:
LOCAL_C_INCLUDES := $(LOCAL_PATH)//foo
在使用 LOCAL_CFLAGS 和 LOCAL_CPPFLAGS 設置include之前就要定義這個變量。
編譯系統還會在使用ndk-gdb調試作原生的調試的時候使用LOCAL_C_INCLUDES 定義的路徑。
這個可選的變量設置編譯系統在編譯C和C++代碼時需要傳遞的編譯器標記(compiler flags)。這個特性在指定額外的宏定義或者編譯選項的時候會非常有用。
盡量不要在Android.mk中更改 optimization/debugging 的級別。編譯系統會自動根據 Application.mk中的相關信息為你設置這個變量。使用這種方式編譯系統會生成在調試時很有用的數據文件。
注意: 在android-ndk-1.5_r1中,這個flag值僅用於c文件中,c++文件不行。現在他們適配了完整的Android構建系統的特性。(你現在可以使用LOCAL_CPPFLAGS 專門設置C++文件的flag)。
通過線面這種方式指定額外的include路徑是可能的:
LOCAL_CFLAGS += -I
相比使用LOCAL_C_INCLUDES ,這樣做更好,因為這樣的話在使用ndk-gdb調試原生程序的時候也可以使用這些路徑。
這個變量是可選的僅用於編譯C++源文件的時候需要傳遞的編譯器標記。LOCAL_CPPFLAGS變量會在編譯器的命令行中出現,是在LOCAL_CFLAGS 出現之後。
*注意:* 在android-ndk-1.5_r1中,這個變量同時作用於C和C++源文件。如果要為C和C++都指定編譯器標記,使用LOCAL_CFLAGS。
這個變量指定了當前module依賴的靜態庫。
如果當前的module是共享庫或者可執行文件,這個變量會強制讓這些庫被連接進最後生成的二進制文件中。
如果當前的module是靜態庫,這個變量僅表示依賴於當前module的其他module也依賴於此變量指定的庫。
這個變量指定了當前module在運行時依賴的共享庫。這個變量的信息在鏈接時是必需的,這個變量會將對應的信息嵌入到最終生成的文件中。
這個變量是LOCAL_STATIC_LIBRARIES的一個變種,它表示鏈接器應該將相關聯的庫認為是 whole archives。獲取更多關於whole archives的信息可以查看GNU 鏈接器的文檔,查看 –whole-archive 標記。
當幾個靜態庫中存在循環的依賴時這個變量非常有用。當你使用這個變量構建一個共享庫時,這個變量會強制讓編譯系統把所有的object文件從靜態庫中拷貝到最後的庫中。然後當你要生成可執行文件時這樣做就不對了。
這個變量包含了額外的鏈接器標記,這些標記在構建你的共享庫或者可執行文件時會使用到。這個變量允許你通過以-l為前綴傳遞你指定的系統中的庫的名字。例如,下面的例子告訴鏈接器生成一個module,這個module在加載的時候鏈接上了 /system/lib/libz.so 。
LOCAL_LDLIBS := -lz
如果要查看可以在NDK中使用的系統庫的列表,查看 Android NDK Native APIs。
注意: 如果你在靜態庫中定義了這個變量,編譯系統會忽略它,並且ndk-build會打印警告。
這個變量表示編譯系統在構建共享庫或者可執行文件時需要的其他的鏈接器標記的列表。下面的例子使用ARM/X86 GCC 4.6+平台的ld.bfd鏈接器,其中ld.gold 是默認的:
LOCAL_LDFLAGS += -fuse-ld=bfd
注意: 如果你在靜態庫中定義了這個變量,編譯系統會忽略它,並且ndk-build會打印警告。
默認的情況是,編譯系統如果在構建一個共享庫時發現了一個未定義的引用時會拋出一個未定義錯誤(undefined symbol error)。這個錯誤在你尋找bug的時候很有用。
若要關閉這個檢查,設置這個變量為true即可。注意這樣做可能導致共享庫在運行時加載。
注意: 如果你在靜態庫中定義了這個變量,編譯系統會忽略它,並且ndk-build會打印警告。
默認地,在thumb 模式下編譯系統會生成ARM架構的二進制文件,這種模式下的都是16位的,並且會會鏈接thumb/目錄下的STL 庫文件。將這個變量定義為arm 會起強制編譯系統以32位的arm模式生成該module的object 文件。下面展示了怎樣做:
LOCAL_ARM_MODE := arm
你也可以讓編譯系統只針對你指定的文件以arm模式編譯,你需要在源文件的名字上加上.arm的後綴。例如,下面的例子會告訴編譯器總是以arm模式編譯bar.c,但是對於foo.c是根據LOCAL_ARM_MODE的值來編譯的。
LOCAL_SRC_FILES := foo.c bar.c.arm
注意: 你還可以通過設置 Application.mk中的 APP_OPTIM來實現生成ARM 的二進制文件用來調試。指定debug 會強制以ARM模式構建,因為工具鏈的調試器不會正確的處理Thumb 模式的代碼。
這變量僅在指定為armeabi-v7a ABI的時候有用。這個變量允許你在你的C、C++和匯編裡面使用ARM 高級SIMD (NEON) GCC本證函數。
要注意並不是所以的ARMv7系列的CPU都支持NEON 指令集擴展。由於這個原因,你必須在運行時檢查,以便於安全地運行代碼。更多信息查看NEON Support 和The cpufeatures Library。
或者,你還可以通過在源文件的名字後面加上.neon的方式讓編譯器針對指定的文件采取neon的支持。在下面的例子中,編譯系統會以thumb 和 NEON支持的方式編譯foo.c ,以thumb 支持的方式編譯bar.c ,以ARM和NEON支持的方式編譯zoo.c。
LOCAL_SRC_FILES = foo.c.neon bar.c zoo.c.arm.neon
如果這些後綴你都要使用,那麼確保.arm要在.neon之前。
Android NDK r4添加了 “NX bit”的安全特性的支持。這個是默認開啟的,但是你可以通過設置這個變量為true來關閉它。我們不建議你在沒有一個很好的理由的情況下這樣做。
這項特性不會修改ABI,而且只會在ARMv6+的CPU的內核中啟用。開啟了這樣特性的機器代碼會無修改地在運行在使用更早的CPU架構的設備上。
更多信息請參考Wikipedia: NX bit 和 The GNU stack kickstart。
默認的,NDK利用只讀的重定位地址和GOT保護。這個變量使運行時的鏈接器對重定位後的某些內存區域做出標記作為只讀的內存,使得某些安全漏洞更加困難(例如GOT重寫)。注意這些保護只在API 16 以後才具有,當API 低於16,這些代碼任然會運行,但是沒有內存保護。
這個變量默認是打開的,你也可以通過設置這個變量為true的方式關閉。沒有一個很好的理由的話我們不建議你這樣做。
更多信息查看 RELRO: RELocation Read-Only 和 Security enhancements in RedHat Enterprise Linux (section 6)。
默認的,編譯系統編譯時具有字符串保護。這樣做會導致一個編譯器的錯誤,如果一個非常量(non-constant )的字符串被用於類似於printf的函數裡面。
這個變量默認是打開的,你也可以通過設置這個變量為true的方式關閉。沒有一個很好的理由的話我們不建議你這樣做。
這個變量將一系列本module的 C/C++編譯標記添加到通過LOCAL_STATIC_LIBRARIES 和 LOCAL_SHARED_LIBRARIES 來引用本module的那些module的LOCAL_CFLAGS 值裡面。
例如,觀察下面這兩個module,foo和bar,bar依賴於foo:
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_EXPORT_CFLAGS := -DFOO=1
include $(BUILD_STATIC_LIBRARY)
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 給編譯器。編譯系統還會預先將那些你所引用的module的LOCAL_CFLAGS 的值添加到你現在的module的LOCAL_CFLAGS 裡面,這樣你就可以很簡單的重寫它們了。
另外,module之間的關系是可傳遞的,如果zoo 依賴於 bar,bar依賴於foo,那麼zoo也會繼承從foo那裡來的標記。
最後,編譯系統在本地編譯的時候並沒有使用導出的標記(例如編譯一個標記被導出的module)。因此,在上面的例子中,編譯foo/foo.c的時候並沒有向編譯器傳遞-DFOO=1 。如果要本地編譯,使用LOCAL_CFLAGS 。
(譯者注:此處的本地編譯(building locally)的概念不是很清楚)
這個變量和 LOCAL_EXPORT_CFLAGS 是一樣的,只是這個變量只適用於C++標記。
這個變量和LOCAL_EXPORT_CFLAGS是一樣的,但是用於C的include的路徑。例如,當bar.c需要引入foo的頭文件時這個變量就很有用。
這個和LOCAL_EXPORT_CFLAGS是一樣的,只是這個用於鏈接器標識。
這個和LOCAL_EXPORT_CFLAGS是一樣的,告訴構建系統將指定的系統庫的名字傳遞給編譯器。你需要在你指定的庫的名字前加上 -l。
注意構建系統會把鏈接器標識導入到你的module的LOCAL_LDLIBS 值裡面。這樣做是因為Unix鏈接器的工作方式。
當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
include $(BUILD_SHARED_LIBRARY)
在這個例子裡面,構建系統會在構建libbar.so的時候將-llog加到鏈接器命令的末尾。這樣做告訴了鏈接器:因為 libbar.so依賴於foo,所以它也會依賴於系統的log庫。
當你的module裡面含有很多源碼或者依賴於靜態庫或共享庫的時候將這個變量設置為true。Doing so forces the build system to use @ syntax for archives containing intermediate object files or linking libraries.
這個特性在Windows平台很有用,因為Windows平台的命令行最大包含8191個字符,對於復雜系統顯得太小了。 It also impacts the compilation of individual source files, placing nearly all compiler flags inside list files, too.
注意任何不是true的值都會導致變成默認的設置。你也可以在Application.mk文件裡面強制規定你的工程的所有的module的行為。
我們不建議默認開啟這項特性,因為會讓構建系統變得更慢。
當構建靜態庫的時候設置這個變量為true。這樣做會生成一個輕的、小的庫文件,這個庫文件一般不包含object文件,僅包含指向這些object文件的路徑。
這樣做對於減小輸出文件的大小很有用。這樣做的一個缺點是這個樣的庫文件不能移動到一個其他的位置(因為庫文件的裡的路徑都是相對路徑)。
有效的值有,true,false,或者空格。你可以在 Application.mk 的APP_THIN_ARCHIVE上設置一個默認的值。
注意: 在非靜態庫或者預構建靜態庫的時候這個變量是被忽略的。
(不是很理解,待翻譯)
Define this variable as a shell command that the build system will use to filter the assembly files extracted or generated from the files you specified for LOCAL_SRC_FILES.
Defining this variable causes the following things to occur:
The build system generates a temporary assembly file from any C or C++ source file, instead of compiling them into an object file.
The build system executes the shell command in LOCAL_FILTER_ASM on any temporary assembly file and on any assembly file listed in LOCAL_SRC_FILES, thus generating another temporary assembly file.
The build system compiles these filtered assembly files into an object file.
For example:
LOCAL_SRC_FILES := foo.c bar.S
LOCAL_FILTER_ASM :=
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” corresponds to the compiler, “2” to the filter, and “3” to the assembler. The filter must be a standalone shell command that takes the name of the input file as its first argument, and the name of the output file as the second one. For example:
myasmfilter $OBJS_DIR/foo.S.original $OBJS_DIR/foo.S
myasmfilter bar.S $OBJS_DIR/bar.S
這個章節介紹了NDK提供的GNU Make的函數宏。使用$(call
來求值,他們會返回文本信息。
這個宏返回最近加入的makefile的路徑,一般是當前的Android.mk的路徑。 my-dir在你的Android.mk 開頭的LOCAL_PATH 的定義中很有用,例如:
LOCAL_PATH := $(call my-dir)
由於GNU Make 的工作方式,這個宏的返回值是構建系統在解析構建腳本的時候最後引入的makefile的路徑。由於這個原因,你不應該在include其他的文件之後還繼續使用my-dir。
例如,思考下面的例子:
LOCAL_PATH := $(call my-dir)
Android.mk
..........declare one module
include $(LOCAL_PATH)/foo/
LOCAL_PATH := $(call my-dir)
..........declare another module
這裡的問題在於第二個my-dir的調用將LOCAL_PATH 的值設置為了$PATH/foo
而不是$PATH/foo
,因為$PATH/foo
才是最近include的路徑。
你可以在Android.mk文件中加入一些額外的includes來避免這個問題。例如:
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 file
include $(LOCAL_PATH)/foo/Android.mk
如果這樣做不可行,那麼你可以將第一次調用my-dir的值存在另一個變量裡面,例如:
MY_LOCAL_PATH := $(call my-dir)
Android.mk
LOCAL_PATH := $(MY_LOCAL_PATH)
... declare one module
include $(LOCAL_PATH)/foo/
LOCAL_PATH := $(MY_LOCAL_PATH)
... declare another module
返回my-dir路徑下的所以子目錄裡面的Android.mk 的列表。
你可以使用這個函數將深沉次的嵌套關系提供給構建系統。默認地,NDK只會在含有 Android.mk文件的目錄裡面尋找文件。
返回當前的makefile文件的路徑()。
返回當前的包含當前的makefile的makefile的路徑。
Returns the path of the grandparent makefile in the inclusion tree (the path of the makefile that included the current one).
這是一個允許你通過module的名字找到並包含這個module的Android.mk文件。典型的應用如下:
$(call import-module,
在這個例子裡面,構建系統會根據NDK_MODULE_PATH這個環境變量所指示的目錄裡面尋找名為
的module,然後自動為你include對應的 Android.mk文件。
叨了個叨最近因為換工作的一些瑣事搞的我一個頭兩個大,也沒怎麼去學新東西,實在是有些愧疚。新項目用到了EventBus3.0,原來只是聽說EventBus的鼎鼎大名,一直沒
SharedPreferences是Android提供用來存儲一些簡單的配置信息的一種機制,例如,一些默認歡迎語、登錄的用戶名和密碼等。其以鍵值對的方式存儲
借助SQLiteOpenHelper幫助類實現對數據庫的創建和升級。MainActivity.javapackage com.example.databasetest;i
Android中WebView的一些簡單用法一直想寫一個關於 WebView 控件的 一些簡單運用,都沒什麼時間,這次也是擠出時間寫的,裡面的一些基礎知識就等有時間再更新