版权信息:本文为本人原创,欢迎转载,但请著明出处,并保留本版权信息。

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 编译脚本分析 之一相关推荐

  1. 【Android NDK 开发】Android.mk 配置静态库 ( Android Studio 配置静态库 | 配置动态库与静态库区别 | 动态库与静态库打包对比 )

    文章目录 I . Android Studio 中使用 Android.mk 配置静态库 总结 II . 第三方动态库来源 III . 配置 Android.mk 构建脚本路径 IV . 预编译 第三 ...

  2. 【Android NDK 开发】Android.mk 配置动态库 ( Android Studio 配置动态库 | 动态库加载版本限制 | 本章仅做参考推荐使用 CMake 配置动态库 )

    文章目录 I . Android Studio 中使用 Android.mk 配置动态库 总结 II . 第三方动态库来源 III . 配置 Android.mk 构建脚本路径 IV . 预编译 第三 ...

  3. android.mk 添加v7_在Android上以命令行方式移植FFmpeg

    最近要做视频I帧提取和摘要生成的项目,在Android平台上的应用,经过调研,发现ffmpeg有很多相关功能的轮子,因此考虑将ffmpeg移植到Android平台.为了更好解耦和以及更多的文档参考,选 ...

  4. android.mk编译动态库,安卓之Android.mk多文件以及动态库编译

    1.多文件编译 多文件编译共有两种方式: (1) 在Android.mk中一一添加 LOCAL_PATH:= $(call my-dir) #定义当前模块的相对路径 include $(CLEAR_V ...

  5. android.mk多个module,Android.mk中的变量的使用介绍(二)

    废话不多说,直接分享,欢迎斧正. Android.mk中的变量(二) 1.LOCAL_PATH 这个变量用于给出当前文件的路径.你必须在Android.mk的开头定义.例如: LOCAL_PATH : ...

  6. android.mk添加静态库,Android Gradle添加静态库

    看看这个 sample. >告诉编译器头部的位置(在android.ndk {}中): CFlags ="-I ${file("path / to / headers&quo ...

  7. android.mk是在哪儿,Android.mk基础

    1.前言 Android.mk用于向编译系统描述源文件和共享库,它实际上是编译系统解析一次或多次的微小GNU makefile片段.它的语法支持将源文件分组位模块,模块是静态库.共享库或独立的可执行文 ...

  8. android 6.0电池优化,Android 优化——电量优化

    WakeLock Android 系统本身为了优化电量的使用,会在没有操作时进入休眠状态,来节省电量.当然,为了便于开发(很多应用不可避免的希望在灭屏后还能运行一些事儿,或是要保持屏幕一直亮着--比如 ...

  9. 全志A33Linux连接脚本,全志A33编译脚本分析

    0x00 环境说明: 分析所使用的SDK为锐尔威视的开发板的资料中的Linux-SDK 0x01 脚本分析: 顶层目录下的build.sh: buildroot/scripts/mkcommon.sh ...

最新文章

  1. 浏览器下载附件Content-Disposition
  2. 【Android UI设计与开发】第16期:滑动菜单栏(一)
  3. jQuery插件AjaxFileUpload文件上传实现Javascript多文件上传功能
  4. 目标检测--Spatial pyramid pooling in deep convolutional networks for visual recognition(PAMI, 2015)
  5. SAP UI5 应用开发教程之三十二 - 如何创建一个自定义 SAP UI5 控件试读版
  6. java登陆界面工具_javaee编写登陆界面
  7. DeepLearning.ai 提炼笔记(5-1)-- 循环神经网络
  8. 华为荣耀20和x10比较_华为和荣耀旗舰该如何选?其实懂手机的朋友只选择前者...
  9. Linux 命令(16)—— chattr 与 lsattr 命令
  10. 算法图解 各部分回忆
  11. python数据分析练手小项目-汽车销售偷漏纳税人识别
  12. 【python文件读取】加密数据的读取
  13. hexo的next主题换到Yelee(Yilia)
  14. Buildroot 构建根文件系统(Jz2440)
  15. Linux系统磁盘的挂入和装载
  16. 如果计算机电源突然断电 会导致,电脑突然断电问题
  17. 厦门计算机中专学校,厦门有哪些中专学校
  18. ADSP-21489的图形化编程详解(1:硬件的准备和软件环境的搭建)
  19. android studio Cannot launch SDK manager ....
  20. 电脑录屏没有系统声音怎么办

热门文章

  1. 选择IT事业,意味着终身学习
  2. 在.Net项目中使用Redis作为缓存服务
  3. [转]【高并发】高并发秒杀系统架构解密,不是所有的秒杀都是秒杀!
  4. 【ArcGIS遇上Python】三种利用Python批量处理地理数据的方法——以栅格数据投影转换为例
  5. Matlab三种归一化方法
  6. 剑指offer之求两个链表的第一个公共节点
  7. Android开发之运行客户的Demo拿不到数据
  8. linux c之使用共享内存实现进程间通信
  9. 栈与队列之用java实现队列
  10. Android之玩转MPAndroidChart让(折线图、柱形图、饼状图、散列图、雷达图)优雅的舞动