光伏发电补贴政策缙云:Android NDK 编译脚本分析 之一

来源:百度文库 编辑:中财网 时间:2024/05/09 22:31:36
        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/2、GNU Makefile 中文手册:http://xhbdahai.cublog.cn/