android.mk ndk编译选项优化,Android NDK 编译脚本分析 之一
版權信息:本文為本人原創,歡迎轉載,但請著明出處,并保留本版權信息。
Android NDK編譯腳本編寫起來還是是比較簡單條理的,然而它的語法和傳統的linux GNU?Make編譯腳本的編寫似乎有很大的不同,這讓習慣了GNU Makefile的用戶很不習慣。有許多人會用它,但對其工作原理卻不理解,筆者甚至一度誤認為那是一套全新腳本語言。我將在后文中對這一編譯管理系統做一些分析,試著分析一下它和傳統GNU Makefile的關系。
本文假設您已經擁有 Linux命令和GNU Makefile的基礎知識,當然您也可以邊閱讀,邊查找參考相關的知識。參考資料2是徐海兵先生整理的 GNU Makefile 中文手冊,推薦英文不太好的朋友拿來作為參考。
這篇文章是對自己前段時間所學知識的一個記錄整理,以期與大家互相交流,希望朋友們不要吝于來信,指出本文的錯漏之處或者你們不同理解(絕非客氣,真的期望能收到您的信件,我的郵箱 techres#163.com,請把 # 換成 @)。
====================================================================
Android NDK 的編譯腳本系統,實際上并不是什么新東西,就是對 GNU MakeFile 系統的封裝。Android NDK?自帶了很多 .mk? 文件(保存在ndk的 NDK_ROOT/build 目錄中),文件中預定義了很多 Make? 腳本函數和變量,以供用戶編寫自己的編譯腳本時使用。另外,NDK為所有應用統一提供了一個固定的編譯入口--即大家熟悉的ndk-build。
我們首先從每個應用編譯時都需要用到的編譯入口開始分析。
一、ndk-build分析
(一)、腳本內容分析
該文件存在于ndk安裝根目錄中,實際上是一個 shell 腳本。其有效內容如下:
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 "$@"
下面我們對這些有效代碼逐一進行分析:
PROGDIR=`dirname $0`
PROGDIR=`cd $PROGDIR && pwd`
在GNU makefile中,兩個反引號相當于 shell ?函數,反引號括起來的內容相當于 shell 函數的參數。而shell函數的功能就是調用操作系統的命令。
PROGDIR=`dirname $0`
linux 命令 dirname, 功能是獲取后面參數的路徑。例如:
#dirname ../../../ndk-build
執行的結果是:"../../.."。順便提一下,這里不能用pwd命令,pwd 命令,是獲得當前路徑,獲取的是當前路徑的絕對路徑。所以,上面兩條語句的結果就是在 PROGDIR 變量中保存 ndk-build 所在的路徑。有了這兩條語句之后,就可以在任何位置執行 ndk-build ,而不必非要在 ndk 根目錄中執行。
再之后的兩段語句,是用來確定不同平臺下正確的 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
最后一條語句,是調用:
$GNUMAKE -f $PROGDIR/build/core/build-local.mk "$@"
這是真正開始執行 make ,指定 Makefile 為 build-local.mk 文件。同時,將 ndk-build 的所有參數($@)原封不動地都傳遞進去。
總之ndk-build 是對 make 指令的封裝,并不對各個參數作處理,具體參數原封不動地傳給 make 和Makefile。由此可見,ndk-build,只是對make命令的一個封裝,為編譯提供一個統一的且適應性更強的編譯入口。
(二)、技巧
二、 build-local.mk文件分析
=======================================================================================================================
一、Android.mk文件內容分析
典型的 Android.mk 文件一般會包含如下內容:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
下面逐一對之作分析
1、LOCAL_PATH := $(call my-dir)
宏 my-dir 定義在 difinitions.mk 文件中,其功能是獲取當前文件所在的路徑。
2、include $(CLEAR_VARS)
在文件 build-all.mk 文件中有如下定義:
CLEAR_VARS??????????????? := $(BUILD_SYSTEM)/clear-vars.mk
build/core/clear-vars.mk 內容如下:
# 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))
注釋中說得很清楚,該文件的功能就是將一些模塊內部的變量的內容清除。最后兩條語句是實際的清除操作:
$(call clear-src-tags)
宏 clear-src-tags 沒有搜到其定義,不知道其確切功能是什么。不過,從名字來看,應該是對文件名的tags進行清理的。例如編譯是為文件名加上的 .neon .arm 等等tags。
最后那條語句是真正清除上面羅列出的這些變量的值。從上面的列表中可以看出,都是一些 LOCAL 變量。【參考資料】
1、GNU Makefile 英文手冊:http://www.gnu.org/software/make/manual/
總結
以上是生活随笔為你收集整理的android.mk ndk编译选项优化,Android NDK 编译脚本分析 之一的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 葛根汤的功效与作用、禁忌和食用方法
- 下一篇: android 强制下线功能,Andro