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 NDK 开发】Android.mk 配置静态库 ( Android Studio 配置静态库 | 配置动态库与静态库区别 | 动态库与静态库打包对比 )
文章目录 I . Android Studio 中使用 Android.mk 配置静态库 总结 II . 第三方动态库来源 III . 配置 Android.mk 构建脚本路径 IV . 预编译 第三 ...
- 【Android NDK 开发】Android.mk 配置动态库 ( Android Studio 配置动态库 | 动态库加载版本限制 | 本章仅做参考推荐使用 CMake 配置动态库 )
文章目录 I . Android Studio 中使用 Android.mk 配置动态库 总结 II . 第三方动态库来源 III . 配置 Android.mk 构建脚本路径 IV . 预编译 第三 ...
- android.mk 添加v7_在Android上以命令行方式移植FFmpeg
最近要做视频I帧提取和摘要生成的项目,在Android平台上的应用,经过调研,发现ffmpeg有很多相关功能的轮子,因此考虑将ffmpeg移植到Android平台.为了更好解耦和以及更多的文档参考,选 ...
- android.mk编译动态库,安卓之Android.mk多文件以及动态库编译
1.多文件编译 多文件编译共有两种方式: (1) 在Android.mk中一一添加 LOCAL_PATH:= $(call my-dir) #定义当前模块的相对路径 include $(CLEAR_V ...
- android.mk多个module,Android.mk中的变量的使用介绍(二)
废话不多说,直接分享,欢迎斧正. Android.mk中的变量(二) 1.LOCAL_PATH 这个变量用于给出当前文件的路径.你必须在Android.mk的开头定义.例如: LOCAL_PATH : ...
- android.mk添加静态库,Android Gradle添加静态库
看看这个 sample. >告诉编译器头部的位置(在android.ndk {}中): CFlags ="-I ${file("path / to / headers&quo ...
- android.mk是在哪儿,Android.mk基础
1.前言 Android.mk用于向编译系统描述源文件和共享库,它实际上是编译系统解析一次或多次的微小GNU makefile片段.它的语法支持将源文件分组位模块,模块是静态库.共享库或独立的可执行文 ...
- android 6.0电池优化,Android 优化——电量优化
WakeLock Android 系统本身为了优化电量的使用,会在没有操作时进入休眠状态,来节省电量.当然,为了便于开发(很多应用不可避免的希望在灭屏后还能运行一些事儿,或是要保持屏幕一直亮着--比如 ...
- 全志A33Linux连接脚本,全志A33编译脚本分析
0x00 环境说明: 分析所使用的SDK为锐尔威视的开发板的资料中的Linux-SDK 0x01 脚本分析: 顶层目录下的build.sh: buildroot/scripts/mkcommon.sh ...
最新文章
- 浏览器下载附件Content-Disposition
- 【Android UI设计与开发】第16期:滑动菜单栏(一)
- jQuery插件AjaxFileUpload文件上传实现Javascript多文件上传功能
- 目标检测--Spatial pyramid pooling in deep convolutional networks for visual recognition(PAMI, 2015)
- SAP UI5 应用开发教程之三十二 - 如何创建一个自定义 SAP UI5 控件试读版
- java登陆界面工具_javaee编写登陆界面
- DeepLearning.ai 提炼笔记(5-1)-- 循环神经网络
- 华为荣耀20和x10比较_华为和荣耀旗舰该如何选?其实懂手机的朋友只选择前者...
- Linux 命令(16)—— chattr 与 lsattr 命令
- 算法图解 各部分回忆
- python数据分析练手小项目-汽车销售偷漏纳税人识别
- 【python文件读取】加密数据的读取
- hexo的next主题换到Yelee(Yilia)
- Buildroot 构建根文件系统(Jz2440)
- Linux系统磁盘的挂入和装载
- 如果计算机电源突然断电 会导致,电脑突然断电问题
- 厦门计算机中专学校,厦门有哪些中专学校
- ADSP-21489的图形化编程详解(1:硬件的准备和软件环境的搭建)
- android studio Cannot launch SDK manager ....
- 电脑录屏没有系统声音怎么办