Android Mk Application Mk make makefile筆記

說明

這只是筆記。。。。。。。。

從0開始搭建測(cè)試環(huán)境

下載android ndk ,然后配置ndk環(huán)境變量,使ndk-build命令能在任意目錄執(zhí)行.

目錄的規(guī)定

在任意目錄創(chuàng)建一個(gè)Android.mk和Application.mk
然后切換命令行在此目錄輸入ndk-build
出現(xiàn)錯(cuò)誤

Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
D:\env\android_sdk\ndk-bundle\build\\..\build\core\build-local.mk:151: *** Android NDK: Aborting

百思不得其解,網(wǎng)上的文章沒有幾篇靠譜的,嘗試把這個(gè)目錄改名為jni,切換到此目錄,竟然錯(cuò)誤消失了,出現(xiàn)另外一個(gè)目錄

解決警告

雖然這個(gè)錯(cuò)誤沒有出現(xiàn)了,但是又出現(xiàn)了2個(gè)警告,1是提示定義最小版本,二是定說沒有模塊.

Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-14.
D:/env/android_sdk/ndk-bundle/build//../build/core/build-all.mk:89: Android NDK: WARNING: There are no modules to build in this project!
  • 定義版本號(hào)
    在Application.mk定義如下內(nèi)容:
    APP_PLATFORM:=android-14

    E:\cross-c\Androidmk\jni>ndk-build -B
    Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-14.
    D:/env/android_sdk/ndk-bundle/build//../build/core/build-all.mk:89: Android NDK: WARNING: There are no modules to build in this project!
    make: Nothing to be done for `all'.

這種情況,關(guān)閉終端重啟.

ndk-build命令幫助

ndk-build V=1 顯示詳細(xì)信息
ndk-build -B 強(qiáng)制編譯
ndk-build NDK_APPLICATION_MK=My.mk自定義Application.mk
ndk-build NDK_DEBUG為1可以實(shí)現(xiàn)優(yōu)化不優(yōu)化的問題,有符號(hào)就能定位堆棧。
ndk-build NDK_HOST_32BIT=1 不根據(jù)操作系統(tǒng)的64位使用這個(gè)構(gòu)建
<ndk>/toolchain/<name>/prebuilt/

下面的語法實(shí)際上是make命令的語法

E:\cross-c\Androidmk\jni>ndk-build --help
用例: make [選項(xiàng)] [目標(biāo)] ...
Options:
  -b, -m                      Ignored for compatibility.忽略兼容性
  -B, --always-make           Unconditionally make all targets.無條件完成所有target編譯,感覺沒啥變化
  -C DIRECTORY, --directory=DIRECTORY
                              Change to DIRECTORY before doing anything. 做任意事情之前改變目錄
  -d                          Print lots of debugging information.
  --debug[=FLAGS]          debug模式,打印調(diào)試信息    Print various types of debugging information.
  -e, --environment-overrides 覆蓋makefiles的環(huán)境變量
                              Environment variables override makefiles.
  -f FILE, --file=FILE, --makefile=FILE 自定義makefile文件
                              Read FILE as a makefile.
  -h, --help               打印幫助信息and退出
  -i, --ignore-errors         Ignore errors from commands.忽略命令行錯(cuò)誤
  -I DIRECTORY, --include-dir=DIRECTORY
                              Search DIRECTORY for included makefiles. 定義包含的目錄
  -j [N], --jobs[=N]          Allow N jobs at once; infinite jobs with no arg. 次允許N個(gè)作業(yè);沒有參數(shù)則無限工作
  -k, --keep-going            Keep going when some targets can't be made.當(dāng)一些目標(biāo)無法達(dá)成時(shí),繼續(xù)前進(jìn)。
  -l [N], --load-average[=N], --max-load[=N] 指定平均加載任務(wù)
                              Don't start multiple jobs unless load is below N.除非負(fù)載小于N,否則不要啟動(dòng)多個(gè)作業(yè)。
  -L, --check-symlink-times   Use the latest mtime between symlinks and target. 用符號(hào)鏈接和目標(biāo)之間的最新時(shí)間。
  -n, --just-print, --dry-run, --recon
                              Don't actually run any commands; just print them.不運(yùn)行實(shí)際的命令只是打印。
  -o FILE, --old-file=FILE, --assume-old=FILE
                              Consider FILE to be very old and don't remake it. 認(rèn)為文件很舊,不要重做。
  -p, --print-data-base       Print make's internal database.打印內(nèi)部數(shù)據(jù)庫
  -q, --question              Run no commands; exit status says if up to date. 退出狀態(tài)表示是否是最新
  -r, --no-builtin-rules      Disable the built-in implicit rules.禁用內(nèi)置的隱式規(guī)則。
  -R, --no-builtin-variables   禁用內(nèi)置變量 Disable the built-in variable settings.
  -s, --silent, --quiet      靜默模式,不輸出信息 Don't echo commands.
  -S, --no-keep-going, --stop
                              Turns off -k.
  -t, --touch                 Touch targets instead of remaking them.
  -v, --version            打印make版本號(hào)   Print the version number of make and exit.
  -w, --print-directory  打印當(dāng)前目錄     Print the current directory.
  --no-print-directory     不打印當(dāng)前目錄   Turn off -w, even if it was turned on implicitly. 隱式打開
  -W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE
                              Consider FILE to be infinitely new. 認(rèn)為文件是無限新的
  --warn-undefined-variables  Warn when an undefined variable is referenced. 引用未定義變量時(shí)發(fā)出警告。

    This program built for i686-w64-mingw32
    Report bugs to <bug-make@gnu.org>
    E:\cross-c\Androidmk\jni>




mk語法與AndroidMk的變量與宏

android 一般使用ndk-build測(cè)試的,而不是單純的玩make,

定義變量
變量名 := 變量值

判斷變量是否存在

變量拼接
MY_VAR+=append........
打印字符串
這里在控制臺(tái)打印HelloWorld
$(warning HelloWorld)
打印變量

MY_VAR:=I am var
$(warning $(MY_VAR))

打印拼接的變量

    $(warning 33333$(MY_VAR))
  • 控制臺(tái)輸出的效果
    E:\cross-c\Androidmk\jni>ndk-build
    E:/cross-c/Androidmk/jni/Application.mk:3: WellcomeUseAndroidMk
    [armeabi-v7a] Compile++ thumb: png <= hello.cpp
    [armeabi-v7a] SharedLibrary  : libpng.so
    [armeabi-v7a] Install        : libpng.so => libs/armeabi-v7a/libpng.so

打印當(dāng)前目錄
$(warning currentPath:$(my-dir))
my-dir變量是android的ndk-build環(huán)境才有的,純make是沒有的
打印CLEAR_VARS

$(CLEAR_VARS)需要在Android.mk里面編寫才能測(cè)試

$(warning currentPath:$(CLEAR_VARS))
$(warning ------------------)

輸出結(jié)果
D:/env/android_sdk/ndk-bundle/build//../build/core/clear-vars.mk

語法錯(cuò)誤的效果

:\cross-c\Androidmk\jni>ndk-build
:/cross-c/Androidmk/jni/Application.mk:3: *** missing separator.  Stop.

注釋

#開頭就是注釋了。
邏輯分支

DEBUG:=1
NAME:=qssq
SEX:=man
EMPTY:=#定義空
SPACE:=$(EMPTY) $(EMPTY) #定義空格
ifeq ($(DEBUG),1)#關(guān)鍵字后面需要加空格,否則語法錯(cuò)誤
$(warning 調(diào)試模式)
else
$(warning 非調(diào)試模式)
endif


#去掉收尾空格進(jìn)行判斷是否為空
ifeq ($(strip $(SPACE)),)
$(warning SPACE變量去掉首尾空格為空)
endif

# 如果不是空而是空格也是不匹配的。
ifneq ($(SPACE),)
$(warning 不去掉首尾,不是空)
endif

#----------------------------------------------
ifeq ($(DEBUG),qssq)
$(warning 輸出了作者)
else
$(warning 不知道你輸入了什么名字,名字是$(NAME))
endif

ifeq ($(SEX),man)
$(warning 是個(gè)男人)
endif

#是否SEX等于woman字符串
ifneq ($(SEX),woman)
$(warning 不是女人)
endif

#定義變量 (看上去是一個(gè)函數(shù)
define tempvar
$(warning  執(zhí)行了temp定義)
endef

#判斷是否定義了tempvar
ifdef tempvar
$(warning 即將執(zhí)行tempvar)
$(call tempvar)
endif




#判斷是否定義了tempvar3
ifdef tempvar3
$(warning 即將執(zhí)行tempvar3)
$(call tempvar3)
endif


ifndef tempvar2
$(warning 沒有定義tempvar2)
endif

定義多行
如果下一行要繼續(xù)上一行,則上一行應(yīng)該以\結(jié)尾

Application.mk內(nèi)嵌的變量

設(shè)置編譯的架構(gòu)

定義需要編譯的架構(gòu) 多個(gè)用空格隔開
APP_ABI :=arm64-v8a

APP_ABI:=armeabi-v7a x86 x86_64 arm64-v8a x86_64

APP_ABI:=all 和不填寫的效果一樣。

定義目標(biāo)平臺(tái)
APP_PLATFORM
接受的變量如 android-14
測(cè)試錯(cuò)誤的結(jié)果
賦值為android-1433 提示這個(gè)1433大于最高的版本28,請(qǐng)選擇一個(gè)支持的api級(jí)別,或者設(shè)置為latest,latest的意思就是最新的。

:/cross-c/Androidmk/jni/Application.mk:6: 33333I am var
ndroid NDK: android-1433 is above the maximum supported version android-28. Choose a supported API level or set APP_PLATFORM to "latest".
:/env/android_sdk/ndk-bundle/build//../build/core/setup-app-platform.mk:127: *** Android NDK: Aborting.    .  Stop.

設(shè)置最高版本APP_PLATFORM:=latest

Android NDK: Using latest available APP_PLATFORM: android-28.

設(shè)置最低版本
最低版本就是不指定APP_PLATFORM變量。

Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-14.

設(shè)置最小支持庫
筆者在編譯后找不到某些頭文件,發(fā)現(xiàn)我們的c++大神把我的配置
gnustl_static改為了stlport_static
如今記憶猶新哈。
APP_STL

libstdc++(默認(rèn))   默認(rèn)最小系統(tǒng) C++ 運(yùn)行時(shí)庫。    不適用
gabi++_static   GAbi++ 運(yùn)行時(shí)(靜態(tài))。 C++ 異常和 RTTI
gabi++_shared   GAbi++ 運(yùn)行時(shí)(共享)。 C++ 異常和 RTTI
stlport_static  STLport 運(yùn)行時(shí)(靜態(tài))。    C++ 異常和 RTTI;標(biāo)準(zhǔn)庫
stlport_shared  STLport 運(yùn)行時(shí)(共享)。    C++ 異常和 RTTI;標(biāo)準(zhǔn)庫
gnustl_static   GNU STL(靜態(tài))。    C++ 異常和 RTTI;標(biāo)準(zhǔn)庫
gnustl_shared   GNU STL(共享)。    C++ 異常和 RTTI;標(biāo)準(zhǔn)庫
c++_static  LLVM libc++ 運(yùn)行時(shí)(靜態(tài))。    C++ 異常和 RTTI;標(biāo)準(zhǔn)庫
c++_shared  LLVM libc++ 運(yùn)行時(shí)(共享)。    C++ 異常和 RTTI;標(biāo)準(zhǔn)庫

AndroidMk的執(zhí)行順序

先執(zhí)行Application.mk
然后執(zhí)行Android.mk

Application.mk官方說明

這里的配置相對(duì)于Android.mk比較少

本文檔介紹 Application.mk 構(gòu)建文件,此文件用于描述應(yīng)用需要的原生模塊。 模塊可以是靜態(tài)庫、共享庫或可執(zhí)行文件。

建議在閱讀本頁之前先閱讀概念和 Android.mk 頁面。 這樣有助于您最深入地了解本頁的內(nèi)容。

概覽
Application.mk 文件實(shí)際上是定義要編譯的多個(gè)變量的微小 GNU Makefile 片段。 它通常位于 PROJECT/jni/ 下,其中PROJECT 指向應(yīng)用的項(xiàng)目目錄。 另一種方式是將其放在頂級(jí) NDK/apps/ 目錄的子目錄下。 例如:NDK/apps/<myapp>/Application.mk
這里的 <myapp> 是用于向 NDK 構(gòu)建系統(tǒng)描述應(yīng)用的短名稱。它不會(huì)實(shí)際進(jìn)入生成的共享庫或最終軟件包。

變量
APP_PROJECT_PATH
此變量用于存儲(chǔ)應(yīng)用項(xiàng)目根目錄的絕對(duì)路徑。構(gòu)建系統(tǒng)使用此信息將生成的 JNI 共享庫的簡(jiǎn)縮版放入 APK 生成工具已知的特定位置。

如果將 Application.mk 文件放在 NDK/apps/<myapp>/ 下,則必須定義此變量。 如果將其放在PROJECT/jni/ 下,則此變量可選。

APP_OPTIM
將此可選變量定義為 release 或 debug。在構(gòu)建應(yīng)用的模塊時(shí)可使用它來更改優(yōu)化級(jí)別。

發(fā)行模式是默認(rèn)模式,可生成高度優(yōu)化的二進(jìn)制文件。調(diào)試模式會(huì)生成未優(yōu)化的二進(jìn)制文件,更容易調(diào)試。

請(qǐng)注意,您可以調(diào)試發(fā)行或調(diào)試二進(jìn)制文件。但發(fā)行二進(jìn)制文件在調(diào)試時(shí)提供的信息較少。 例如,構(gòu)建系統(tǒng)會(huì)選擇某些合適的變量,您無需檢查它們。 此外,代碼重新排序可能增大單步調(diào)試代碼的難度;堆疊追蹤可能不可靠。

在應(yīng)用清單的 <application> 標(biāo)記中聲明 android:debuggable 將導(dǎo)致此變量默認(rèn)使用 debug而非 release。 將 APP_OPTIM 設(shè)置為 release 可替換此默認(rèn)值。

APP_CFLAGS
此變量用于存儲(chǔ)構(gòu)建系統(tǒng)在為任何模塊編譯任何 C 或 C++ 源代碼時(shí)傳遞到編譯器的一組 C 編譯器標(biāo)志。 您可使用此變量根據(jù)需要它的應(yīng)用更改指定模塊的版本,而無需修改 Android.mk 文件本身。

這些標(biāo)志中的所有路徑應(yīng)為頂級(jí) NDK 目錄的相對(duì)路徑。例如,如果您有以下設(shè)置:

sources/foo/Android.mk
sources/bar/Android.mk
要在 foo/Android.mk 中指定您在編譯時(shí)要添加指向 bar 源文件的路徑,應(yīng)使用:

APP_CFLAGS += -Isources/bar
或者:

APP_CFLAGS += -I(LOCAL_PATH)/../bar -I../bar 在其等于 -INDK_ROOT/../bar 后不會(huì)運(yùn)行。

注:此變量?jī)H適用于 android-ndk-1.5_r1 中的 C 源文件,而不適用于 C++ 源文件。 在該版本后的所有版本中,APP_CFLAGS 匹配整個(gè) Android 構(gòu)建系統(tǒng)。

APP_CPPFLAGS
此變量包含構(gòu)建系統(tǒng)在僅構(gòu)建 C++ 源文件時(shí)傳遞到編譯器的一組 C++ 編譯器標(biāo)志。

注:在 android-ndk-1.5_r1 中,此變量適用于 C 和 C++ 源文件。 在 NDK 的所有后續(xù)版本中,APP_CPPFLAGS 現(xiàn)在匹配整個(gè) Android 構(gòu)建系統(tǒng)。 對(duì)于適用于 C 和 C++ 源文件的標(biāo)志,請(qǐng)使用 APP_CFLAGS。

APP_LDFLAGS
構(gòu)建系統(tǒng)在鏈接應(yīng)用時(shí)傳遞的一組鏈接器標(biāo)志。此變量?jī)H在構(gòu)建系統(tǒng)構(gòu)建共享庫和可執(zhí)行文件時(shí)才相關(guān)。 當(dāng)構(gòu)建系統(tǒng)構(gòu)建靜態(tài)庫時(shí),會(huì)忽略這些標(biāo)志。

APP_BUILD_SCRIPT
默認(rèn)情況下,NDK 構(gòu)建系統(tǒng)在 jni/ 下查找名稱為 Android.mk 的文件。

如果要改寫此行為,可以定義 APP_BUILD_SCRIPT 指向替代構(gòu)建腳本。 構(gòu)建系統(tǒng)始終將非絕對(duì)路徑解釋為 NDK 頂級(jí)目錄的相對(duì)路徑。

APP_ABI
默認(rèn)情況下,NDK 構(gòu)建系統(tǒng)為 armeabi ABI 生成機(jī)器代碼。 此機(jī)器代碼對(duì)應(yīng)于基于 ARMv5TE、采用軟件浮點(diǎn)運(yùn)算的 CPU。 您可以使用 APP_ABI 選擇不同的 ABI。 表 1 所示為不同指令集的 APP_ABI 設(shè)置。

表 1. APP_ABI 不同指令集的設(shè)置。

指令集 值
基于 ARMv7 的設(shè)備上的硬件 FPU 指令 APP_ABI := armeabi-v7a
ARMv8 AArch64 APP_ABI := arm64-v8a
IA-32 APP_ABI := x86
Intel64 APP_ABI := x86_64
MIPS32 APP_ABI := mips
MIPS64 (r6) APP_ABI := mips64
所有支持的指令集 APP_ABI := all
注:all 從 NDKr7 開始可用。

您也可以指定多個(gè)值,將它們放在同一行上,中間用空格分隔。例如:

APP_ABI := armeabi armeabi-v7a x86 mips
如需了解所有支持的 ABI 列表及其用法和限制的詳細(xì)信息,請(qǐng)參閱 ABI 管理。

APP_PLATFORM
此變量包含目標(biāo) Android 平臺(tái)的名稱。例如,android-3 指定 Android 1.5 系統(tǒng)映像。 如需平臺(tái)名稱和對(duì)應(yīng) Android 系統(tǒng)映像的完整列表,請(qǐng)參閱 Android NDK 原生 API。

APP_STL
默認(rèn)情況下,NDK 構(gòu)建系統(tǒng)為 Android 系統(tǒng)提供的最小 C++ 運(yùn)行時(shí)庫 (system/lib/libstdc++.so) 提供 C++ 標(biāo)頭。 此外,它隨附您可以在自己的應(yīng)用中使用或鏈接的替代 C++ 實(shí)現(xiàn)。請(qǐng)使用 APP_STL 選擇其中一個(gè)。 如需了解有關(guān)支持的運(yùn)行時(shí)及其功能的信息,請(qǐng)參閱 NDK 運(yùn)行時(shí)和功能。

APP_SHORT_COMMANDS
相當(dāng)于 Application.mk 中的 LOCAL_SHORT_COMMANDS,適用于整個(gè)項(xiàng)目。如需了解詳細(xì)信息,請(qǐng)參閱 Android.mk 上此變量的相關(guān)文檔。

NDK_TOOLCHAIN_VERSION
將此變量定義為 4.9 或 4.8 以選擇 GCC 編譯器的版本。 64 位 ABI 默認(rèn)使用版本 4.9 ,32 位 ABI 默認(rèn)使用版本 4.8。要選擇 Clang 的版本,請(qǐng)將此變量定義為 clang3.4、clang3.5 或 clang。 指定 clang 會(huì)選擇 Clang 的最新版本。

APP_PIE
從 Android 4.1(API 級(jí)別 16)開始,Android 的動(dòng)態(tài)鏈接器支持位置獨(dú)立的可執(zhí)行文件 (PIE)。 從 Android 5.0(API 級(jí)別 21)開始,可執(zhí)行文件需要 PIE。要使用 PIE 構(gòu)建可執(zhí)行文件,請(qǐng)?jiān)O(shè)置 -fPIE 標(biāo)志。 此標(biāo)志增大了通過隨機(jī)化代碼位置來利用內(nèi)存損壞缺陷的難度。 默認(rèn)情況下,如果項(xiàng)目針對(duì) android-16 或更高版本,ndk-build 會(huì)自動(dòng)將此值設(shè)置為 true。您可以手動(dòng)將其設(shè)置為 true 或 false。

此標(biāo)志僅適用于可執(zhí)行文件。它在構(gòu)建共享或靜態(tài)庫時(shí)沒有影響。

注:PIE 可執(zhí)行文件無法在 4.1 版之前的 Android 上運(yùn)行。

此限制僅適用于可執(zhí)行文件。它在構(gòu)建共享或靜態(tài)庫時(shí)沒有影響。

APP_THIN_ARCHIVE
在 Android.mk 文件中為此項(xiàng)目中的所有靜態(tài)庫模塊設(shè)置 LOCAL_THIN_ARCHIVE 的默認(rèn)值。 如需了解詳細(xì)信息,請(qǐng)參閱 Android.mk 文檔中的 LOCAL_THIN_ARCHIVE。

Android.mk官方說明

基礎(chǔ)知識(shí)
在詳細(xì)了解語法之前,先了解 Android.mk 文件所含內(nèi)容的基本信息很有用。 為此,本節(jié)使用 Hello-JNI 示例中的 Android.mk 文件,解釋文件中的每行所起的作用。

Android.mk 文件必須首先定義 LOCAL_PATH 變量:

LOCAL_PATH := $(call my-dir)
此變量表示源文件在開發(fā)樹中的位置。在這里,構(gòu)建系統(tǒng)提供的宏函數(shù) my-dir 將返回當(dāng)前目錄(包含 Android.mk 文件本身的目錄)的路徑。

下一行聲明 CLEAR_VARS 變量,其值由構(gòu)建系統(tǒng)提供。

include $(CLEAR_VARS)
CLEAR_VARS 變量指向特殊 GNU Makefile,可為您清除許多 LOCAL_XXX 變量,例如 LOCAL_MODULE、LOCAL_SRC_FILESLOCAL_STATIC_LIBRARIES。

請(qǐng)注意,它不會(huì)清除 LOCAL_PATH。此變量必須保留其值,因?yàn)橄到y(tǒng)在單一 GNU Make 執(zhí)行環(huán)境(其中所有變量都是全局的)中解析所有構(gòu)建控制文件。 在描述每個(gè)模塊之前,必須聲明(重新聲明)此變量。

接下來,LOCAL_MODULE 變量將存儲(chǔ)您要構(gòu)建的模塊的名稱。請(qǐng)?jiān)趹?yīng)用中每個(gè)模塊使用一個(gè)此變量。

LOCAL_MODULE := hello-jni
每個(gè)模塊名稱必須唯一,且不含任何空格。構(gòu)建系統(tǒng)在生成最終共享庫文件時(shí),會(huì)將正確的前綴和后綴自動(dòng)添加到您分配給 LOCAL_MODULE 的名稱。 例如,上述示例會(huì)導(dǎo)致生成一個(gè)名為 libhello-jni.so 的庫。

注:如果模塊名稱的開頭已是 lib,則構(gòu)建系統(tǒng)不會(huì)附加額外的前綴 lib;而是按原樣采用模塊名稱,并添加 .so 擴(kuò)展名。 因此,比如原來名為 libfoo.c 的源文件仍會(huì)生成名為 libfoo.so 的共享對(duì)象文件。

此行為是為了支持 Android 平臺(tái)源文件從 Android.mk 文件生成的庫;所有這些庫的名稱都以 lib 開頭。

下一行枚舉源文件,以空格分隔多個(gè)文件:

LOCAL_SRC_FILES := hello-jni.c
LOCAL_SRC_FILES 變量必須包含要構(gòu)建到模塊中的 C 和/或 C++ 源文件列表。

最后一行幫助系統(tǒng)將所有內(nèi)容連接到一起:

include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY 變量指向 GNU Makefile 腳本,用于收集您自最近 include 后在 LOCAL_XXX 變量中定義的所有信息。 此腳本確定要構(gòu)建的內(nèi)容及其操作方法。

示例目錄中有更復(fù)雜的示例,包括您可以查看的帶注釋的 Android.mk 文件。 此外,示例:native-activity 詳細(xì)說明了該示例的 Android.mk 文件。 最后,變量和宏提供本節(jié)中變量的進(jìn)一步信息。

變量和宏
構(gòu)建系統(tǒng)提供許多可用于 Android.mk 文件中的變量。其中許多變量已預(yù)先賦值。 另一些變量由您賦值。

除了這些變量之外,您還可以定義自己的任意變量。在定義變量時(shí)請(qǐng)注意,NDK 構(gòu)建

系統(tǒng)會(huì)預(yù)留以下變量名稱

  • LOCAL_開頭的名稱,例如 LOCAL_MODULE

  • PRIVATE_NDK_APP 開頭的名稱。構(gòu)建系統(tǒng)在內(nèi)部使用這些變量。

  • 小寫名稱,例如 my-dir。構(gòu)建系統(tǒng)也是在內(nèi)部使用這些變量。

為了方便別人閱讀而需要在 Android.mk 文件中定義自己的變量,建議在名稱前附加 MY_。

NDK 定義的變量
本節(jié)討論構(gòu)建系統(tǒng)在解析 Android.mk 文件之前定義的 GNU Make 變量。 在某些情況下,NDK 可能會(huì)多次解析 Android.mk 文件,每次使用其中某些變量的不同定義。

CLEAR_VARS
此變量指向的構(gòu)建腳本用于取消定義下面“開發(fā)者定義的變量”一節(jié)中列出的幾乎全部 LOCAL_XXX 變量。 在描述新模塊之前,使用此變量包括此腳本。 使用它的語法為:

include $(CLEAR_VARS)
BUILD_SHARED_LIBRARY

此變量指向的腳本用于收集您在 LOCAL_XXX 變量中提供的模塊所有相關(guān)信息,以及確定如何從列出的源文件構(gòu)建目標(biāo)共享庫。 請(qǐng)注意,使用此腳本要求您至少已為 LOCAL_MODULELOCAL_SRC_FILES賦值(如需了解有關(guān)這些變量的詳細(xì)信息,請(qǐng)參閱模塊描述變量)。

使用此變量的語法為:

include $(BUILD_SHARED_LIBRARY)
共享庫變量導(dǎo)致構(gòu)建系統(tǒng)生成具有 .so 擴(kuò)展名的庫文件。

BUILD_STATIC_LIBRARY
用于構(gòu)建靜態(tài)庫的 BUILD_SHARED_LIBRARY 的變體。構(gòu)建系統(tǒng)不會(huì)將靜態(tài)庫復(fù)制到您的項(xiàng)目/軟件包,但可能使用它們構(gòu)建共享庫(請(qǐng)參閱下面的 LOCAL_STATIC_LIBRARIESLOCAL_WHOLE_STATIC_LIBRARIES)。 使用此變量的語法為:

include $(BUILD_STATIC_LIBRARY)
靜態(tài)庫變量導(dǎo)致構(gòu)建系統(tǒng)生成擴(kuò)展名為 .a 的庫。

PREBUILT_SHARED_LIBRARY
指向用于指定預(yù)建共享庫的構(gòu)建腳本。與BUILD_SHARED_LIBRARYBUILD_STATIC_LIBRARY 的情況不同,這里的 LOCAL_SRC_FILES 值不能是源文件, 而必須是指向預(yù)建共享庫的單一路徑,例如 foo/libfoo.so。 使用此變量的語法為:

include $(PREBUILT_SHARED_LIBRARY)
也可使用 LOCAL_PREBUILTS 變量引用另一個(gè)模塊中的預(yù)建庫。 如需了解有關(guān)使用預(yù)建庫的詳細(xì)信息,請(qǐng)參閱使用預(yù)建庫。

PREBUILT_STATIC_LIBRARY
與 PREBUILT_SHARED_LIBRARY 相同,但用于預(yù)構(gòu)建的靜態(tài)庫。如需了解有關(guān)使用預(yù)建庫的詳細(xì)信息,請(qǐng)參閱使用預(yù)建庫。

TARGET_ARCH
Android 開放源代碼項(xiàng)目所指定的目標(biāo) CPU 架構(gòu)的名稱。對(duì)于與 ARM 兼容的任何構(gòu)建,請(qǐng)使用獨(dú)立于 CPU 架構(gòu)修訂版或 ABI 的 arm(請(qǐng)參閱下面的 TARGET_ARCH_ABI)。

此變量的值取自您在 Android.mk 文件中定義的 APP_ABI 變量,系統(tǒng)將在解析 Android.mk 文件前讀取其值。(翻譯:應(yīng)該是Application.mk)

TARGET_PLATFORM
作為構(gòu)建系統(tǒng)目標(biāo)的 Android API 級(jí)別號(hào)。例如,Android 5.1 系統(tǒng)映像對(duì)應(yīng)于 Android API 級(jí)別 22:android-22。如需平臺(tái)名稱及相應(yīng) Android 系統(tǒng)映像的完整列表,請(qǐng)參閱 Android NDK 原生 API。以下示例顯示了使用此變量的語法:

TARGET_PLATFORM := android-22
TARGET_ARCH_ABI
當(dāng)構(gòu)建系統(tǒng)解析此 Android.mk 文件時(shí),此變量將 CPU 和架構(gòu)的名稱存儲(chǔ)到目標(biāo)。 您可以指定以下一個(gè)或多個(gè)值,使用空格作為多個(gè)目標(biāo)之間的分隔符。 表 1 顯示了要用于每個(gè)支持的 CPU 和架構(gòu)的 ABI 設(shè)置。

表 1. 不同 CPU 和架構(gòu)的 ABI 設(shè)置。

CPU 和架構(gòu)|設(shè)置的參數(shù)
ARMv5TE armeabi
ARMv7   armeabi-v7a
ARMv8 AArch64   arm64-v8a
i686    x86
x86-64  x86_64
mips32 (r1) mips
mips64 (r6) mips64
全部  all

以下示例顯示如何將 ARMv8 AArch64 設(shè)置為目標(biāo) CPU 與 ABI 的組合:

TARGET_ARCH_ABI := arm64-v8a
注:在 Android NDK 1.6_r1 和以前的版本中,此變量定義為 arm。

如需了解架構(gòu) ABI 和相關(guān)兼容性問題的詳細(xì)信息,請(qǐng)參閱 ABI 管理。

未來的新目標(biāo) ABI 將有不同的值。

TARGET_ABI
目標(biāo) Android API 級(jí)別與 ABI 的聯(lián)接,特別適用于要針對(duì)實(shí)際設(shè)備測(cè)試特定目標(biāo)系統(tǒng)映像的情況。 例如,要指定在 Android API 級(jí)別 22 上運(yùn)行的 64 位 ARM 設(shè)備:

TARGET_ABI := android-22-arm64-v8a
注:在 Android NDK 1.6_r1 和以前的版本中,默認(rèn)值為 android-3-arm。

模塊描述變量
本節(jié)中的變量向構(gòu)建系統(tǒng)描述您的模塊。每個(gè)模塊描述應(yīng)遵守以下基本流程:

使用 CLEAR_VARS 變量初始化或取消定義與模塊相關(guān)的變量。
為用于描述模塊的變量賦值。
使用 BUILD_XXX 變量設(shè)置 NDK 構(gòu)建系統(tǒng),以便為模塊使用適當(dāng)?shù)臉?gòu)建腳本。
LOCAL_PATH
此變量用于指定當(dāng)前文件的路徑。必須在 Android.mk 文件的開頭定義它。 以下示例向您展示如何操作:

LOCAL_PATH := $(call my-dir)
CLEAR_VARS 指向的腳本不會(huì)清除此變量。因此,即使您的 Android.mk 文件描述了多個(gè)模塊,您也只需定義它一次。

LOCAL_MODULE
此變量用于存儲(chǔ)模塊的名稱。它在所有模塊名稱之間必須唯一,并且不得包含任何空格。 必須在包含任何腳本(用于 CLEAR_VARS 的腳本除外)之前定義它。 無需添加 lib 前綴或者 .so 或 .a 文件擴(kuò)展名;構(gòu)建系統(tǒng)會(huì)自動(dòng)進(jìn)行這些修改。 在整個(gè) Android.mk 和 Application.mk 文件中,請(qǐng)通過未修改的名稱引用模塊。 例如,以下行會(huì)導(dǎo)致生成名為 libfoo.so 的共享庫模塊:

LOCAL_MODULE := "foo"
如果希望生成的模塊使用 lib 以外的名稱和 LOCAL_MODULE 以外的值,可以使用 LOCAL_MODULE_FILENAME 變量為生成的模塊指定自己選擇的名稱。

LOCAL_MODULE_FILENAME
此可選變量可讓您覆蓋構(gòu)建系統(tǒng)默認(rèn)用于其生成的文件的名稱。 例如,如果 LOCAL_MODULE 的名稱為 foo,您可以強(qiáng)制系統(tǒng)將它生成的文件命名為 libnewfoo。 以下示例顯示如何完成此操作:

LOCAL_MODULE := foo
LOCAL_MODULE_FILENAME := libnewfoo
對(duì)于共享庫模塊,此示例將生成一個(gè)名為 libnewfoo.so 的文件。

注:無法替換文件路徑或文件擴(kuò)展名。

LOCAL_SRC_FILES
此變量包含構(gòu)建系統(tǒng)用于生成模塊的源文件列表。 只列出構(gòu)建系統(tǒng)實(shí)際傳遞到編譯器的文件,因?yàn)闃?gòu)建系統(tǒng)會(huì)自動(dòng)計(jì)算所有關(guān)聯(lián)的依賴關(guān)系。

請(qǐng)注意,可以使用相對(duì)文件路徑(指向 LOCAL_PATH)和絕對(duì)文件路徑。

建議避免使用絕對(duì)文件路徑;相對(duì)路徑會(huì)使 Android.mk 文件移植性更強(qiáng)。

注:在構(gòu)建文件中務(wù)必使用 Unix 樣式的正斜杠 (/)。構(gòu)建系統(tǒng)無法正確處理 Windows 樣式的反斜杠 ()。

LOCAL_CPP_EXTENSION
可以使用此可選變量為 C++ 源文件指明 .cpp 以外的文件擴(kuò)展名。 例如,以下行會(huì)將擴(kuò)展名改為 .cxx。(設(shè)置必須包含點(diǎn)。)

LOCAL_CPP_EXTENSION := .cxx
從 NDK r7 開始,您可以使用此變量指定多個(gè)擴(kuò)展名。例如:

LOCAL_CPP_EXTENSION := .cxx .cpp .cc
LOCAL_CPP_FEATURES
可以使用此可選變量指明您的代碼依賴于特定 C++ 功能。它在構(gòu)建過程中啟用正確的編譯器和鏈接器標(biāo)志。 對(duì)于預(yù)構(gòu)建的庫,此變量還可聲明二進(jìn)制文件依賴哪些功能,從而幫助確保最終關(guān)聯(lián)正確工作。 建議使用此變量,而不要直接在 LOCAL_CPPFLAGS 定義中啟用 -frtti 和 -fexceptions。

使用此變量可讓構(gòu)建系統(tǒng)對(duì)每個(gè)模塊使用適當(dāng)?shù)臉?biāo)志。使用 LOCAL_CPPFLAGS 會(huì)導(dǎo)致編譯器對(duì)所有模塊使用所有指定的標(biāo)志,而不管實(shí)際需求如何。

例如,要指示您的代碼使用 RTTI(運(yùn)行時(shí)類型信息),請(qǐng)編寫:
LOCAL_CPP_FEATURES := rtti
要指示您的代碼使用 C++ 異常,請(qǐng)編寫:

LOCAL_CPP_FEATURES := exceptions
您還可為此變量指定多個(gè)值。例如:

LOCAL_CPP_FEATURES := rtti features
描述值的順序不重要。
LOCAL_C_INCLUDES
可以使用此可選變量指定相對(duì)于 NDK root 目錄的路徑列表,以便在編譯所有源文件(C、C++ 和 Assembly)時(shí)添加到 include 搜索路徑。 例如:

LOCAL_C_INCLUDES := sources/foo
甚至:

LOCAL_C_INCLUDES := $(LOCAL_PATH)//foo
在通過 LOCAL_CFLAGS 或 LOCAL_CPPFLAGS 設(shè)置任何對(duì)應(yīng)的 include 標(biāo)志之前定義此變量。

在使用 ndk-gdb 啟動(dòng)本地調(diào)試時(shí),構(gòu)建系統(tǒng)也會(huì)自動(dòng)使用 LOCAL_C_INCLUDES 路徑。

LOCAL_CFLAGS
此可選變量為構(gòu)建系統(tǒng)設(shè)置在構(gòu)建 C 和 C++ 源文件時(shí)要傳遞的編譯器標(biāo)志。 此功能對(duì)于指定額外的宏定義或編譯選項(xiàng)可能很有用。

盡量不要更改 Android.mk 文件中的優(yōu)化/調(diào)試級(jí)別。構(gòu)建系統(tǒng)可使用 Application.mk 文件中的相關(guān)信息自動(dòng)為您處理此設(shè)置。 這樣允許構(gòu)建系統(tǒng)生成在調(diào)試時(shí)使用的有用數(shù)據(jù)文件。

注:在 android-ndk-1.5_r1 中,相應(yīng)的標(biāo)志只適用于 C 源文件,而不適用于 C++ 源文件。 它們現(xiàn)在與整個(gè) Android 構(gòu)建系統(tǒng)的行為匹配。(您現(xiàn)在可以使用 LOCAL_CPPFLAGS 只為 C++ 源文件指定標(biāo)志。)

可通過編寫以下代碼指定其他 include 路徑:

LOCAL_CFLAGS += -I<path>,
但使用 LOCAL_C_INCLUDES 更好,因?yàn)檫@樣也可以通過 ndk-gdb 使用可用于本地調(diào)試的路徑。
LOCAL_CPPFLAGS
僅當(dāng)構(gòu)建 C++ 源文件時(shí)才會(huì)傳遞一組可選的編譯器標(biāo)志。 它們將出現(xiàn)在編譯器命令行中的 LOCAL_CFLAGS 后面。

注:在 android-ndk-1.5_r1 中,相應(yīng)的標(biāo)志適用于 C 和 C++ 源文件。 這已經(jīng)更正,可與整個(gè) Android 構(gòu)建系統(tǒng)的行為匹配。要為 C 和 C++ 源文件指定標(biāo)志,請(qǐng)使用 LOCAL_CFLAGS。

LOCAL_STATIC_LIBRARIES
此變量用于存儲(chǔ)當(dāng)前模塊依賴的靜態(tài)庫模塊列表。

如果當(dāng)前模塊是共享庫或可執(zhí)行文件,此變量將強(qiáng)制這些庫鏈接到生成的二進(jìn)制文件。

如果當(dāng)前模塊是靜態(tài)庫,此變量只是指示,依賴當(dāng)前模塊的模塊也會(huì)依賴列出的庫。

LOCAL_SHARED_LIBRARIES
此變量是此模塊在運(yùn)行時(shí)依賴的共享庫模塊列表。 此信息在鏈接時(shí)需要,并且會(huì)在生成的文件中嵌入相應(yīng)的信息。

LOCAL_WHOLE_STATIC_LIBRARIES
此變量是 LOCAL_STATIC_LIBRARIES 的變體,表示鏈接器應(yīng)將相關(guān)的庫模塊視為整個(gè)存檔。 如需了解有關(guān)整個(gè)存檔的詳細(xì)信息,請(qǐng)參閱 GNU 鏈接器關(guān)于 --whole-archive 標(biāo)志的文檔。

當(dāng)多個(gè)靜態(tài)庫之間具有循環(huán)相依關(guān)系時(shí),此變量很有用。 使用此變量構(gòu)建共享庫時(shí),將會(huì)強(qiáng)制構(gòu)建系統(tǒng)將所有對(duì)象文件從靜態(tài)庫添加到最終二進(jìn)制文件。 但在生成可執(zhí)行文件時(shí)不會(huì)發(fā)生這樣的情況。

LOCAL_LDLIBS
此變量包含在構(gòu)建共享庫或可執(zhí)行文件時(shí)要使用的其他鏈接器標(biāo)志列表。 它可讓您使用 -l 前綴傳遞特定系統(tǒng)庫的名稱。 例如,以下示例指示鏈接器生成在加載時(shí)鏈接到 /system/lib/libz.so 的模塊:

LOCAL_LDLIBS := -lz
如需了解此 NDK 版本中可以鏈接的已公開系統(tǒng)庫列表,請(qǐng)參閱 Android NDK 原生 API。

注: 如果為靜態(tài)庫定義此變量,構(gòu)建系統(tǒng)會(huì)忽略它,并且 ndk-build 會(huì)顯示一則警告。

LOCAL_LDFLAGS
構(gòu)建共享庫或可執(zhí)行文件時(shí)供構(gòu)建系統(tǒng)使用的其他鏈接器標(biāo)志列表。 例如,以下示例在 ARM/X86 GCC 4.6+ 上使用 ld.bfd 鏈接器,該系統(tǒng)上的默認(rèn)鏈接器是 ld.gold

LOCAL_LDFLAGS += -fuse-ld=bfd
注:如果為靜態(tài)庫定義此變量,構(gòu)建系統(tǒng)會(huì)忽略它,并且 ndk-build 會(huì)顯示一則警告。

LOCAL_ALLOW_UNDEFINED_SYMBOLS
默認(rèn)情況下,若構(gòu)建系統(tǒng)在嘗試構(gòu)建共享庫時(shí)遇到未定義的引用,將會(huì)引發(fā)“未定義的符號(hào)”錯(cuò)誤。 此錯(cuò)誤可幫助您捕獲源代碼中的缺陷。

要停用此檢查,請(qǐng)將此變量設(shè)置為 true。請(qǐng)注意,此設(shè)置可能導(dǎo)致共享庫在運(yùn)行時(shí)加載。

注: 如果為靜態(tài)庫定義此變量,構(gòu)建系統(tǒng)會(huì)忽略它,并且 ndk-build 會(huì)顯示一則警告。

LOCAL_ARM_MODE
默認(rèn)情況下,構(gòu)建系統(tǒng)在 thumb 模式中生成 ARM 目標(biāo)二進(jìn)制文件,其中每個(gè)指令都是 16 位寬,并且與 thumb/ 目錄中的 STL 庫鏈接。將此變量定義為 arm 會(huì)強(qiáng)制構(gòu)建系統(tǒng)在 32 位 arm 模式下生成模塊的對(duì)象文件。 以下示例顯示如何執(zhí)行此操作:

LOCAL_ARM_MODE := arm
您也可以為源文件名附加 .arm 后綴,指示構(gòu)建系統(tǒng)只在 arm 模式中構(gòu)建特定的源文件。 例如,以下示例指示構(gòu)建系統(tǒng)始終在 ARM 模式中編譯 bar.c,但根據(jù) LOCAL_ARM_MODE 的值構(gòu)建 foo.c。

LOCAL_SRC_FILES := foo.c bar.c.arm
注:您也可以在 Application.mk 文件中將 APP_OPTIM 設(shè)置為 debug,強(qiáng)制構(gòu)建系統(tǒng)生成 ARM 二進(jìn)制文件。指定 debug 會(huì)強(qiáng)制構(gòu)建 ARM,因?yàn)楣ぞ哝溦{(diào)試程序無法正確處理 Thumb 代碼。

LOCAL_ARM_NEON
此變量?jī)H在您針對(duì) armeabi-v7a ABI 時(shí)才重要。它允許在 C 和 C++ 源文件中使用 ARM Advanced SIMD (NEON) GCC 內(nèi)聯(lián)函數(shù),以及在 Assembly 文件中使用 NEON 指令。

請(qǐng)注意,并非所有基于 ARMv7 的 CPU 都支持 NEON 指令集擴(kuò)展。因此,必須執(zhí)行運(yùn)行時(shí)檢測(cè)以便在運(yùn)行時(shí)安全地使用此代碼。 如需了解詳細(xì)信息,請(qǐng)參閱 NEON 支持和 cpufeatures 庫。

或者,您也可以使用 .neon 后綴指定構(gòu)建系統(tǒng)只編譯支持 NEON 的特定源文件。 在以下示例中,構(gòu)建系統(tǒng)編譯支持 thumb 和 neon 的 foo.c、支持 thumb 的 bar.c,以及支持 ARM 和 NEON 的 zoo.c。

LOCAL_SRC_FILES = foo.c.neon bar.c zoo.c.arm.neon
如果您使用兩個(gè)后綴,.arm 必須在 .neon 前面。

LOCAL_DISABLE_NO_EXECUTE
Android NDK r4 添加了對(duì)“NX 位”安全功能的支持。此支持默認(rèn)啟用,但您也可通過將此變量設(shè)置為 true 將其停用。 如果沒有必要的原因,我們不建議停用。

此功能不會(huì)修改 ABI,并且僅在針對(duì) ARMv6+ CPU 設(shè)備的內(nèi)核上啟用。 啟用此功能的機(jī)器代碼在運(yùn)行較早 CPU 架構(gòu)的設(shè)備上將不加修改而直接運(yùn)行。

如需了解詳細(xì)信息,請(qǐng)參閱 Wikipedia:NX 位和 GNU ??焖偃腴T。

LOCAL_DISABLE_RELRO

默認(rèn)情況下,NDK 編譯具有只讀重定位和 GOT 保護(hù)的代碼。 此變量指示運(yùn)行時(shí)鏈接器在重定位后將某些內(nèi)存區(qū)域標(biāo)記為只讀,增加了某些安全漏洞利用(例如 GOT 覆蓋)的難度。 請(qǐng)注意,這些保護(hù)僅在 Android API 級(jí)別 16 和更高版本上有效。在較低的 API 級(jí)別上,該代碼仍會(huì)運(yùn)行,但沒有內(nèi)存保護(hù)。

此變量默認(rèn)啟用,但您也可通過將其值設(shè)置為 true 來停用它。 如果沒有必要的原因,我們不建議停用。

如需了解詳細(xì)信息,請(qǐng)參閱 RELRO:重定位只讀和 RedHat Enterprise Linux 中的安全增強(qiáng)功能(第 6 節(jié))。

LOCAL_DISABLE_FORMAT_STRING_CHECKS

默認(rèn)情況下,構(gòu)建系統(tǒng)編譯具有格式字符串保護(hù)的代碼。如果 printf 樣式的函數(shù)中使用非常量的格式字符串,這樣會(huì)強(qiáng)制編譯器出錯(cuò)。

此保護(hù)默認(rèn)啟用,但您也可通過將此變量的值設(shè)置為 true 將其停用。 如果沒有必要的原因,我們不建議停用。

LOCAL_EXPORT_CFLAGS
此變量用于記錄一組 C/C++ 編譯器標(biāo)志,這將標(biāo)志將添加到通過 LOCAL_STATIC_LIBRARIES 或 LOCAL_SHARED_LIBRARIES 變量使用它們的任何其他模塊的 LOCAL_CFLAGS 定義。

例如,假設(shè)有以下模塊對(duì):foo 和 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)

在這里,構(gòu)建系統(tǒng)在構(gòu)建 bar.c 時(shí)會(huì)向編譯器傳遞標(biāo)志 -DFOO=1 和 -DBAR=2。 它還會(huì)在模塊的 LOCAL_CFLAGS 前面加上導(dǎo)出的標(biāo)志,以便您輕松替換它們。

此外,模塊之間的關(guān)系也是可傳遞的:如果 zoo 依賴于 bar,后者又依賴于 foo,則 zoo 也會(huì)繼承從 foo 導(dǎo)出的所有標(biāo)志。
最后,構(gòu)建系統(tǒng)在本地構(gòu)建時(shí)不使用導(dǎo)出的標(biāo)志(即,構(gòu)建要導(dǎo)出其標(biāo)志的模塊)。 因此,在上面的示例中,構(gòu)建 foo/foo.c 時(shí)不會(huì)將 -DFOO=1 傳遞到編譯器。 要在本地構(gòu)建,請(qǐng)改用 LOCAL_CFLAGS。

LOCAL_EXPORT_CPPFLAGS
此變量與 LOCAL_EXPORT_CFLAGS 相同,但僅適用于 C++ 標(biāo)志。

LOCAL_EXPORT_C_INCLUDES
此變量與 LOCAL_EXPORT_CFLAGS 相同,但適用于 C include 路徑。例如,當(dāng) bar.c 需要包含模塊 foo 中的標(biāo)頭時(shí)很有用。

LOCAL_EXPORT_LDFLAGS
此變量與 LOCAL_EXPORT_CFLAGS 相同,但適用于鏈接器標(biāo)志。

LOCAL_EXPORT_LDLIBS
此變量與 LOCAL_EXPORT_CFLAGS 相同,用于指示構(gòu)建系統(tǒng)將特定系統(tǒng)庫的名稱傳遞到編譯器。 在您指定的每個(gè)庫名稱前面附加 -l。

請(qǐng)注意,構(gòu)建系統(tǒng)會(huì)將導(dǎo)入的鏈接器標(biāo)志附加到模塊的 LOCAL_LDLIBS 變量值。 其原因在于 Unix 鏈接器運(yùn)行的方式。

當(dāng)模塊 foo 是靜態(tài)庫并且具有依賴于系統(tǒng)庫的代碼時(shí),此變量通常很有用。 然后您可以使用 LOCAL_EXPORT_LDLIBS 導(dǎo)出相依關(guān)系。 例如:

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)

在此示例中,構(gòu)建系統(tǒng)在構(gòu)建 libbar.so 時(shí),將在鏈接器命令的末尾放置 -llog。 這樣會(huì)告知鏈接器,由于 libbar.so 依賴于 foo,因此它也依賴于系統(tǒng)日志記錄庫。

LOCAL_SHORT_COMMANDS
當(dāng)您的模塊有很多源文件和/或相依的靜態(tài)或共享庫時(shí),將此變量設(shè)置為 true。 這樣會(huì)強(qiáng)制構(gòu)建系統(tǒng)對(duì)包含中間對(duì)象文件或鏈接庫的存檔使用 @ 語法。

此功能在 Windows 上可能很有用,其中命令行最多只接受 8191 個(gè)字符,這對(duì)于復(fù)雜的項(xiàng)目可能太少。 它還會(huì)影響個(gè)別源文件的編譯,而且將幾乎所有編譯器標(biāo)志放在列表文件內(nèi)。

請(qǐng)注意,true 以外的任何值都將恢復(fù)到默認(rèn)行為。 您也可在 Application.mk 文件中定義 APP_SHORT_COMMANDS,以強(qiáng)制對(duì)項(xiàng)目中的所有模塊實(shí)施此行為。

不建議默認(rèn)啟用此功能,因?yàn)樗鼤?huì)減慢構(gòu)建的速度。

LOCAL_THIN_ARCHIVE
構(gòu)建靜態(tài)庫時(shí)將此變量設(shè)置為 true。這樣會(huì)生成一個(gè)瘦存檔 ,即一個(gè)庫文件,其中不含對(duì)象文件,而只包含它通常要包含的實(shí)際對(duì)象的文件路徑。

這對(duì)于減小構(gòu)建輸出的大小非常有用。缺點(diǎn)是:這樣的庫無法移至不同的位置(其中的所有路徑都是相對(duì)的)。

有效值為 true、false 或空白??赏ㄟ^ APP_THIN_ARCHIVE 變量在 Application.mk 文件中設(shè)置默認(rèn)值。

注:對(duì)于非靜態(tài)庫模塊或預(yù)構(gòu)建的靜態(tài)庫模塊會(huì)忽略此變量。

LOCAL_FILTER_ASM
將此變量定義為構(gòu)建系統(tǒng)要用于過濾從您為 LOCAL_SRC_FILES 指定的文件提取或生成的匯編文件的 shell 命令。

定義此變量會(huì)導(dǎo)致發(fā)生以下情況:

構(gòu)建系統(tǒng)從任何 C 或 C++ 源文件生成臨時(shí)匯編文件,而不是將它們編譯到對(duì)象文件。
構(gòu)建系統(tǒng)在任何臨時(shí)匯編文件以及 LOCAL_SRC_FILES 中所列任何匯編文件的 LOCAL_FILTER_ASM 中執(zhí)行 shell 命令,因此會(huì)生成另一個(gè)臨時(shí)匯編文件。
構(gòu)建系統(tǒng)將這些過濾的匯編文件編譯到對(duì)象文件中。
例如:

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”對(duì)應(yīng)編譯器,“2”對(duì)應(yīng)過濾器,“3”對(duì)應(yīng)匯編程序。過濾器必須是采用輸入文件名稱作為其第一個(gè)參數(shù)、輸出文件名稱作為第二個(gè)參數(shù)的獨(dú)立 shell 命令。 例如:

myasmfilter $OBJS_DIR/foo.S.original $OBJS_DIR/foo.S
myasmfilter bar.S $OBJS_DIR/bar.S

NDK 提供的函數(shù)宏
本節(jié)說明 NDK 提供的 GNU Make 函數(shù)宏。使用 $(call <function>) 對(duì)它們估值;它們返回文本信息。

my-dir
此宏返回最后包含的 makefile 的路徑,通常是當(dāng)前 Android.mk 的目錄。my-dir 可用于在 Android.mk 文件的開頭定義 LOCAL_PATH。 例如:

LOCAL_PATH := $(call my-dir)
由于 GNU Make 運(yùn)行的方式,此宏實(shí)際返回的內(nèi)容是構(gòu)建系統(tǒng)在解析構(gòu)建腳本時(shí)包含在最后一個(gè) makefile 的路徑。 因此,在包含另一個(gè)文件后不應(yīng)調(diào)用 my-dir。

例如,考慮以下示例:

LOCAL_PATH := $(call my-dir)

declare one module

include $(LOCAL_PATH)/foo/Android.mk

LOCAL_PATH := $(call my-dir)

declare another module
這里的問題在于,對(duì) my-dir 的第二次調(diào)用將 LOCAL_PATH 定義為 PATH/foo,而不是PATH,因?yàn)檫@是其最近 include 指向的位置。

在 Android.mk 文件中的任何其他內(nèi)容后放置額外 include 可避免此問題。 例如:

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

如果以這種方式構(gòu)建文件不可行,請(qǐng)將第一個(gè) my-dir 調(diào)用的值保存到另一個(gè)變量中。 例如:

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
返回位于當(dāng)前 my-dir 路徑所有子目錄中的 Android.mk 文件列表。

可以使用此函數(shù)為構(gòu)建系統(tǒng)提供深入嵌套的源目錄層次結(jié)構(gòu)。 默認(rèn)情況下,NDK 只在包含 Android.mk 文件的目錄中查找文件。

this-makefile
返回當(dāng)前 makefile(構(gòu)建系統(tǒng)從中調(diào)用函數(shù))的路徑。

parent-makefile
返回包含樹中父 makefile 的路徑(包含當(dāng)前 makefile 的 makefile 路徑)。

grand-parent-makefile
返回包含樹中祖父 makefile 的路徑(包含當(dāng)前父 makefile 的 makefile 路徑)。

import-module
用于按模塊的名稱查找和包含模塊的 Android.mk 文件的函數(shù)。 典型的示例如下所示:

$(call import-module,<name>)
在此示例中,構(gòu)建系統(tǒng)查找 NDK_MODULE_PATH 環(huán)境變量引用的目錄列表中以 <name> 標(biāo)記的模塊,并且自動(dòng)為您包含其Android.mk 文件。

純make練習(xí)語法。

window使用cygwin64 把bin目錄添加到環(huán)境變量中
make -f myfile.mk 測(cè)試一個(gè)mk文件。

make默認(rèn)識(shí)別的文件是當(dāng)前運(yùn)行目錄下的Makefile不帶后綴文件。

myfile.mk內(nèi)容如下

$(warning nihao)
LOCAL_PATH:= current_$(call my-dir)
$(warning $(LOCAL_PATH))

my-dir沒有輸出任何東西,因?yàn)檫@要安卓的ndk-build才有。
測(cè)試這個(gè)文件的方法
make -f myfile.mk
或者在此目錄創(chuàng)建Makefile然后輸入include myfile.mk 執(zhí)行make將自動(dòng)執(zhí)行.

定義Make target

語法格式與執(zhí)行

target名:
TAB命令行名

aa:
    gcc -o hello hello.c
    ./hello.exe

切記gcc前面是用tab隔開的,否則會(huì)報(bào)錯(cuò)誤。
測(cè)試執(zhí)行
make -f mymake.mk aa

如果不出意外會(huì)編譯當(dāng)前目錄的hello.c并執(zhí)行,前提是hello.c存在以及配置了gcc的環(huán)境變量。

完整示例:

#配置環(huán)境變量make,用法 輸入 make -f test.mk
#圖標(biāo)是可以指定的,如果沒有指定目標(biāo)會(huì)找到第一個(gè),如果傳遞了目標(biāo)比如傳遞make -f test.mk run:則會(huì)執(zhí)行后者,而不是前者。
VARIABLE1:= 555
$(param $(1))
$(info 2-$(VARIABLE1))
aa=$(call VARIABLE1,hello,world)#不用冒號(hào)也可以定義?/
$(warning 你可以輸入make -f test.mk help執(zhí)行菜單幫助)

$(info 2-$(aa))
help:
    @echo 歡迎學(xué)習(xí)mk,你如果能執(zhí)行本文件,那么你應(yīng)該可以算和我一樣已經(jīng)找到了寫make的感覺了。
    @echo 輸入make -f 文件 run 執(zhí)行文件
    @echo 輸入make -f 文件 compile 編譯文件
    @echo 執(zhí)行了all任務(wù),
    @echo 你好 你好 target下面的東西都需要用空格隔開,否則會(huì)出現(xiàn)語法錯(cuò)誤。
    @echo make語法中以艾特開頭可以執(zhí)行系統(tǒng)的命令,如echo就屬于.
    
    
    
$(warning Wellcome Study write makefile)
TEMP:=HELLO
$(warning execcompile)#不執(zhí)行..似乎不能連續(xù)輸出多個(gè)
compile:bbb #這個(gè)值1:值2是必須寫的,否則報(bào)錯(cuò)。
    gcc -o foo hello.c
    ./foo.exe
    @echo 執(zhí)行編譯完成


run:
    @echo 執(zhí)行了run
    ./foo.exe

參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容