android.mk ndk编译选项优化,Android NDK 编译脚本分析 之一
版權(quán)信息:本文為本人原創(chuàng),歡迎轉(zhuǎn)載,但請(qǐng)著明出處,并保留本版權(quán)信息。
Android NDK編譯腳本編寫起來(lái)還是是比較簡(jiǎn)單條理的,然而它的語(yǔ)法和傳統(tǒng)的linux GNU?Make編譯腳本的編寫似乎有很大的不同,這讓習(xí)慣了GNU Makefile的用戶很不習(xí)慣。有許多人會(huì)用它,但對(duì)其工作原理卻不理解,筆者甚至一度誤認(rèn)為那是一套全新腳本語(yǔ)言。我將在后文中對(duì)這一編譯管理系統(tǒng)做一些分析,試著分析一下它和傳統(tǒng)GNU Makefile的關(guān)系。
本文假設(shè)您已經(jīng)擁有 Linux命令和GNU Makefile的基礎(chǔ)知識(shí),當(dāng)然您也可以邊閱讀,邊查找參考相關(guān)的知識(shí)。參考資料2是徐海兵先生整理的 GNU Makefile 中文手冊(cè),推薦英文不太好的朋友拿來(lái)作為參考。
這篇文章是對(duì)自己前段時(shí)間所學(xué)知識(shí)的一個(gè)記錄整理,以期與大家互相交流,希望朋友們不要吝于來(lái)信,指出本文的錯(cuò)漏之處或者你們不同理解(絕非客氣,真的期望能收到您的信件,我的郵箱 techres#163.com,請(qǐng)把 # 換成 @)。
====================================================================
Android NDK 的編譯腳本系統(tǒng),實(shí)際上并不是什么新東西,就是對(duì) GNU MakeFile 系統(tǒng)的封裝。Android NDK?自帶了很多 .mk? 文件(保存在ndk的 NDK_ROOT/build 目錄中),文件中預(yù)定義了很多 Make? 腳本函數(shù)和變量,以供用戶編寫自己的編譯腳本時(shí)使用。另外,NDK為所有應(yīng)用統(tǒng)一提供了一個(gè)固定的編譯入口--即大家熟悉的ndk-build。
我們首先從每個(gè)應(yīng)用編譯時(shí)都需要用到的編譯入口開(kāi)始分析。
一、ndk-build分析
(一)、腳本內(nèi)容分析
該文件存在于ndk安裝根目錄中,實(shí)際上是一個(gè) shell 腳本。其有效內(nèi)容如下:
PROGDIR=`dirname $0`
PROGDIR=`cd $PROGDIR && pwd`
# If GNUMAKE is defined, check that it points to a valid file
if [ -n "$GNUMAKE" ] ; then
ABS_GNUMAKE=`which $GNUMAKE 2> /dev/null`
if [ $? != 0 ] ; then
echo "ERROR: Your GNUMAKE variable is defined to an invalid name: $GNUMAKE"
echo "Please fix it to point to a valid make executable (e.g. /usr/bin/make)"
exit 1
fi
GNUMAKE="$ABS_GNUMAKE"
else
# Otherwise, use 'make' and check that it is available
GNUMAKE=`which make 2> /dev/null`
if [ $? != 0 ] ; then
echo "ERROR: Cannot find 'make' program. Please install Cygwin make package"
echo "or define the GNUMAKE variable to point to it."
exit 1
fi
fi
# On Windows, when running under cygwin, check that we are
# invoking a cygwin-compatible GNU Make binary. It is unfortunately
# common for app developers to have another non-cygwin compatible
#
if [ "$OSTYPE" = "cygwin" ] ; then
GNUMAKE=`cygpath -u $GNUMAKE`
PROGDIR_MIXED=`cygpath -m $PROGDIR`
CYGWIN_GNUMAKE=`$GNUMAKE -f $PROGDIR_MIXED/build/core/check-cygwin-make.mk 2>&1`
if [ $? != 0 ] ; then
echo "ERROR: You are using a non-Cygwin compatible Make program."
echo "Currently using: `cygpath -m $GNUMAKE`"
echo ""
echo "To solve the issue, follow these steps:"
echo ""
echo "1. Ensure that the Cygwin 'make' package is installed."
echo "?? NOTE: You will need GNU Make 3.81 or later!"
echo ""
echo "2. Define the GNUMAKE environment variable to point to it, as in:"
echo ""
echo "???? export GNUMAKE=/usr/bin/make"
echo ""
echo "3. Call 'ndk-build' again."
echo ""
exit 1
fi
fi
$GNUMAKE -f $PROGDIR/build/core/build-local.mk "$@"
下面我們對(duì)這些有效代碼逐一進(jìn)行分析:
PROGDIR=`dirname $0`
PROGDIR=`cd $PROGDIR && pwd`
在GNU makefile中,兩個(gè)反引號(hào)相當(dāng)于 shell ?函數(shù),反引號(hào)括起來(lái)的內(nèi)容相當(dāng)于 shell 函數(shù)的參數(shù)。而shell函數(shù)的功能就是調(diào)用操作系統(tǒng)的命令。
PROGDIR=`dirname $0`
linux 命令 dirname, 功能是獲取后面參數(shù)的路徑。例如:
#dirname ../../../ndk-build
執(zhí)行的結(jié)果是:"../../.."。順便提一下,這里不能用pwd命令,pwd 命令,是獲得當(dāng)前路徑,獲取的是當(dāng)前路徑的絕對(duì)路徑。所以,上面兩條語(yǔ)句的結(jié)果就是在 PROGDIR 變量中保存 ndk-build 所在的路徑。有了這兩條語(yǔ)句之后,就可以在任何位置執(zhí)行 ndk-build ,而不必非要在 ndk 根目錄中執(zhí)行。
再之后的兩段語(yǔ)句,是用來(lái)確定不同平臺(tái)下正確的 make 工具。
# If GNUMAKE is defined, check that it points to a valid file
if [ -n "$GNUMAKE" ] ; then
ABS_GNUMAKE=`which $GNUMAKE 2> /dev/null`
if [ $? != 0 ] ; then
echo "ERROR: Your GNUMAKE variable is defined to an invalid name: $GNUMAKE"
echo "Please fix it to point to a valid make executable (e.g. /usr/bin/make)"
exit 1
fi
GNUMAKE="$ABS_GNUMAKE"
else
# Otherwise, use 'make' and check that it is available
GNUMAKE=`which make 2> /dev/null`
if [ $? != 0 ] ; then
echo "ERROR: Cannot find 'make' program. Please install Cygwin make package"
echo "or define the GNUMAKE variable to point to it."
exit 1
fi
fi
# On Windows, when running under cygwin, check that we are
# invoking a cygwin-compatible GNU Make binary. It is unfortunately
# common for app developers to have another non-cygwin compatible
#
if [ "$OSTYPE" = "cygwin" ] ; then
GNUMAKE=`cygpath -u $GNUMAKE`
PROGDIR_MIXED=`cygpath -m $PROGDIR`
CYGWIN_GNUMAKE=`$GNUMAKE -f $PROGDIR_MIXED/build/core/check-cygwin-make.mk 2>&1`
if [ $? != 0 ] ; then
echo "ERROR: You are using a non-Cygwin compatible Make program."
echo "Currently using: `cygpath -m $GNUMAKE`"
echo ""
echo "To solve the issue, follow these steps:"
echo ""
echo "1. Ensure that the Cygwin 'make' package is installed."
echo "?? NOTE: You will need GNU Make 3.81 or later!"
echo ""
echo "2. Define the GNUMAKE environment variable to point to it, as in:"
echo ""
echo "???? export GNUMAKE=/usr/bin/make"
echo ""
echo "3. Call 'ndk-build' again."
echo ""
exit 1
fi
fi
最后一條語(yǔ)句,是調(diào)用:
$GNUMAKE -f $PROGDIR/build/core/build-local.mk "$@"
這是真正開(kāi)始執(zhí)行 make ,指定 Makefile 為 build-local.mk 文件。同時(shí),將 ndk-build 的所有參數(shù)($@)原封不動(dòng)地都傳遞進(jìn)去。
總之ndk-build 是對(duì) make 指令的封裝,并不對(duì)各個(gè)參數(shù)作處理,具體參數(shù)原封不動(dòng)地傳給 make 和Makefile。由此可見(jiàn),ndk-build,只是對(duì)make命令的一個(gè)封裝,為編譯提供一個(gè)統(tǒng)一的且適應(yīng)性更強(qiáng)的編譯入口。
(二)、技巧
二、 build-local.mk文件分析
=======================================================================================================================
一、Android.mk文件內(nèi)容分析
典型的 Android.mk 文件一般會(huì)包含如下內(nèi)容:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
下面逐一對(duì)之作分析
1、LOCAL_PATH := $(call my-dir)
宏 my-dir 定義在 difinitions.mk 文件中,其功能是獲取當(dāng)前文件所在的路徑。
2、include $(CLEAR_VARS)
在文件 build-all.mk 文件中有如下定義:
CLEAR_VARS??????????????? := $(BUILD_SYSTEM)/clear-vars.mk
build/core/clear-vars.mk 內(nèi)容如下:
# this file is included repeatedly from Android.mk files in order to clean
# the module-specific variables from the environment,
NDK_LOCAL_VARS := \
LOCAL_MODULE \
LOCAL_SRC_FILES \
LOCAL_C_INCLUDES \
LOCAL_CFLAGS \
LOCAL_CXXFLAGS \
LOCAL_CPPFLAGS \
LOCAL_LDFLAGS \
LOCAL_LDLIBS \
LOCAL_ARFLAGS \
LOCAL_CPP_EXTENSION \
LOCAL_STATIC_LIBRARIES \
LOCAL_STATIC_WHOLE_LIBRARIES \
LOCAL_SHARED_LIBRARIES \
LOCAL_MAKEFILE \
LOCAL_ALLOW_UNDEFINED_SYMBOLS \
LOCAL_ARM_MODE \
LOCAL_ARM_NEON \
LOCAL_DISABLE_NO_EXECUTE \
$(call clear-src-tags)
$(call clear-vars, $(NDK_LOCAL_VARS))
注釋中說(shuō)得很清楚,該文件的功能就是將一些模塊內(nèi)部的變量的內(nèi)容清除。最后兩條語(yǔ)句是實(shí)際的清除操作:
$(call clear-src-tags)
宏 clear-src-tags 沒(méi)有搜到其定義,不知道其確切功能是什么。不過(guò),從名字來(lái)看,應(yīng)該是對(duì)文件名的tags進(jìn)行清理的。例如編譯是為文件名加上的 .neon .arm 等等tags。
最后那條語(yǔ)句是真正清除上面羅列出的這些變量的值。從上面的列表中可以看出,都是一些 LOCAL 變量。【參考資料】
1、GNU Makefile 英文手冊(cè):http://www.gnu.org/software/make/manual/
總結(jié)
以上是生活随笔為你收集整理的android.mk ndk编译选项优化,Android NDK 编译脚本分析 之一的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 葛根汤的功效与作用、禁忌和食用方法
- 下一篇: android 强制下线功能,Andro