Android学习笔记之编译系统(一)编译框架一

转载请注明出处:http://blog.csdn.net/droyon/article/details/8639773

最近在读android内核剖析,将一些心得记录下来,方便自己查阅。


在android源代码文件夹下存在build文件夹,,他下面的文件构成了编译系统,该目录下的make脚本和shell脚本共同组成了Androd的编译环境。

在我们编译系统时,我们一般先执行:

. build/envsetup.sh 
make
make后面可以跟上参数,参数包括:产品名,模块名,sdk。

make 后面无论跟的是产品名还是模块名,那么首先编译系统要认识。产品和模块名如何要让android系统认识,是在android编译系统定义的,以及输出路径out(out下有两个目录,target是最终的输出目标,host是在编译sdk,或者cts时,生成的供pc使用的一些工具)目录的指定。android编译系统实现在build文件夹下,那里存放了一系列的*.mk文件。每个子项目目录下都有Android.mk,在文件中定义了子项目要生成的目标文件,是apk还是jar包。

1、关于Android.mk的语法:

LOCAL_PATH:指定了子项目的绝对路径,一般通过编译系统中定义的call-dir获取。

LOCAL_PATH:= $(call my-dir)
LOCAL_MODULE_TAGS:指定子项目的标签,标签包括:user、eng、userdebug、optional。

LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES:指定子项目所包含的所有源文件。可以通过函数获得,如下所示。
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
        src/com/android/music/IMediaPlaybackService.aidl
LOCAL_PACKAGE_NAME:指定项目名称,这个名称就是子项目名。对于c++项目使用LOCAL_MODULE。

LOCAL_PACKAGE_NAME := Music
LOCAL_MODULE:= reference-ril
BUILE_PACKAGE:代表编译生成apk,还有BUILE_HOST_EXECUTABLE,BUILE_HOST_STATIC_LIBRARY

2、build编译系统文件加载顺序

执行make命令,会加载根目录中的Makefile,在这个文件中,会加载buile/core/main.mk,在这个文件中定义了,make命令不跟参数,所执行的情况。

.PHONY: droid
DEFAULT_GOAL := droid
$(DEFAULT_GOAL):
在执行main.mk过程中,会包含build/core/config.mk,在这个文件中,定义了一系列路径变量:

SRC_HEADERS := \
        $(TOPDIR)system/core/include \
        $(TOPDIR)hardware/libhardware/include \
        $(TOPDIR)hardware/libhardware_legacy/include \
        $(TOPDIR)hardware/ril/include \
        $(TOPDIR)dalvik/libnativehelper/include \
        $(TOPDIR)frameworks/base/include \
        $(TOPDIR)frameworks/base/opengl/include \
    $(TOPDIR)frameworks/base/native/include \
        $(TOPDIR)external/skia/include
SRC_HOST_HEADERS:=$(TOPDIR)tools/include
SRC_LIBRARIES:= $(TOPDIR)libs
SRC_SERVERS:= $(TOPDIR)servers
SRC_TARGET_DIR := $(TOPDIR)build/target
SRC_API_DIR := $(TOPDIR)frameworks/base/api
在config.mk文件中会包含pathmap.mk文件,在这个文件中也会定义一系列的framework层常量,很重要,在后面会引用

FRAMEWORKS_BASE_SUBDIRS := \
        $(addsuffix /java, \
            core \
            graphics \
            location \
            media \
            drm \
            opengl \
            sax \
            telephony \
            wifi \
            keystore \
            icu4j \
            voip \
         )
FRAMEWORKS_BASE_JAVA_SRC_DIRS := \
        $(addprefix frameworks/base/,$(FRAMEWORKS_BASE_SUBDIRS))
等,这个常量定义了编译到framework.jar的源文件目录,如果你修改了android framework层的代码,新建了目录,如果目录不再第一段代码中,那么可能编译不到framework.jar中。

然后继续config.mk的执行。然后config.mk会定义一系列的编译宏,在Android.mk中最后使用的那个命令include $(BUILD_PACKAGE)

