Chinaunix首页 | 论坛 | 博客
  • 博客访问: 866101
  • 博文数量: 189
  • 博客积分: 4310
  • 博客等级: 上校
  • 技术积分: 1925
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-27 08:56
文章分类

全部博文(189)

文章存档

2015年(1)

2013年(2)

2012年(1)

2011年(39)

2010年(98)

2009年(48)

分类: LINUX

2011-08-08 14:43:19

解析下android/build/envsetup.sh下的命令get_build_var

export TARGET_PRODUCT=harmony
比如get_build_var TARGET_DEVICE
那么build/core/dumpvar.mk将被执行
dumpvar_goals := \
    $(strip $(patsubst dumpvar-%,%,$(filter dumpvar-%,$(MAKECMDGOALS)))) // 取出dumpvar-开头的所有命令行
ifdef dumpvar_goals

  ifneq ($(words $(dumpvar_goals)),1) // 当前只支持一个var的查询
    $(error Only one "dumpvar-" goal allowed. Saw "$(MAKECMDGOALS)")
  endif

  # If the goal is of the form "dumpvar-abs-VARNAME", then
  # treat VARNAME as a path and return the absolute path to it.
  absolute_dumpvar := $(strip $(filter abs-%,$(dumpvar_goals)))
  ifdef absolute_dumpvar
    dumpvar_goals := $(patsubst abs-%,%,$(dumpvar_goals))
    DUMPVAR_VALUE := $(PWD)/$($(dumpvar_goals))
    dumpvar_target := dumpvar-abs-$(dumpvar_goals)
  else
#//////////////////////////////////////////////
$(info xxxxxxxxxxx)
$(info $(TARGET_DEVICE)) // 其实这里变量TARGET_DEVICE早在前面赋值了,所以我们可以直接在这里查看到
$(info xxxxxxxxxxx)
#//////////////////////////////////////////////
    DUMPVAR_VALUE := $($(dumpvar_goals))
    dumpvar_target := dumpvar-$(dumpvar_goals)
  endif

.PHONY: $(dumpvar_target)
$(dumpvar_target):
    @echo $(DUMPVAR_VALUE) // 简单的显示一下而已,赋值不在dumpvar.mk中完成

那TARGET_DEVICE什么时候得到的值呢,又是从哪里得到的呢,我们来详细的看看[luther.gliethttp]

首先定义产品的TARGET_PRODUCT环境变量
build/core/main.mk
=> include $(BUILD_SYSTEM)/config.mk也就是build/core/config.mk
==> build/core/envsetup.mk

ifeq ($(TARGET_PRODUCT),) // 如果没有定义TARGET_PRODUCT,那么默认generic
ifeq ($(TARGET_SIMULATOR),true)
TARGET_PRODUCT := sim
else
TARGET_PRODUCT := generic
endif
endif

然后根据TARGET_PRODUCT查找配置AndroidProducts.mk
build/core/product_config.mk
=> build/core/product.mk文件中的2个function
即$(call import-products, $(get-all-product-makefiles))
其中get-all-product-makefiles将以字符串空格分割的方式
返回vendor/*/目录下的所有AndroidProducts.mk文件和build/target/product/AndroidProducts.mk


# the variant -- the set of files that are included for a build
ifeq ($(strip $(TARGET_BUILD_VARIANT)),) // 如果没有定义TARGET_BUILD_VARIANT,那么默认eng
TARGET_BUILD_VARIANT := eng
endif

define import-products
$(call import-nodes,PRODUCTS,$(1),$(_product_var_list))
endef

define get-all-product-makefiles
$(call get-product-makefiles,$(_find-android-products-files))
endef

后面的内容下面的一篇文章讲得很好,直接看下面这个文章即可.

----------------------------------------

转自:

今天有时间小看一下Android 的Makefile, 终于稍有明白Android 编译系统是如何通过环境变量 TARGET_PRODUCT 来决定编译定制product.

首先, 编译Android 代码 通常情况下使用:

# make showcommands

这实际上等价于下面的完整命令 (具体参见 build/core/envsetup.mk )

# TARGET_ARCH=arm TARGET_PRODUCT=generic TARGET_BUILD_TYPE=release make showcommands

可见,默认情况下编译系统认为TARGET_PRODUCT 是generic 的

那如何编译特定产品的Android呢?

这就需要查看Android Makefile是如何解析环境变量TARGET_PRODUCT的。

Android Makefile 的引用关系是这样的

Makefile  -> build/core/main.mk -> build/core/config.mk -> build/core/envsetup.mk -> build/core/product_config.mk

在build/core/product_config.mk 中编译系统首先调用 build/core/product.mk中定义的函数get-all-product-makefiles ,来

遍历整个vendor 的子目录, 找到vendor下所有的 AndroidProducts.mk, 不同子目录下的AndroidProducts.mk 中定义了不同的 PRODUCT_NAME, PRODUCT_DEVICE 等信息,(我们也可以通过 打开build/core/product_config.mk  中的#$(dump-products) 语句使控制台编译的时候输出所有product 的信息)  , 接着build/core/product_config.mk 会调用resolve-short-product-name 将TARGET_PRODUCT匹配的AndroidProducts.mk 中定义的 PRODUCT_DEVICE 赋值给TARGET_DEVICE。

有了这个TARGET_DEVICE, 再回到 build/core/config.mk,

会include $(TARGET_DEVCIE)/BoardConfig.mk

board_config_mk := \
 $(strip $(wildcard \
  $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
  vendor/*/$(TARGET_DEVICE)/BoardConfig.mk \
 ))

 include $(board_config_mk)

而这个配置文件BoardConfig.mk 决定了目标系统编译属性,比如使用ALSA还是不是 GENERIC_AUDIO 等等

另外在这里TARGET_DEVICE 宏也决定了TARGET_DEVICE_DIR, 因为TARGET_DEVICE_DIR 取的是上面提到的BoardConfig.mk 的路径。

TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))

当然Android 的Ob目标输出也是由TARGET_DEVICE决定,见build/core/envsetup.mk

TARGET_OUT_ROOT_release := $(OUT_DIR)/target
TARGET_OUT_ROOT_debug := $(DEBUG_OUT_DIR)/target
TARGET_OUT_ROOT := $(TARGET_OUT_ROOT_$(TARGET_BUILD_TYPE))

TARGET_PRODUCT_OUT_ROOT := $(TARGET_OUT_ROOT)/product

PRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE)

再回到 build/core/main.mk, 编译系统接着做的一个件事情是,遍历所有字目录,找到所有Android.mk文件,并将这些Android.mk文件include 进来

#
# Typical build; include any Android.mk files we can find.
#

subdir_makefiles := \
 $(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk)

include $(subdir_makefiles)

我们再来看其中的

./build/target/board/Android.mk

,对了它引用了

include $(TARGET_DEVICE_DIR)/AndroidBoard.mk

由上面TARGET_DEVICE_DIR的定义,这下又进入了

vendor 下TARGET_DEVICE指向的目录了,这个mk文件中定义了特定Product需要编译和安装app 和 script.

阅读(6103) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~