上一篇文章对于源码中的安卓编译系统文档进行了翻译,本文就以android当中的init模块作为例子,对其中的Android.mk文件进行分析,读者可以在阅读本文的同时查看我的译文:http://blog.csdn.net/class_brick/article/details/70859809。
总的来说,init模块中的Android.mk文件主要进行了 个流程的操作:
1、设置本模块名称
2、清理LOCAL_变量
3、设置LOCAL_变量,包括编译的内容、方式、选项等
4、执行编译
5、设置其他模块对于init的联系并编辑
以上前四步是Android.mk文件的通常流程,在阅读其他文件时,也可以按照这样的思路。
文件位于/system/core/init/文件不大,只有75行:
# Copyright 2005 The Android Open Source Project
#第一行,为LOCAL_PATH进行赋值,实际上的值就是当前Android.mk所在的目录,即为#/system/core/init/。
LOCAL_PATH:= $(call my-dir)
#第二行,清除除了LOCAL_PATH之外的所有LOCAL_前缀的变量
include $(CLEAR_VARS)
#第三行,对于LOCAL_SRC_FILES进行赋值,指定需要编译的.cpp/.c/.y/.l/.java文件
LOCAL_SRC_FILES:= \
builtins.c \
init.c \
devices.c \
property_service.c \
util.c \
parser.c \
keychords.c \
signal_handler.c \
init_parser.c \
ueventd.c \
ueventd_parser.c \
watchdogd.c
#第四行,对于LOCAL_CFLAGS进行赋值,指定c/c++编译器的额外标签,相当于在编译时执
#行gcc *.c -Wno-unused-parameter,作用是忽略未使用参数的警告
LOCAL_CFLAGS += -Wno-unused-parameter
#第五行,如果INIT_BOOTCHART的值为true,就编译bootchart.c与加入编译命令#-DBOOTCHART=1,bootchart的作用是对android的开机性能进行分析,默认是关闭的
ifeq ($(strip $(INIT_BOOTCHART)),true)
LOCAL_SRC_FILES += bootchart.c
LOCAL_CFLAGS += -DBOOTCHART=1
endif
#第六行,如果编译目标是userdebug或者eng,就加入编译选项允许设置selinux的开关
ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
LOCAL_CFLAGS += -DALLOW_LOCAL_PROP_OVERRIDE=1 -DALLOW_DISABLE_SELINUX=1
endif
# Enable ueventd logging
# 第七行,直译,允许ueventd记录日志
#LOCAL_CFLAGS += -DLOG_UEVENTS=1
# 第八行,设置本模块的名称为init
LOCAL_MODULE:= init
# 第九行,设置init模块可以被静态链接
LOCAL_FORCE_STATIC_EXECUTABLE := true
# 第十行,将编译后的此模块放到TARGET_ROOT_OUT目录下,TARGET_ROOT_OUT的值在编译时的
# envsetup.sh脚本中被设置,值为out/target/product/xxx/root
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
# 第十一行,编译后的没有经过符号剥离的目标路径
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
# 第十二行,init模块需要的静态库列表
LOCAL_STATIC_LIBRARIES := \
libfs_mgr \
liblogwrap \
libcutils \
liblog \
libc \
libselinux \
libmincrypt \
libext4_utils_static \
libsparse_static \
libz
# 第十三行,额外的依赖项,表示必须该目录下必须存在Android.mk文件(悖论?)
LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
# 第十四行,将init模块编译成可执行文件
include $(BUILD_EXECUTABLE)
# Make a symlink from /sbin/ueventd and /sbin/watchdogd to /init
# 第十五行,直译,设置/sbin/ueventd和/sbin/watchdogd到/init的符号链接
SYMLINKS := \
$(TARGET_ROOT_OUT)/sbin/modprobe \
$(TARGET_ROOT_OUT)/sbin/ueventd \
$(TARGET_ROOT_OUT)/sbin/watchdogd
# 这里涉及到makefile文件的语法,简单的描述一下, 通常的形式是:
# 变量1 : 变量2
# 命令
# 含义:
# 代表变量1的生成需要变量2,如果变量2中的内容有任何一个比变量1要新的话
# 就执行命令中的内容
# 所以接下来的含义就是SYMLINKS中的内容将会依赖于init模块
# 并在init模块更新之后执行接下来的四行命令
$(SYMLINKS): INIT_BINARY := $(LOCAL_MODULE)
$(SYMLINKS): $(LOCAL_INSTALLED_MODULE) $(LOCAL_PATH)/Android.mk
@echo “Symlink: $@ -> ../$(INIT_BINARY)”
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf ../$(INIT_BINARY) $@
ALL_DEFAULT_INSTALLED_MODULES += $(SYMLINKS)
# We need this so that the installed files could be picked up based on the
# local module name
# 第十六行,直译,我们需要通过这个来基于init模块名称的找到已安装文件
ALL_MODULES.$(LOCAL_MODULE).INSTALLED := \
$(ALL_MODULES.$(LOCAL_MODULE).INSTALLED) $(SYMLINKS)