# . build/envsetup.sh
# lunch
# make
那么我们以此作为入口,进行解析。lunch 当前编译的产品
croot 跳转到根目录
m 编译整个源码
mm 编译当前目录所有模块,不编译依赖模块
mmm 编译指定模块,不编译依赖模块
mma 编译当前目录所有模块,编译依赖模块
mmma 编译指定模块,编译依赖模块
cgrep 对所有的c/c++文件执行grep命令
ggrep 对所有的Gradle文件执行grep命令
jgrep 对所有的java文件执行grep命令
resgrep 对所有的资源文件执行grep命令
sgrep 对所有的文件执行grep命令
godir 查找目录,并切换。
lunch 命令没有参数,打印产品列表,以供选择;如果有名称,格式为“<product_name>--< build_variant >”,其中前半部分是产品名称,后面是“build_variant”必须是eng /user/userdebug 三者之一。
lunch主要作用就是根据用户输入或选择的产品的名来设置与产品相关的环境变量。这些环境变量与产品编译相关的主要有:TARGET_PRODUCT:所编译的产品名称。
TARGET_BUILD_VARIANT:表示编译产品的类型。可能值有 eng ,user .userdebug。
TARGET_BUILD_TYPE:表示编译的类型,可选值为release和debug当选择debug版本时,系统会加入调式信息,方便追踪。
PLATFORM_VERSION_CODENAME:平台版本名称,通常是AOSP(Android OpenSource Project的缩写)
PLATFORM_ VERSION:Android平台的版本号。
TARGET_PRODUCT:所编译的产品名称。
TARGET_BUILD_VARIANT:表示编译产品的类型,可能值有 eng、user、userdebug。
TARGET_BUILD_TYPE:表示编译的类型,可选值为release和debug。当选择debug版本时,系统会加入调式信息,方便追踪。
TARGET_BUILD_APPS:编译系统时,这个变量值为空,编译单个模块时,这个模块的变量值为模块的路径。
TARGET_ARCH:编译目标的CPU架构。
TARGET_ARCH_VARIANT:编译目标的CPU架构版本。
TARGET_CPU_VARIANT:编译目标的CPU代号。
TARGET_2ND_ARCH: 编译目标的第二CPU架构。
TARGET_2ND_ARCH _VARIANT: 编译目标的第二CPU架构版本。
TARGET_2ND_CPU_VARIANT:编译目标的第二CPU代号
HOST_ARCH:编译平台架构。
HOST_OS:编译平台使用的操作系统。
HOST_OS_EXTRA:编译平台操作系统的一些额外信息,包括版本号、产品名称、代号等。
BUILD_ID:编译版本信息,可以定义公司特有标识。
OUT_DIR:编译结果输出目录。
对这些环境变量的修改,可以放到产品的定义文件中。如果只是希望临时改变这些环境变量的值,可以通过在make命令中加入参数的方式完成。如: make BUILD_ID='Android L'# Check for broken versions of make.
ifneq (1,$(strip $(shell expr $(MAKE_VERSION) \>= 3.81)))
$(warning ********************************************************************************)
$(warning * You are using version $(MAKE_VERSION) of make.)
$(warning * Android can only be built by versions 3.81 and higher.)
$(warning * see https://source.android.com/source/download.html)
$(warning ********************************************************************************)
$(error stopping)
endif
(2)、定义缺省的编译目标为“droid”。因此,命令“make”相当于“make droid”:# This is the default target. It must be the first declared target.
.PHONY: droid
DEFAULT_GOAL := droid
$(DEFAULT_GOAL): droid_targets
(3)、引入几个make文件。这里注意“-include”和“include”的区别:前者包含的文件如果不存在不会报错,后者则会报错并停止编译。# Targets that provide quick help on the build system.
include $(BUILD_SYSTEM)/help.mk
# Set up various standard variables based on configuration
# and host information.基于配置和主机信息设置各种标准变量。
include $(BUILD_SYSTEM)/config.mk
# This allows us to force a clean build - included after the config.mk
# environment setup is done, but before we generate any dependencies. This
# file does the rm -rf inline so the deps which are all done below will
# be generated correctly
include $(BUILD_SYSTEM)/cleanbuild.mk
# Include the google-specific config
-include vendor/google/build/config.mk
VERSION_CHECK_SEQUENCE_NUMBER := 6
-include $(OUT_DIR)/versions_checked.mk
(4)、检查java的版本是否是1.8或1.7,不是则会报错退出。1.8或1.7版本的java,在Linux下还要求是openJDK的版本,否则要求是Oracle的JDK版本。# Check for the correct version of java, should be 1.8 by
# default and only 1.7 if LEGACY_USE_JAVA7 is set.
ifeq ($(LEGACY_USE_JAVA7),) # if LEGACY_USE_JAVA7 == ''
required_version := "1.8.x"
required_javac_version := "1.8"
java_version := $(shell echo '$(java_version_str)' | grep '[ "]1\.8[\. "$$]')
javac_version := $(shell echo '$(javac_version_str)' | grep '[ "]1\.8[\. "$$]')
else
required_version := "1.7.x"
required_javac_version := "1.7"
java_version := $(shell echo '$(java_version_str)' | grep '^java .*[ "]1\.7[\. "$$]')
javac_version := $(shell echo '$(javac_version_str)' | grep '[ "]1\.7[\. "$$]')
endif # if LEGACY_USE_JAVA7 == ''
ifeq ($(strip $(java_version)),)
$(info ************************************************************)
$(info You are attempting to build with the incorrect version)
$(info of java.)
$(info $(space))
$(info Your version is: $(java_version_str).)
$(info The required version is: $(required_version))
$(info $(space))
$(info Please follow the machine setup instructions at)
$(info $(space)$(space)$(space)$(space)https://source.android.com/source/initializing.html)
$(info ************************************************************)
$(error stop)
endif
# Check for the current JDK.
#
# For Java 1.7/1.8, we require OpenJDK on linux and Oracle JDK on Mac OS.
requires_openjdk := false
ifeq ($(BUILD_OS),linux)
requires_openjdk := true
endif
(5)、将变量VERSIONS_CHECKED和BUILD_EMULATOR写入文件out/version_checked.mk,下次build时会重新包含这个文件。ifndef BUILD_EMULATOR
# Emulator binaries are now provided under prebuilts/android-emulator/
BUILD_EMULATOR := false
endif
$(shell echo 'VERSIONS_CHECKED := $(VERSION_CHECK_SEQUENCE_NUMBER)' \
> $(OUT_DIR)/versions_checked.mk)
$(shell echo 'BUILD_EMULATOR ?= $(BUILD_EMULATOR)' \
>> $(OUT_DIR)/versions_checked.mk)
endif
(6)、再包含进3个mk文件:# Bring in standard build system definitions.
include $(BUILD_SYSTEM)/definitions.mk
# Bring in dex_preopt.mk
include $(BUILD_SYSTEM)/dex_preopt.mk
# The pdk (Platform Development Kit) build
include build/core/pdk_config.mk
(7)、如果变量ONE_SHOT_MAKEFILE的值不为空,将它定义的文件包含进来。当编译一个单独的模块时,ONE_SHOT_MAKEFILE的值会设为模块的make文件路径。如果值ONE_SHOT_MAKEFILE的值为空,说明正在编译整个系统,因此,调用findleayes.py脚本搜索系统里所有Android.mk文件并将它们包含进来。 (8)、根据编译类型来设置属性ro.secure的值。 (9)、包含进post_clean.mk和legacy_prebuilts.mk脚本。根据legacy_prebuilds.mk中定义的变量GRANDFATHERED_ALL_PREBUILT检查是由有不在这个列表中的prebuilt模块。如果有则报错退出。# Now with all Android.mks loaded we can do post cleaning steps.
include $(BUILD_SYSTEM)/post_clean.mk
ifeq ($(stash_product_vars),true)
$(call assert-product-vars, __STASHED)
endif
include $(BUILD_SYSTEM)/legacy_prebuilts.mk
ifneq ($(filter-out $(GRANDFATHERED_ALL_PREBUILT),$(strip $(notdir $(ALL_PREBUILT)))),)
$(warning *** Some files have been added to ALL_PREBUILT.)
$(warning *)
$(warning * ALL_PREBUILT is a deprecated mechanism that)
$(warning * should not be used for new files.)
$(warning * As an alternative, use PRODUCT_COPY_FILES in)
$(warning * the appropriate product definition.)
$(warning * build/target/product/core.mk is the product)
$(warning * definition used in all products.)
$(warning *)
$(foreach bad_prebuilt,$(filter-out $(GRANDFATHERED_ALL_PREBUILT),$(strip $(notdir $(ALL_PREBUILT)))),$(warning * unexpected $(bad_prebuilt) in ALL_PREBUILT))
$(warning *)
$(error ALL_PREBUILT contains unexpected files)
endif
(10)、计算哪些模块应该在本次编译之后引入。 (11)、包含Makefile文件。至此,所有的编译文件都包含进来了。# build/core/Makefile contains extra stuff that we don't want to pollute this
# top-level makefile with. It expects that ALL_DEFAULT_INSTALLED_MODULES
# contains everything that's built during the current make, but it also further
# extends ALL_DEFAULT_INSTALLED_MODULES.
ALL_DEFAULT_INSTALLED_MODULES := $(modules_to_install)
include $(BUILD_SYSTEM)/Makefile
modules_to_install := $(sort $(ALL_DEFAULT_INSTALLED_MODULES))
(12)、定义系统的编译目标。下面详细介绍。# Building a full system-- the default is to build droidcore
droid_targets: droidcore dist_files
# Build files and then package it into the rom formats
.PHONY: droidcore
droidcore: files \
systemimage \
$(INSTALLED_BOOTIMAGE_TARGET) \
$(INSTALLED_RECOVERYIMAGE_TARGET) \
$(INSTALLED_USERDATAIMAGE_TARGET) \
$(INSTALLED_CACHEIMAGE_TARGET) \
$(INSTALLED_VENDORIMAGE_TARGET) \
$(INSTALLED_FILES_FILE) \
# All the droid stuff, in directories
.PHONY: files
files: prebuilt \
$(modules_to_install) \
$(INSTALLED_ANDROID_INFO_TXT_TARGET)
.PHONY: prebuilt
prebuilt: $(ALL_PREBUILT)
在droid的依赖目标中,droidcore、files和prebuilt是中间目标,其余目标的作用介绍如下: 目标说明dist_file用来复制文件到out/dist目录systemimage用来产生system.img$(INSTALLED_BOOTIMAGE_TARGET)用来产生boot.img$(INSTALLED_RECOVERYIMAGE_TARGET)用来产生recovery.img$(INSTALLED_USERDATAIMAGE_TARGET)用来产生userdata.img$(INSTALLED_CACHEIMAGE_TARGET)用来产生cache.img$(INSTALLED_VENDORIMAGE_TARGET)用来产生vendor.img$(INSTALLED_FILES_FILE)用来产生名为installed-files.txt文件,该文件将会存放在out/target/product/<product_name>下。文件的内容是当前产品配置将要安装的所有文件列表。$(modules_to_install)modules_to_install变量是当前产品配置下所有将要安装的模块的列表。因此,该目标将导致所有这些模块的编译。$(INSTALLED_ANDROID_INFO_TXT_TARGET)用来产生名为android_info.txt文件,该文件将会存放在out/target/product/<product_name>下。文件内容是当前产品的设备信息。$(ALL_PREBUILT)用来产生所有在变量GRANDFATHERED_ALL_PREBUILT中的文件。 除了droid及其相关目标,Build系统里还有很多可以独立使用的目标。 目标说明make clean清除所有编译结果,相当于“rm -rf out”make snod快速打包system.img。make help打印build系统简单的帮助信息。make sdk生成Android SDK。make framework编译出所有framework的jar包make services编译出系统服务及相关的模块。add_lunch_combo pollux-user
add_lunch_combo pollux-userdebug
add_lunch_combo pollux-eng
产品名称串的格式是<produce_name>-<goal>,前半部分是产品名称,后半部分是编译类型。产品的编译类型有三种:eng、user、userdebug。PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/pollux.mk
vendorsetup.sh文件中加入“选择列表”的是pollux,因此,实际能选用的文件只用pollux.mk。Boot header(文件头)
1 page
Kernel(gzip压缩的映像)
n pages
Ramdisk(映像)
m pages
Second stage(载入器程序)
o pages
boot.img是一种Android自定义的文件格式。该格式包括了一个2*1024大小的文件头,后面是用gzip压缩过的kernel镜像,在后面是ramdisk映像,最后是一个加载器程序。相当于一个小型文本界面的Linux系统,有自己的内核和文件系统,作用是恢复或升级系统。