已开通新的博客,后续文字都会发到新博客
https://www.0xforee.top
Android 编译系统解析系列文档
编译系统入口envsetup.sh解析
解析lunch的执行过程以及make执行过程中include文件的顺序
关注一些make执行过程中的几个关键点
对一些独特的语法结构进行解析
这篇文章的主要内容我们来分析关于模块配置文件Android.mk加载的一些关键的知识点
躲不开的背景知识"mm"与"mmm"
在分析模块配置文件Android.mk文件的加载过程之前,我们需要先了解一段背景知识,那就是Android.mk的使用情景是什么样的?
还记得我们在前边分析lunch的时候提到的源码的全编与模块编译吗?
控制全编与模块编译的命令就在envsetup.sh文件中定义,其中全编直接运行make,模块单编需要用到mm与mmm两条命令,定义如下
function findmakefile()
{
TOPFILE=build/core/envsetup.mk
local HERE=$PWD
T=
while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
T=`PWD= /bin/pwd`
if [ -f "$T/Android.mk" ]; then
echo $T/Android.mk
\cd $HERE
return
fi
\cd ..
done
\cd $HERE
}
function mm()
{
local T=$(gettop)
local DRV=$(getdriver $T)
# If we're sitting in the root of the build tree, just do a
# normal make.
if [ -f build/core/envsetup.mk -a -f Makefile ]; then
$DRV make $@
else
# Find the closest Android.mk file.
local M=$(findmakefile)
local MODULES=
local GET_INSTALL_PATH=
local ARGS=
# Remove the path to top as the makefilepath needs to be relative
local M=`echo $M|sed 's:'$T'/::'`
if [ ! "$T" ]; then
echo "Couldn't locate the top of the tree. Try setting TOP."
elif [ ! "$M" ]; then
echo "Couldn't locate a makefile from the current directory."
else
for ARG in $@; do
case $ARG in
GET-INSTALL-PATH) GET_INSTALL_PATH=$ARG;;
esac
done
if [ -n "$GET_INSTALL_PATH" ]; then
MODULES=
ARGS=GET-INSTALL-PATH
else
MODULES=all_modules
ARGS=$@
fi
ONE_SHOT_MAKEFILE=$M $DRV make -C $T -f build/core/main.mk $MODULES $ARGS
fi
fi
}
先看mm命令,如果运行这条命令的路径为TOP目录,那么就等价于直接使用make命令
如果不是,我们就以当前目录为基点,递归向上查找距离最近的Android.mk文件,这个查找的过程在findmakefile()
函数中定义
Android编译系统在使用mm命令的时候为我们提供了一个参数,可以方便我们打印出所要编译模块的最终安装路径,这个参数就是GET-INSTALL-PATH
,
- 如果编译系统在检查到正在使用mm时加了这个参数,我们就不执行编译的操作,只打印这个参数的值
这个逻辑的实现其实只是将GET-INSTALL-PATH
定义为了一个target,我们使用mm时,会将这个target传进去,从而调用到这个target定义的命令,我们后边遇到模块解析代码的时候就会看到这个target相关代码
- 如果没有这个参数,我们就指定编译全部的模块(all_modules),然后将mm后边的参数全部作为MAKEGOALS传入
以上就是mm执行的全部过程,有三点需要注意:
- $DRV,这个变量的作用是加一些静态分析的选项以及路径
- ARG参数的添加可以让我们使用-B这样的make自带的参数
- ONE_SHOT_MAKEFILE是区别全编与模块编译的关键变量
对于mmm函数&#