Android mk
NDK
構(gòu)建系統(tǒng)預(yù)留了以下的變量,在自定義變量時(shí)注意不要跟這些系統(tǒng)變量沖突
- 以
LOCAL_
開(kāi)頭的 - 以
PRIVATE_, NDK_, APP
開(kāi)頭的 - 小寫字母的如
my-dir
LOCAL_PATH
每個(gè)Android.mk
文件必須由LOCAL_PATH
開(kāi)始,用于在development tree
中查找源文件
include $(CLEAR_VARS)
CLEAR_VARS
指向一個(gè)指定的GNU Makefile
,并清理許多LOCAL_XXX
變量,比如LOCAL_MODULE, LOCAL_SRC_FILES
等欢伏,它并不清理LOCAL_PATH
。因?yàn)樗械木幾g控制文件由同一個(gè)GNU Makefile
解析和執(zhí)行,其變量是全局的霹购,所以必須清理后才能避免相互影響
LOCAL_MODULE
每一個(gè)模塊的名稱必須是唯一的且不能包含任何空格。系統(tǒng)在構(gòu)建shared-library
時(shí)朋腋,會(huì)自動(dòng)加上前綴lib
和后綴.so
如果模塊名稱本身已經(jīng)是以
lib
開(kāi)頭齐疙,則系統(tǒng)不會(huì)再加入前綴,只是會(huì)加入后綴
LOCAL_SRC_FILES
指明當(dāng)前模塊的源文件(C/C++文件)
缺省的C++源碼的擴(kuò)展名為.cpp
. 也可以修改旭咽,通過(guò)LOCAL_CPP_EXTENSION
修改
BUILD_SAHRED_LIBRARY
該變量指向一個(gè)構(gòu)建腳本并收集所有通過(guò)LOCAL_XXX
變量指定的關(guān)于當(dāng)前模塊的信息贞奋,并根據(jù)你所列出的源文件構(gòu)建一個(gè)動(dòng)態(tài)庫(kù)(.so)
使用該變量前,你應(yīng)該至少定義了LOCAL_MODULE
和LOCAL_SRC_FILES
用法是:
include $(BUILD_SAHRED_LIBRARY)
BUILD_STATIC_LIBRARY
用來(lái)構(gòu)建一個(gè)靜態(tài)庫(kù)(.a)穷绵,用法是:
include $(BUILD_STATIC_LIBRARY)
PREBUILT_SHARED_LIBRARY
用來(lái)指定一個(gè)預(yù)先已經(jīng)編譯好的動(dòng)態(tài)庫(kù)轿塔,與BUILD_SAHRED_LIBRARY
和BUILD_STATIC_LIBRARY
不同,該模塊對(duì)應(yīng)的LOCAL_SRC_FILES
不能是源文件,而只能是一個(gè)已經(jīng)編譯好的的動(dòng)態(tài)庫(kù)的路徑勾缭,如foo/libfoo.so
揍障,用法是:
include $(PREBUILT_SHARED_LIBRARY)
PREBUILT_STATIC_LIBRARY
用來(lái)指定一個(gè)預(yù)先已經(jīng)編譯好的靜態(tài)庫(kù)
TARGET_ARCH
指定目標(biāo)CPU
架構(gòu),對(duì)于大多數(shù)兼容ARM
指令的構(gòu)建俩由,通常使用arm
,與CPU
架構(gòu)版本無(wú)關(guān)
TARGET_PLATFORM
指定目標(biāo)平臺(tái)的Android API
版本號(hào)毒嫡。例如,5.1系統(tǒng)對(duì)應(yīng)的值是:
TARGET_PLATFORM := android-22
TARGET_ARCH_ABI
指定CPU
的名稱和架構(gòu)采驻,你可以指定一個(gè)或多個(gè)值审胚,可取的值有:
- ARMv5TE -----> armeabi
- ARMv7 -----> armeabi-v7a
- ARMv8 AArch64 -----> arm64-v8a
- i686 -----> x86
- x86-64 -----> x86-64
- mips32(r1) -----> mips
- mips64(r6) -----> mips64
- All -----> all
TARGET_ABI
連接了Android API
和ABI
兩個(gè)值,例如:
TARGET_ABI := android-22-arm64-v8a
LOCAL_MODULE_FILENAME
該選項(xiàng)可以重寫模塊的默認(rèn)名稱礼旅,例如:
LOCAL_MODULE := foo
LOCAL_MODULE_FILENAME := libnewfoo
系統(tǒng)最終會(huì)生成libnewfoo.so
LOCAL_SRC_FILES
包含了構(gòu)建該模塊的源文件列表膳叨。可以使用相對(duì)路徑也可以使用絕對(duì)路徑痘系,不過(guò)最好不要使用絕對(duì)路徑而使用相對(duì)路徑菲嘴,這樣可以方便移植
LOCAL_CPP_EXTENSION
指出C++
源文件的擴(kuò)展名(可選)
LOCAL_CPP_FEATURES
該變量指明當(dāng)前模塊所依賴的C++
特性(可選)
推薦使用該變量代替在LOCAL_CPPFLAGS
選項(xiàng)中傳入-frtti
和-fexception
使用該變量允許系統(tǒng)對(duì)于每個(gè)模塊各自使用合適的flag
,而使用LOCAL_CPPFLAGS
則會(huì)導(dǎo)致編譯器給所有模塊都使用傳入的flags
LOCAL_CPP_FEATURES := rtti --> (use Runtime Type Information)
LOCAL_CPP_FEATURES := exceptions --> (use C++ exceptions)
LOCAL_C_INCLUDES
指明編譯時(shí)的include
路徑列表汰翠,相對(duì)于NDK ROOT
目錄×淦骸(可選)
LOCAL_CFLAGS
指明在編譯C/C++
時(shí)要添加的flags
(可選)
注意:不要在這改變優(yōu)化選項(xiàng)和調(diào)試等級(jí),這些選項(xiàng)應(yīng)該在
Application.mk
中自動(dòng)指定
也可以指定include
目錄:
LOCAL_CFLAGS += -I<path>
這個(gè)方法比LOCAL_C_INCLUDES
要好一些,因?yàn)榭梢员?code>ndk-gdb所使用
LOCAL_CXXFLAGS
LOCAL_CPPFLAGS
的別名
LOCAL_CPPFLAGS
指明編譯C++
代碼時(shí)的flags
(可選)复唤,這些選項(xiàng)在編譯器的命令行中會(huì)跟在LOCAL_CFLAGS
后面
LOCAL_STATIC_LIBRARIES
指明編譯模塊時(shí)需要的靜態(tài)庫(kù)列表
如果當(dāng)前模塊是動(dòng)態(tài)庫(kù)或可執(zhí)行文件健田,該變量會(huì)告訴編譯器將該變量列出的靜態(tài)庫(kù)連接到最終的二進(jìn)制文件上
如果當(dāng)前模塊一個(gè)靜態(tài)庫(kù),該變量只是簡(jiǎn)單的指明其他依賴當(dāng)前模塊的庫(kù)同時(shí)也依賴該變量聲明的這些庫(kù)
LOCAL_SHARED_LIBRARIES
列出當(dāng)前模塊在runtime
時(shí)依賴的動(dòng)態(tài)庫(kù)
LOCAL_WHOLE_STATIC_LIBRARIES
靜態(tài)庫(kù)全鏈接佛纫,不同于LOCAL_STATIC_LIBRARIES妓局,類似于使用--whole-archive
LOCAL_LDLIBS
該變量包含了在編譯動(dòng)態(tài)庫(kù)或可執(zhí)行文件時(shí)的附加連接選項(xiàng)列表。它允許你使用-l
前綴來(lái)傳遞指定的系統(tǒng)庫(kù)呈宇,例如:
LOCAL_LDLIBS := -lz
上面的代碼告訴編譯器在編譯模塊時(shí)還要連接/system/lib/libz.so
LOCAL_ALLOW_UNDEFIEND_SYMBOLS
默認(rèn)情況下好爬,系統(tǒng)在編譯動(dòng)態(tài)庫(kù)時(shí)遇到undefined reference
錯(cuò)誤時(shí),會(huì)拋出undefined symbol error
如果將該變量設(shè)為true
甥啄,則會(huì)關(guān)閉undefined reference
檢查
如果你在編譯靜態(tài)庫(kù)時(shí)指定該變量存炮,系統(tǒng)會(huì)忽略該變量
LOCAL_ARM_MODE
默認(rèn)情況下,系統(tǒng)產(chǎn)生的二進(jìn)制文件是thumb
模式蜈漓,每個(gè)指令是16位穆桂,并且連接這/thumb
下STL libraries
。通過(guò)將該變量設(shè)為arm
,可以讓產(chǎn)生的指令變?yōu)?2位融虽,例如:
LOCAL_ARM_MODE := arm
也可以將某一個(gè)源文件以.arm
結(jié)尾以此來(lái)指定該文件要被編譯成arm
模式充尉,例如:
LOCAL_SRC_FILES := foo.c bar.c.arm
注意:也可以在
Application.mk
中指定APP_OPTIM := debug
來(lái)達(dá)到同樣的目的
LOCAL_ARM_NEON
該變量只有在將ABI
指定為armeabi-v7a
時(shí)才有效。設(shè)置為true時(shí)衣形,會(huì)講浮點(diǎn)編譯成neon指令驼侠,這會(huì)極大地加快浮點(diǎn)運(yùn)算(前提是硬件支持)
同時(shí)姿鸿,也可以將某一個(gè)源文件以.neon
結(jié)尾來(lái)指定該源文件支持neon
,例如:
LOCAL_SRC_FILES := foo.c.neon bar.c zoo.c.arm.neon
上面的代碼指明了zoo.c
設(shè)為arm
模式同時(shí)支持neon
LOCAL_DISABLE_NO_EXECUTE
Android NDK r4
添加了NX bit
安全特性,該選項(xiàng)默認(rèn)是開(kāi)啟的倒源,如果要關(guān)閉苛预,可以將LOCAL_DISABLE_NO_EXECUTE
這個(gè)變量設(shè)為true
該變量并不改變ABI
,同時(shí)只在ARMv6+ CPU
的設(shè)備開(kāi)啟
LOCAL_DISABLE_RELRO
默認(rèn)情況下笋熬, NDK
在編譯代碼時(shí)會(huì)加入read-only relocations
和GOT protection
該變量指明runtime linker
在relocation
之后確保內(nèi)存為read-only
热某,同時(shí)確保security exploit
更為困難。
這些保護(hù)只在
Android API 16
及以上才起作用
將這個(gè)變量LOCAL_DISABLE_RELRO
設(shè)為true
,可以將上述機(jī)制關(guān)閉
LOCAL_DISABLE_FORMAT_STRING_CHECKS
默認(rèn)情況下胳螟, 系統(tǒng)在編譯時(shí)會(huì)進(jìn)行string
格式的檢查昔馋。這個(gè)檢查默認(rèn)是開(kāi)啟的,不過(guò)可以將LOCAL_DISABLE_FORMAT_STRING_CHECKS
這個(gè)變量設(shè)為true
來(lái)取消這個(gè)檢查
LOCAL_EXPORT_CFLAGS
在該變量中聲明的所有flags
都會(huì)添加到在那些以LOCAL_STATIC_LIBRARIES
或者LOCAL_SHARED_LIBRARIES
聲明依賴當(dāng)前靜態(tài)庫(kù)或動(dòng)態(tài)庫(kù)的模塊的LOCAL_CFLAGS
中糖耸,例如:
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_CFLGAS := -DBAR=2
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SAHRED_LIBRARY)
這里秘遏,系統(tǒng)會(huì)將-DFOO=1
和-DBAR=2
都傳入給bar.c
另外,所有依賴關(guān)系都是傳遞的嘉竟,如果zoo
依賴bar
,而bar
又依賴foo
邦危,則zoo
同樣繼承了foo
模塊的所有exported flags
系統(tǒng)并不會(huì)傳遞exported flags
給當(dāng)前模塊,舉例來(lái)說(shuō)舍扰,-DFOO=1
并不會(huì)傳遞給foo
LOCAL_EXPORT_CPPFLAGS
作用同LOCAL_EXPORT_CFLAGS
倦蚪,只是針對(duì)C++
LOCAL_EXPORT_C_INCLUDES
導(dǎo)出include paths
,例如边苹,該變量會(huì)告訴bar.c
應(yīng)該包含foo
模塊的頭文件
LOCAL_EXPORT_LDFLAGS
該變量作用同LOCAL_EXPORT_CFLAGS
,只不過(guò)是針對(duì)linker flags
LOCAL_EXPORT_LDLIBS
該變量告訴系統(tǒng)傳遞指定的的系統(tǒng)庫(kù)給編譯器陵且,系統(tǒng)會(huì)添加導(dǎo)入的的連接屬性給LOCAL_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)
系統(tǒng)會(huì)在編譯libbar.so
時(shí)將-llog
放在連接命令行末端
LOCAL_SHORT_COMMANDS
當(dāng)你的模塊中有大量源文件或依賴庫(kù)時(shí)个束,可以將此變量設(shè)為true
慕购,之后系統(tǒng)會(huì)使用@
語(yǔ)法來(lái)直接包含對(duì)象文件或二進(jìn)制文件,這個(gè)特性在Windows
會(huì)有用播急,也可以在Application.mk
中定義APP_SHORT_COMMANDS
來(lái)為每個(gè)模塊開(kāi)啟這一屬性
LOCAL_THIN_ARCHIVE
構(gòu)建靜態(tài)庫(kù)時(shí),可以將此變量設(shè)為true
售睹,系統(tǒng)會(huì)產(chǎn)生一個(gè)'瘦身了的archive
文件'桩警,在該庫(kù)文件中并不包含對(duì)象文件,而只是包含每個(gè)對(duì)象文件對(duì)應(yīng)的路徑
my-dir
這個(gè)宏返回最后一個(gè)makefile
的路徑昌妹,一般都是當(dāng)前Android.mk
的路徑捶枢,這個(gè)宏一般用來(lái)在Android.mk
開(kāi)頭定義LOCAL_PATH
變量,例如:
LOCAL_PATH := $(call my-dir)
all-subdir-makefiles
返回當(dāng)前my-dir
路徑下所有子目錄的所有Android.mk
this-makefile
返回當(dāng)前makefile
的路徑
parent-makefile
返回包含當(dāng)前makefile
的父makefile
的路徑
grand-parent-makefile
返回包含當(dāng)前makefile
的祖父makefile
的路徑
import-module
可以用來(lái)包含一個(gè)指定模塊的Android.mk
飞崖,用法是:
$(call import-module,<name>)
使用Prebuilt Libraries
你必須聲明每個(gè)prebuilt library
作為一個(gè)獨(dú)立的模塊烂叔,步驟為以下幾步:
- 定義一個(gè)模塊名稱,該名稱不必同
prebuilt library
本身的名字一致 - 在
Android.mk
中固歪,將LOCAL_SRC_FILES
置為prebuilt library
的路徑 include PREBUILT_SHARED_LIBRARY or PREBUILT_STATIC_LIBRARY
例子:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := libfoo.so
include $(PREBUILD_SHARED_LIBRARY)