BUILD_COMBOS:= $(BUILD_SYSTEM)/combo

CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk
BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk
BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
BUILD_RAW_STATIC_LIBRARY := $(BUILD_SYSTEM)/raw_static_library.mk
BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
BUILD_RAW_EXECUTABLE:= $(BUILD_SYSTEM)/raw_executable.mk
BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
BUILD_PHONY_PACKAGE:= $(BUILD_SYSTEM)/phony_package.mk
BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk
BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk
BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk
BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk
BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk
BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk
BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk
BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk
在这里面有我们熟悉的BUILD_PACKAGE,代表编译源文件成为apk。

再往下config.mk文件包含buildspec.mk在这个文件中会定义我们要编译的产品的名字。(如有错误请指正)文件路径为:根目录/buildspec.mk
再往下cofig.mk文件会包含envsetup.mk,主要是环境的配置,例如apk安装路径常量,设置目标输出路径。

OUT_DIR := $(TOPDIR)out

TARGET_SYSLOADER_SYSTEM_OUT := $(TARGET_SYSLOADER_OUT)/root/system

TARGET_INSTALLER_OUT := $(PRODUCT_OUT)/installer
TARGET_INSTALLER_DATA_OUT := $(TARGET_INSTALLER_OUT)/data

其中会包含product_config.mk文件,在这个文件中,它会包含product.mk文件,在product.mk文件中,会检测device 、verndor、build/target/product目录下所有的AndroidProduct.mk文件。

define _find-android-products-files
$(shell test -d device && find device -maxdepth 6 -name AndroidProducts.mk) \
  $(shell test -d vendor && find vendor -maxdepth 6 -name AndroidProducts.mk) \
  $(SRC_TARGET_DIR)/product/AndroidProducts.mk
endef
文件目录深度为6级。

然后在product_config.mk文件中,调用自身函数将product加入进来。

ifneq ($(strip $(TARGET_BUILD_APPS)),)
  # An unbundled app build needs only the core product makefiles.
  $(call import-products,$(call get-product-makefiles,\
      $(SRC_TARGET_DIR)/product/AndroidProducts.mk))
else
  # Read in all of the product definitions specified by the AndroidProducts.mk
  # files in the tree.
  #
  #TODO: when we start allowing direct pointers to product files,
  #    guarantee that they're in this list.
  $(call import-products, $(get-all-product-makefiles))
endif # TARGET_BUILD_APPS
到这里product_config.mk结束,继续config.mk文件的执行,也就是上面所的设置环境变量,设置OUT_DIR := $(TOPDIR)out,等。

这样envsetup.mk文件就执行结束了。继续执行config.mk文件,再往下config.mk文件会加载每一个product下的BoardConfig.mk文件。

board_config_mk := \
        $(strip $(wildcard \
                $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
                device/*/$(TARGET_DEVICE)/BoardConfig.mk \
                vendor/*/$(TARGET_DEVICE)/BoardConfig.mk \
        ))
ifeq ($(board_config_mk),)
  $(error No config file found for TARGET_DEVICE $(TARGET_DEVICE))
endif
ifneq ($(words $(board_config_mk)),1)
  $(error Multiple board config files for TARGET_DEVICE $(TARGET_DEVICE): $(board_config_mk))
endif
include $(board_config_mk
BoardCOnfig.mk会加载一些属性,这些属性会加入到系统属性中。

最后config.mk文件会设置工具命令宏。

AAPT := $(HOST_OUT_EXECUTABLES)/aapt$(HOST_EXECUTABLE_SUFFIX)
config.mk文件就执行结束了。

继续main.mk文件的执行。接下来检查编译系统,是linux还是window以及苹果 Darwin等,以及检查openJDK的版本等。

在然后,加载definations.mk加载各种函数,包括我们在Android.mk中使用的my-dir。

define my-dir


今天太晚了,明天接着写。main.mk文件会接着往下执行。












你可能感兴趣的:(andriod系统编译流程,Android)