当前位置: 代码迷 >> Android >> 深入显出Android makefile(2)-LOCAL_PATH
  详细解决方案

深入显出Android makefile(2)-LOCAL_PATH

热度:563   发布时间:2016-05-01 12:20:36.0
深入浅出Android makefile(2)--LOCAL_PATH

一、说明
上文我们对acp的Android.mk文件做了一个大致的描述,使得大家对Android.mk文件有了一个初步的认识,下面我们就重点分析下第一行:LOCAL_PATH:= $(call my-dir)

二、LOCAL_PATH
有人就问了,在本Android.mk中又没有使用到LOCAL_PATH,为什么要定义这么一个变量呢?为什么规定必须放在所有的include $(CLEAR_VARS)之前呢?

在Android.mk中我们发现有LOCAL_SRC_FILES :=?acp.的定义,NDK文件中对LOCAL_SRC_FILES?的说明如下:
This is a list of source files that will be built for your module.?Only list the files that will be passed to a compiler, since the?build system automatically computes dependencies for you.
Note that?source files names are all relative to LOCAL_PATH and?you can use path components.
因此在定义LOCAL_SRC_FILES?时已经间接的使用到了LOCAL_PATH变量,即定义LOCAL_SRC_FILES是用的基于当前路径的相对路径。

我们接着看看为什么LOCAL_PATH的定义必须要放到所有的include $(CLEAR_VARS)之前。
LOCAL_PATH通过调用my-dir函数来获取当前的路径,my-dir函数的定义位于core/definitions.mk文件:
# Figure out where we are.define my-dir$(strip \  $(eval md_file_ := $$(lastword $$(MAKEFILE_LIST))) \                         #从MAKEFILE_LIST中获取到当前的makefile  $(if $(filter $(CLEAR_VARS),$(md_file_)), \    $(error LOCAL_PATH must be set before including $$(CLEAR_VARS)) \   , \    $(patsubst %/,%,$(dir $(md_file_))) \   ) \)endef
请注意,这里明确的说明了LOCAL_PATH的定义必须要放在任何include $(CLEAR_VARS)语句之前,如果不这么做的话,编译就直接报错,停止不干了。

可是它是怎么判断LOCAL_PATH的定义是在任何include $(CLEAR_VARS)语句之前呢,我们看到有这么一句话:
$(if $(filter $(CLEAR_VARS),$(md_file_))
?这个判断语句是个关键,我们先看看CLEAR_VARS变量的定义

三、CLEAR_VARS
在build/core/config.mk中有如下明确的定义:
CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
BUILD_SYSTEM的定义在build/core/main.mk文件中:
BUILD_SYSTEM := $(TOPDIR)build/core
BUILD_SYSTEM := $(TOPDIR)build/core
紧接着:
TOPDIR :=
即TOPDIR为android源码的根目录BUILD_SYSTEM=build/core所以CLEAR_VARS变量的值就为build/core/clear_vars.mk,当然这个也是相对于Android源码根路径。
得到了CLEAR_VARS变量的值,我们再回到my-dir函数中。

四、my-dir
根据gnu make定义,gnu make会自动将所有读取的makefile路径都会加入到该变量中,而且是按照读取的先后顺序添加。

那么,在运行本makefile文件时,$(MAKEFILE_LIST)字符串中最后一个makefile肯定是最后读取的makefile,即$(lastword $(MAKEFILE_LIST))则会返回build/tools/acp/Android.mk,此字符串经过$(eval md_file_ := $$(lastword $$(MAKEFILE_LIST))运算,赋值给了临时变量md_file_。

判断md_file_中是否包含CLEAR_VARS变量的值$(if $(filter $(CLEAR_VARS),$(md_file_)),肯定也就会返回失败,再通过$(patsubst %/,%,$(dir $(md_file_)))函数,则会得到当前路径,即build/tools/acp

但是为什么LOCAL_PATH必须要在任何including $(CLEAR_VARS))之前定义呢,因为include $(CLEAR_VARS)之后,$(MAKEFILE_LIST)字符串中就会添加
$(BUILD_SYSTEM)/clear_vars.mk,此时?$$(lastword $$(MAKEFILE_LIST))就会返回$(BUILD_SYSTEM)/clear_vars.mk,同样,$(patsubst %/,%,$(dir $(md_file_)))也就会返回$(BUILD_SYSTEM)的值build/core,而不是当前的路径build/tools/acp。

这么一来得到的LOCAL_PATH的值就是错误的值,因此,LOCAL_PATH必须要在任何including $(CLEAR_VARS))之前定义。
  相关解决方案