LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:= helloworld LOCAL_SRC_FILES := helloworld.c include $(BUILD_SHARED_LIBRARY)
MY_SOURCES := foo.c ifneq ($(MY_CONFIG_BAR),) MY_SOURCES += bar.c endif LOCAL_SRC_FILES += $(MY_SOURCES)
注意:‘:=’是賦值的意思;'+='是追加的意思;‘$’表示引用某變量的值。
LOCAL_SRC_FILES := foo.c toto/bar.c\
Hello.c
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # Build all java files in the java subdirectory LOCAL_SRC_FILES := $(call all-subdir-java-files) # Any libraries that this library depends on LOCAL_JAVA_LIBRARIES := android.test.runner # The name of the jar file to create LOCAL_MODULE := sample # Build a static jar file. include $(BUILD_STATIC_JAVA_LIBRARY)
注:LOCAL_JAVA_LIBRARIES := android.test.runner表示生成的JAVA庫的jar文件名
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_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 表示編譯一個靜態庫。
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 表示編譯一個共享庫。
out/target/product/generic/obj/APPS out/target/product/generic/obj/JAVA_LIBRARIES out/target/product/generic/obj/EXECUTABLE out/target/product/generic/obj/STATIC_LIBRARY out/target/product/generic/obj/SHARED_LIBRARY
每個模塊的目標文件夾分別為:
LOCAL_NO_MANIFEST
如果你的Package沒有Manifest(AndroidManifest.xml),你可以設置
LOCAL_NO_MANIFEST:=true. |
------分隔符,方便下次編輯修改------
If your package doesn't have a manifest (AndroidManifest.xml), then set LOCAL_NO_MANIFEST:=true. The common resources package does this. |
LOCAL_PACKAGE_NAME
LOCAL_PACKAGE_NAME變量是一個App的名字,例如:Dialer、Contacts等等。它可能在我們使用ant編譯系統編譯App時會發生改變。
LOCAL_PACKAGE_NAME is the name of an app. For example, Dialer, Contacts, etc. This will probably change or go away when we switch to an ant-based build system for the apps. |
LOCAL_PATH
LOCAL_PATH := $(call my-dir):每個Android.mk文件都必須以定義LOCAL_PATH變量開始,其目的是為了定位源文件的位置。例如:
LOCAL_PATH := $(my-dir) |
my-dir宏函數使用的是MAKEFILE_LIST變量,你必須在include其它任何makefile之前來調用它。另外,考慮到當你include任何子目錄時都要重新設置LOCAL_PATH,你必須在include它們之前設置它。
The directory your Android.mk file is in. You can set it by putting the following as the first line in your Android.mk: LOCAL_PATH := $(my-dir) The my-dir macro uses the MAKEFILE_LIST variable, so you must call it before you include any other makefiles. Also, consider that any subdirectories you inlcude might reset LOCAL_PATH, so do your own stuff before you include them. This also means that if you try to write several include lines that reference LOCAL_PATH, it won't work, because those included makefiles might reset LOCAL_PATH. |
LOCAL_PREBUILT_EXECUTABLES
LOCAL_PREBUILT_EXECUTABLES預編譯including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)時所用,指定需要復制的可執行文件。
When including $(BUILD_PREBUILT) or $(BUILD_HOST_PREBUILT), set these to executables that you want copied. They're located automatically into the right bin directory. |
LOCAL_PREBUILT_LIBS
LOCAL_PREBUILT_LIBS變量是在預編譯including $(BUILD_PREBUILT)或者$(BUILD_HOST_PREBUILT)時所用, 指定需要復制的庫.
When including $(BUILD_PREBUILT) or $(BUILD_HOST_PREBUILT), set these to libraries that you want copied. They're located automatically into the right lib directory. |
LOCAL_SHARED_LIBRARIES
LOCAL_SHARED_LIBRARIES變量用來列出模塊所需的共享庫的列表,不需要加上.so后綴。例如:
|
------分隔符,方便下次編輯修改------
These are the libraries you directly link against. You don't need to pass transitively included libraries. Specify the name without the suffix: LOCAL_SHARED_LIBRARIES := \ libutils \ libui \ libaudio \ libexpat \ libsgl |
LOCAL_SRC_FILES
LOCAL_SRC_FILES變量必須包含一系列將被構建和組合成模塊的C/C++源文件。
注意:不需要列出頭文件或include文件,因為生成系統會為你自動計算出源文件的依賴關系。默認的C++源文件的擴展名是.cpp,但你可以通過定義LOCAL_DEFAULT_EXTENSION來指定一個擴展名。
The build system looks at LOCAL_SRC_FILES to know what source files to compile -- .cpp .c .y .l .java. For lex and yacc files, it knows how to correctly do the intermediate .h and .c/.cpp files automatically. If the files are in a subdirectory of the one containing the Android.mk, prefix them with the directory name: LOCAL_SRC_FILES := \ file1.cpp \ dir/file2.cpp |
LOCAL_STATIC_LIBRARIES
LOCAL_STATIC_LIBRARIES變量和LOCAL_SHARED_LIBRARIES類似,用來列出你的模塊中所需的靜態庫的列表,你可以在你的module中包含一些想使用的靜態庫,通常我們使用共享庫,但是有些地方,像在sbin下的可執行程序和主機上的可執行程序我們要使用靜態庫。例如:
|
------分隔符,方便下次編輯修改------
These are the static libraries that you want to include in your module. Mostly, we use shared libraries, but there are a couple of places, like executables in sbin and host executables where we use static libraries instead.
|
LOCAL_MODULE
LOCAL_MODULE變量必須定義,用來標識在Android.mk文件中描述的每個模塊。名稱必須是唯一的,而且不包含任何空格。如果有其它moudle中已經定義了該名稱,那么你在編譯時就會報類似這樣的錯誤:
libgl2jni already defined by frameworks/base/opengl/tests/gl2_jni/jni. Stop. |
下面就是該錯誤的截圖:
接下來就是修改你的module的名字了,或者找到跟你重名的module把它干掉,但不建議你那么做,因為有可能會帶來未知的錯誤(你修改了別人的module的名字,而別人不一定知道,當他再編譯或者做其它時,就會出錯)。
LOCAL_MODULE is the name of what's supposed to be generated from your Android.mk. For exmample, for libkjs, the LOCAL_MODULE is "libkjs" (the build system adds the appropriate suffix -- .so .dylib .dll). |
注意:編譯系統會自動產生合適的前綴和后綴,例如:
LOCAL_MODULE := screenshot |
一個被命名為“screenshot”的共享庫模塊,將會生成“libscreenshot.so”文件。
補充1:變量命名的規范性
如果LOCAL_MODULE變量定義的值可能會被其它module調用時,就要考慮為其變量命名的規范性了。特別是在使用JNI時,既在LOCAL_JNI_SHARED_LIBRARIES變量中定義的值,最好要和LOCAL_MODULE變量定義的值保存一致(具體請參考LOCAL_JNI_SHARED_LIBRARIES變量的使用說明)。
這時的LOCAL_MODULE變量的命名最好以lib開頭,既“libxxx”,例如:
LOCAL_MODULE := libscreenshot |
LOCAL_MODULE_PATH
通知編譯系統將module放到其它地方而不是它通常的類型。如果你重寫這個變量,確保你還要再設置LOCAL_UNSTRIPPED_PATH變量的值。如果你忘了設置LOCAL_UNSTRIPPED_PATH變量的值的話,就會報錯。
Instructs the build system to put the module somewhere other than what's normal for its type. If you override this, make sure you also set LOCAL_UNSTRIPPED_PATH if it's an executable or a shared library so the unstripped binary has somewhere to go. An error will occur if you forget to. |
LOCAL_WHOLE_STATIC_LIBRARIES
LOCAL_WHOLE_STATIC_LIBRARIES 指定模塊所需要載入的完整靜態庫(這些靜態庫在鏈接是不允許鏈接器刪除其中無用的代碼)。通常這在你想往共享庫中增加一個靜態庫時是非常有用的,共享庫就會接受到靜態庫暴露出的content,例如:
|
------分隔符,方便下次編輯修改------
These are the static libraries that you want to include in your module without allowing the linker to remove dead code from them. This is mostly useful if you want to add a static library to a shared library and have the static library's content exposed from the shared library.
|
LOCAL_REQUIRED_MODULES
LOCAL_REQUIRED_MODULES 指定模塊運行所依賴的模塊(模塊安裝時將會同步安裝它所依賴的模塊)
Set LOCAL_REQUIRED_MODULES to any number of whitespace-separated module names, like "libblah" or "Email". If this module is installed, all of the modules that it requires will be installed as well. This can be used to, e.g., ensure that necessary shared libraries or providers are installed when a given app is installed. |
LOCAL_PRELINK_MODULE
LOCAL_PRELINK_MODULE變量用來規定是否需要預連接處理(默認需要,用來做動態庫優化)。LOCAL_PRELINK_MODULE只有在編譯.so的時候才會有的選項,主要是通過預鏈接的方式來加快程序啟動和執行的速度,如果在你的代碼(/jni/Android.mk)中有下面一條語句:
LOCAL_PRELINK_MODULE := true |
那么你要在build/core/prelink-linux-arm.map中定義你的庫所需要使用的空間,如果不定義或者空間不夠的話,在編譯的時候就會報錯。如下圖所示:
當在build/core/prelink-linux-arm.map中定義了我們這里使用的libhello-jni.so庫的空間之后,既在該文件中加入一條語句:
libhello-jni.so 0x99E00000 |
注意:在prelink-linux-arm.map文件的開頭部分有明確的規定,指定的內存取值范圍分配給不同的部分使用,而我們的App的庫也給指定了一個范圍:
0x90000000 - 0x9FFFFFFF Prelinked App Libraries |
重新編譯,就不會再報錯了,下面的截圖中很清晰地看到已經將libhello-jni.so庫預編譯成功了:
注意:
在給我們的應用庫分配地址空間時,最好以1M為邊界,地址空間大小按照由大到小的降序進行排序。
下面是對於Prelink的說明:
Prelink利用事先鏈接代替運行時鏈接的方法來加速共享庫的加載,它不僅可以加快起動速度,還可以減少部分內存開銷。程序運行時的動態鏈接尤其是重定位(relocation)的開銷對於大型系統來說是很大的。動態鏈接和加載的過程開銷很大,並且在大多數的系統上,函數庫並不會常常被更動,每次程序被執行時所進行的鏈接動作都是完全相同的,對於嵌入式系統來說尤其如此。因此,這一過程可以改在運行時之前就可以預先處理好,即花一些時間利用Prelink工具對動態共享庫和可執行文件進行處理,修改這些二進制文件並加入相應的重定位等信息,節約了本來在程序啟動時的比較耗時的查詢函數地址等工作,這樣可以減少程序啟動的時間,同時也減少了內存的耗用。
Prelink的這種做法當然也有代價的,每次更新動態共享庫時,相關的可執行文件都需要重新執行一遍Prelink才能保證有效,因為新的共享庫中的符號信息、地址等很可能與原來的已經不同了,這就是為什么android framework代碼一改動,這時候就會導致相關的應用程序重新被編譯。
LOCAL_JNI_SHARED_LIBRARIES
LOCAL_JNI_SHARED_LIBRARIES變量主要是用在JNI的編譯中,如果你要在你的Java代碼中引用JNI中的共享庫*.so,此變量就是共享庫的名字。
那么你要注意的一點是:在你的Project根目錄下的Android.mk中要定義此變量用來引用你要使用的JNI中的共享庫*.so。例如:
$(Project)/Android.mk LOCAL_JNI_SHARED_LIBRARIES := libsanangeles |
而在你的jni目錄下的Android.mk中則要定義LOCAL_MODULE變量的值,一定要讓這兩個變量的值相同。假如你沒有這么做,而是像這樣:
$(Project)/jni/Android.mk LOCAL_MODULE := sanangeles |
那么,在編譯的時候就會出現下圖的錯誤:
這說明在編譯libsanangeles.so找不到其規則,因為在上面的代碼中定義的是sanangeles。重新修改LOCAL_MODULE變量的值:
$(Project)/jni/Android.mk LOCAL_MODULE := libsanangeles |
即可正常編譯。
LOCAL_EXPORT_CFLAGS
定義這個變量用來記錄C/C++編譯器標志集合,並且會被添加到其他任何以LOCAL_STATIC_LIBRARIES和LOCAL_SHARED_LIBRARIES的模塊的LOCAL_CFLAGS定義中。例如:這樣定義"foo"模塊:
foo/Android.mk include $(CLEAR_VARS) LOCAL_MODULE :=foo LOCAL_SRC_FILES :=foo/foo.c LOCAL_EXPORT_CFLAGS :=-DFOO=1 include $(BUILD_STATIC_LIBRARY) |
另一個模塊,叫做"bar",並且依賴於上面的模塊:
bar/Android.mk 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"將被傳遞到編譯器。輸出的標志被添加到模塊的LOCAL_CFLAGS上,所以你可以很容易重寫它們。它們也有傳遞性:如果"zoo"依賴"bar",“bar”依賴"foo",那么"zoo"也將繼承"foo"輸出的所有標志。
最后,當編譯模塊輸出標志的時候,這些標志並不會被使用。在上面的例子中,當編譯foo/foo.c時,-DFOO=1將不會被傳遞給編譯器。
LOCAL_EXPORT_CPPFLAGS
類似LOCAL_EXPORT_CFLAGS,但適用於C++標志。
具體請參考LOCAL_EXPORT_CFLAGS條目。
LOCAL_EXPORT_C_INCLUDES
類似LOCAL_EXPORT_CFLAGS,但是只有C能包含路徑,如果"bar.c"想包含一些由"foo"模塊提供的頭文件的時候這會很有用。
具體請參考LOCAL_EXPORT_CFLAGS條目。
LOCAL_EXPORT_LDLIBS
類似於LOCAL_EXPORT_CFLAGS,但是只用於鏈接標志。注意,引入的鏈接標志將會被追加到模塊的LOCAL_LDLIBS,這是由UNIX連接器的工作方式決定的。
當模塊foo是一個靜態庫的時候並且代碼依賴於系統庫時會很有用的。LOCAL_EXPORT_LDLIBS可以用於輸出依賴,例如:
#Frist build the static library libfoo.a include $(CLEAR_VARS) LOCAL_MODULE := foo LOCAL_SRC_FILES := foo/foo.c LOCAL_EXPORT_LDLIBS := -llog include $(BUILD_STATIC_LIBRARY) #Then build the shared library libbar.so include $(CLEAR_VARS) LOCAL_MODULE := bar LOCAL_SRC_FILES := bar.c LOCAL_STATIC_LIBRARIES := foo include $(BUILD_SHARED_LIBRARY) |
這里,在連接器命令最后,libbar.so將以”-llog”參數進行編譯來表明它依賴於系統日志庫,因為它依賴於foo。
LOCAL_ALLOW_UNDEFINED_SYMBOLS
默認情況下,當試圖編譯一個共享庫的時候遇到任何未定義的引用都可能導致"未定義符號"(undefined symbol)的錯誤。這在你的源代碼中捕獲bug會很有用。
然而,但是由於某些原因,你需要禁用此檢查的話,設置變量為"true"即可。需要注意的是,相應的共享庫在運行時可能加載失敗。
LOCAL_ARM_MODE
LOCAL_ARM_MODE變量主要是應用與嵌入式產品的編譯系統中,可以指定為arm模式。例如:
LOCAL_ARM_MODE := arm |
注意:你需要執行編譯系統為在ARM模式下通過文件的名字增加后綴的方式編譯指定的源文件。例如:
LOCAL_SRC_FILES :=foo.c bar.c.arm |
這會告訴編譯系統一直以ARM模式編譯"bar.c",並且通過LOCAL_ARM_MODE的值編譯foo.c。
2.2.2.BUILD_XXX變量
2.2.2.1.BUILD_SHARED_LIBRARY
BUILD_SHARED_LIBRARY:指明要編譯生成動態共享庫。指向一個生成腳本,這個腳本通過LOCAL_XXX變量收集關於組件的信息,並決定如何根據你列出來的源文件生成目標共享庫。
注意:在include這個腳本文件之前你必須至少已經定義了LOCAL_MODULE和LOCAL_SRC_FILES。例如:
include $(BUILD_SHARED_LIBRARY) |
注意:這會生成一個名為lib$(LOCAL_MODULE).so的動態庫。
2.2.2.2.BUILD_STATIC_LIBRARY
BUILD_STATIC_LIBRARY與BUILD_SHARED_LIBRARY類似,但用來生成目標靜態庫。靜態庫不會被拷貝至你的project/packages文件夾下,但可用來生成共享庫。
例如:
include $(BUILD_STATIC_LIBRARY) |
注意:這會生成一個靜態庫,名叫lib$(LOCAL_MODULE).a的靜態庫。
2.2.2.3.BUILD_PACKAGE
BUILD_PACKAGE變量用於在最好編譯時生成*.apk,例如:
include $(BUILD_STATIC_LIBRARY) |
注意:這會生成一個apk安裝包,名字就叫$(LOCAL_MODULE).apk的安裝包。
2.2.3.其它變量
2.2.3.1.CLEAR_VARS
CLEAR_VARS變量是生成系統提供的,它指向一個特殊的GNU Makefile,它將會為你自動清除許多名為LOCAL_XXX的變量(比如:LOCAL_MODULE、LOCAL_SRC_FILES、LOCAL_STATIC_LIBRARIES等),但LOCAL_PATH是例外,它不會被清除。
注意:這些變量的清除是必須的,因為所有的控制文件是在單一的Makefile,執行環境中解析的,在這里所有的變量都是全局的。
2.2.3.2.TARGET_PLATFORM
TARGET_PLATFORM:當解析該Android.mk文件時用它來指定Andoid目標平台的名稱。例如:android-3與Android 1.5相對應。
2.2.4.NDK提供的宏函數
下面是GNU Make的宏函數,必須通過這樣的形式調用:
$(call <function>) |
2.2.4.1.my-dir
my-dir:返回放置當前Android.mk的文件夾相對於NDK生成系統根目錄的路徑。可用來在Android.mk的開始處定義LOCAL_PATH的值:
LOCAL_PATH := $(call my-dir) |
2.2.4.2.all-subdir-makefiles
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僅在source/*/Android.mk里尋找文件。
2.2.4.3.this-makefile
this-makefile:返回當前Makefile所在目錄的路徑。
2.2.4.4.parent-makefile
parent-makefile:返回父Makefile所在目錄makefile的路徑。
2.2.4.5.import-module
一個允許你通過名字找到並包含另一個模塊的的Android.mk的功能,例如:
$(call import-module,<name>) |
這將會找到通過NDK_MODULE_PATH環境變量引用的模塊<name>的目錄列表,並且將其自動包含到Android.mk中。
3.Application.mk
3.1.作用
Application.mk目的是描述在你的應用程序中所需要的模塊(即靜態庫或動態庫)。
Application.mk文件通常被放置在$PROJECT/jni/Application.mk下,$PROJECT指的是您的項目。另一種方法是將其放在頂層的子目錄下,既$NDK/apps目錄下,例如:
$NDK/apps/<myapp>/Application.mk
<myapp>是一個簡稱,用於描述你的NDK編譯系統的應用程序(這個名字不會生成共享庫或者最終的包),這個方法是Android NDK r4以前的,現在仍然兼容。但是我們強烈建議你使用第一種方法,因為它更簡單並且不用修改NDK安裝樹的目錄。
3.2.詳細說明
下面是Application.mk中定義的幾個變量:
3.2.1.APP_MODULES
APP_MODULES 變量是強制性的,並且會列出所有你所需要的模塊。它不允許用一個空格來分隔其模塊列表,這個模塊名字被定義在Android.mk文件中的LOCAL_MODULE中。
3.2.2.APP_PROJECT_PATH
APP_PROJECT_PATH變量也是強制性的,並且會給出應用程序工程的根目錄一個絕對路徑。這是用來復制或者安裝一個沒有任何版本限制的JNI庫,從而給 APK 生成工具一個詳細的路徑。例如:
\HelloNDK\Application.mk APP_PROJECT_PATH := $(call my-dir)/project APP_MODULES := HelloNdk |
這里定義了工程路徑為$(call my-dir)/project,而要編譯的模塊則是HelloNdk,這樣編譯系統才會找到我們要編譯的庫和源文件。
3.2.3.APP_CFLAGS
APP_CFLAGS則是當要編譯模塊中有任何C文件或者C++文件的時候,C編譯器的信號就會被發出。這里可以在你的應用中需要這些模塊時,進行編譯的調整,這樣就不許要直接更改Android.mk為文件本身了。
3.2.4.APP_OPTIM
這個變量是可選的,可以定義成兩個值release或者debug,用於修改編譯程序模塊時的優化層級。release模式是默認的,會產生高優化的文件,debug模式會生成不優化的文件,使得調試更容易進行。
注意:調試release和debug文件都是可能的,但是release版在調試節提高的信息很少,一些變量被優化輸出,無法檢查,代碼被重排序,使得跟蹤代碼很困難,堆棧追蹤也不可靠,等等。
3.2.5.APP_CPPFLAGS
當編譯的只有C++源文件的時候,可以通過這個C++編譯器來設置。
注意:在Android NDK-1.5_r1中,這個標志可以應用於C和C++源文件中。並且得到了糾正,以建立完整的與系統相匹配的Android編譯系統。你先可也可以使用APP_CFLAGS來應用於C或者C++源文件中。建議使用APP_CFLAGS。
4.補充
4.1.兩種不同級別的應用apk
目前我所理解是在Android開發中我們會遇到兩種不同級別的應用apk:系統級應用apk和普通級應用apk。
下面分別描述兩種apk:
4.1.1.編譯系統級應用apk
將應用程序的代碼放到源代碼目錄路徑下,然后進行編譯。將編譯生成的*.apk通過adb或者其它方式放到/system/app目錄下即可。
4.1.2.編譯普通級應用apk
應用程序的代碼並沒有放到平台的源代碼目錄下,然后通過編譯生成的*.apk通過adb install的方式放到/data/app目錄下,就是普通級的apk。
5.參考資料
1. |
Android ndk r7b for linux/ Android ndk r6b for windows |
2. |
Android NDK 概覽($(NDK)/doc/OVERVIEW.html) http://hualang.iteye.com/blog/1135105 |
3. |
NDK使用方法($(NDK)/doc/HOWTO.html) http://hualang.iteye.com/blog/1136209 |
4. |
Android.mk 文件($(NDK)/doc/ANDROID-MK.html) http://hualang.iteye.com/blog/1140414 |
5. |
Application.mk 文件($(NDK)/doc/APPLICATION-MK.html) http://hualang.iteye.com/blog/1149359 |
6. |
Android Building System 總結 http://blog.csdn.net/yili_xie/article/details/5004205 |
7. |
build-system.html Android 源碼下:platform/build/core/build-system.html |