Makefile 是用来告诉你怎样去编译和连接程序,在编译时根据编译环境和编译目标选择编译工具、编译参数及编译哪些模块,同时指定了编译目标所的依赖性和生成规则。在Android中,主要的Makefile文件存在与build/core目录中变现为许多的.mk文件。
任何的编译系统均由两个部分构成:配置部分和目标构建部分。
Android配置部分,主要完成:>基于android产品的配置(product_config); >选择构建安装的运行环境;>设置TARGET相关变量如,TARGET_ARCH,TARGET_OS,TARGET_BUILD_TYPE; >设置HOST相关变量如,HOST_ARCH,HOST_OS,HOST_BUILD_TYPE;>配置target上运行的程序所需要的工具链及编译参数如,linux-arm-gcc,cflags,include等;>配置host上运行的程序所需要的工具链及编译参数。
主要的配置变量:TARGET_BUILD_AVRIANT:安装变量
-取值范围(Eng user userdebug tests);
-决定生成后的哪些文件会被安装进目标系统也就是system.image。如果取值为eng,就会将eng类型的模块安装到目标系统;
-在main.mk中的modules_to_install := $(sort \
$(ALL_DEFAULT_INSTALLED_MODULES) \
$(product_FILES) \
$(foreach tag,$(tags_to_install),$($(tag)_MODULES)) \
$(call get-tagged-modules, shell_$(TARGET_SHELL)) \
$(CUSTOM_MODULES) \
)
$(tag)_MODULES)的值就是根据TARGET_BUILD_VARIANT变量来得到的。
-TARGET_PRODUCT:用来定制产品包,也就是哪些packages会被安装进系统中;如果TARGET_PRODUCT的值等于ipanel的话它就找到build/target/product/目录下的ipanel.mk文件,再根据ipanel.mk中的值得到一些跟产品相关的变量,如TARGET_DEVICE,TARGET_PACKAGES等。
-TARGET_DEVICE:这一变量决定了是导入board目录下的哪个子目录到BoardConfig.mk文件,决定了产品的输出目录的名称;
-PRODUCT_PACKAGES:决定了你定制的哪些产品的包。
-TARGET_BUILD_TYPE:定义目标的编译类型如,release;
-HOST_BUILD_TYPE:定义主机的编译类型如,release;
-TARGET_ARCH:定义了目标的硬件环境;
-HOST_ARCH:定义了主机的硬件环境;
-HOST_OS:定义了主机的系统平台;
注:这些参数可以在buildspec.mk文件中声明也可以在android目录输入tapas来交互设置,如没有设置则采用默认值。
主要的make文件说明:
Main.mk:android的编译入口
-SHELL设置;
-编译环境设置;
-编译环境检查;
-包含必要的宏;
-根据make参数设置编译时的变量;
-包含需要编译的android.mk
config.mk:编译配置
-包含pathmap.mk
-定义了一些变量如SRC_SOURCE_HEADERS等一些通用的编译参数,package的后缀名等COMMONT_PACKAGE_SUFFIX:=.zip
-包含buildspec.mk导入主要的环境变量
-包含envsetup.mk:遍历所有product相关的路据,载入所有支持product的信息到变量集PRODUCT.<productMKpath><attribute>中,一个product对应一个<productMKpath>.最后根据TARGET_PRODUCT的值,定义各种跟product相关的变量。
-包含board_config.mk主要是芯片级别的设置
-依次设置HOST_,TARGET_值再包含select.mk,在select.mk中先定义combo_os_arch,通常是linux-arm,然后定义各种跟编译连接相关的变量,最后包含进build/core/combo/TARGET_linux-arm.mk
-包含javac.mk定义javac的命令和通用的参数
-定义一些变量,指向通用工具,其中一些是系统提供的,如YACC
envsetup.mk:
-包含进version_default.mk定义版本相关的一些变量
-检查TARGET_PRODUCT;若为空,则置generic。TARGET_PRODUCT应在buildspec.mk中定义好;
-检查TARGET_BUILD_VARIANT,若为空,则置eng
-包含product_config.mk
检查TARGET_BUILD_VARIANT的取值范围eng user userdebug tests
-判断及设定HOST_OS,HOST_ARCH,TARGET_ARCH等目标环境
-定义TARGET_BUILD_TYPE默认为release
-定义OUT_DIR
定义一些路径变量DEBUG_OUT_DIR TARGET_OUT_ROOT_release等。
product_config.mk:
-主要是通过node_fns.mk,product.mk,device.mk得到PRODUCTS.XXX相关的变量
跟编译相关的主要变量
-LOCAL_PATH:当前路径可以用$(call my-dir)
-LOCAL_PACKAGE_NAME:package的名字也就是生成后目标的名称
-LOCAL_MODULE_SUFFIX:模块的后缀
-LOCAL_MODULE:模块名
-LOCAL_MODULE_TAGS:默认optional。取值范围user debug eng tests optional samples这个值有两个作用:
决定编译出来的目标文件会输出到哪个目录,如果是tests的话就输出到DATA目录下;用于区分它是属于哪一类模块,如果等于eng的话他就属于eng模块。在main.mk中会选择安装那种类型的模块到image
-LOCAL_SRC_FILES:需要编译的源文件
-LOCAL_SHARED_LIBRARIES:需要链接的外部库
-LOCAL_PRELINK_MODULE:是否需要预处理
-LOCAL_MODULE_CLASS:模块最后安装到哪种类型的文件夹中,如果是动态库的话,应该填写SHARED_LIBRARIES.
-LOCAL_INSTALLED_MODULE:编译后生成的目标文件的目录。如果强制指定的话,就会生成到你指定的目录LOCAL_INSTALLED_MODULE:=$(LOCAL_MODULE_PATH)/$(LOCAL_MODULE_SUBDIR)$(LOCAL_INSTALLED_MODULE_STEM)
在base_rules.mk中LOCAL_MODULE_PATH:=$($(my_prefix)OUT$(use_data)_$(LOCAL_MODULE_CLASS)),如果模块定义了TAGS:=TESTS则user_data的值是DATA,这样的模块会被安装在data目录下,那么通过替换我们知道这个LOCAL_MODULE_PATH:=TARGET_OUT_$(LOCAL_MODULE_CLASS)这个LOCAL_MODULE_CLASS在特定的类型编译会被google赋值成为固定内容,它的值就会用来定义生成的目录,比如:LOCAL_MODULE_CLASS:=ETC的时候,则会被安装在system/etc/目录
编译主要的Makefile
Android.mk :如果自己新增模块的话就要自己编写这个makefile。规则可以参照package/Apps里面的模板下面,下面是列出的5种类型文件的Android.mk的编写方法:
-编译静态库-->
LOCAL_PATH:=$(call my-dir)<以hello为例>
include $(CLEAR_VARS)
LOCAL_MODULE=libhellos
LOCAL_CFLAGS = $(L_CFLAGS)
LOCAL_SRC_FILES = hellos.c
LOCAL_C_INCLUDES = $(INCLUDES)
LOCAL_SHARED_LIBRARIES:=libcutils
LOCAL_COPY_HEADERS_TO:=libhellos
LOCAL_COPY_HEADERS := hellos.h
include $(BUILD_STATIC_LIBRARY)
编译动态库--->
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE=libhellos
LOCAL_CFLAGS = $(L_CFLAGS)
LOCAL_SRC_FILES = hellos.c
LOCAL_C_INCLUDES = $(INCLUDES)
LOCAL_SHARED_LIBRARIES:=libcutils
LOCAL_COPY_HEADERS_TO:=libhellod
LOCAL_COPY_HEADERS := hellos.h
include $(BUILD_SHARED_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hellos
LOCAL_STATIC_LIBRARIES := libhellos
LOCAL_SHARED_LIBRARIES :=
LOCAL_LDLIBS += -ldl
LOCAL_SRC_FILES := mains.c
LOCAL_C_INCLUDES := $(INCLUDES)
include $(BUILD_EXECUTEABLE)
编写可执行程序使用动态库-->LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hellod
LOCAL_MODULE_TAGS := debug
LOCAL_SHARED_LIBRARIES := libs libcutils
LOCAL_SRC_FILES := maind.c
LOCAL_C_INCLUDES := $(INCLUDES)
include $(BUILD_EXECUTEABLE)
编写JAVA package
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := libartity
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := Calculator
include $(BUILD_PACKAGE)