【Bash百宝箱】Android编译系统(Makefile)

标签: android Android-mk
1059人阅读 评论(0) 收藏 举报
分类:

0、Makefile

Android编译系统基于GNU make,用来管理Makefile,Makefile的基础知识可参考:
http://blog.csdn.net/ieearth/article/details/47296429

Makefile最一般的规则就是个依赖树,如下:

target: prerequisites
    commands

target是我们编译时要生成的目标,prerequisites是编译目标所需要的依赖文件,当依赖文件比编译目标新时就会执行下面的commands,commands前需要保留一个tab制表符。Android编译系统正是基于这个简单的规则,构建了一个庞大的依赖树,首先从树的根节点开始。

1、根节点droid

Android系统源码根目录有一个Makefile:

### DO NOT EDIT THIS FILE ###
include build/core/main.mk
### DO NOT EDIT THIS FILE ###

这个Makefile没做什么事,只是简单地include另一个Makefile,build/core下的main.mk较为复杂,有1k多行代码,想要一下子看懂还是不太容易的,可以按照依赖树的规则,从根节点开始分析。Android编译系统依赖树的根节点为Makefile中从上到下的第一个编译目标,即droid:

# This is the default target.  It must be the first declared target.
.PHONY: droid
DEFAULT_GOAL := droid
$(DEFAULT_GOAL): droid_targets

.PHONY: droid_targets
droid_targets:

根节点droid是个伪目标,依赖于droid_targets,而droid_targets的依赖树有两个依赖分支:

ifneq ($(TARGET_BUILD_APPS),)
# If this build is just for apps, only build apps and not the full system by default.
...
.PHONY: apps_only
apps_only: $(unbundled_build_modules)
droid_targets: apps_only
...
else
...
# Building a full system-- the default is to build droidcore
droid_targets: droidcore dist_files 
endif # TARGET_BUILD_APPS

根据TARGET_BUILD_APPS变量的判断,当只编译app时,droid_targets依赖于apps_only,否则将编译整个系统,此时droid_targets依赖于droidcore和dist_files。理清了根节点droid的依赖树,main.mk看起来就简单多了,除了构建这些依赖规则之外,main.mk还实现了其它的配置检测功能。

a. 对编译环境的检测:比如java版本是否符合要求,当前机器上的make环境必须高于特定版本等,如果这些检查没有通过,一般情况下系统会终止编译。
b. 进行一些必要前期处理:比如说整个项目工程是否需要先进行清理工作,部分工具的安装等。
c. 引用其它Makefile文件:这点在整个main.mk中处处可见,如引用config.mk、cleanbuild.mk等。
d. 设置全局变量:这些全局变量决定了编译的具体实现过程。
e. 各种函数的实现:Android编译系统中定义了不少函数,它们提供了各种问题的统一解决方案,比如print-vars函数用于打印一串变量列表,my-dir可以知道当前所处的路径等,这些函数对我们自己编写Makefile文件也有一定的指导意义。

在Android中定制一款产品时,一般要添加几个脚本文件:vendorsetup.sh、AndroidProducts.mk、BoardConfig.mk、Android.mk。其中vendorsetup.sh是在envsetup.sh中被调用的,AndroidProducts.mk和BoardConfig.mk作一些配置工作,Android.mk用来编译具体的产品或者产品的某个部分。在Android源码的build/core目录下有许多的Makefile,下面介绍几个主要的。

main.mk:上面介绍了,这个是整个编译系统的主导文件。
config.mk:产品配置的主导文件,在main.mk中被include。
base_rules.mk:定义了编译系统需要遵循的基本规则,多个Makefile都引用了这个文件。
build_id.mk:定义了版本号,在version_defaults.mk中被引用。
cleanbuild.mk:定义了clean操作,在main.mk中被引用。
clear_vars.mk:清空几乎所有的以LOCAL_开头的系统变量,LOCAL_PATH不会被清空,在config.mk中把build/core/clear_vars.mk赋值给变量CLEAR_VARS,一般在Android.mk中使用,直接include这个文件。
definitions.mk:定义了一系列有用的函数,比如说获取当前路径的my-dir,通过call来调用,在Android.mk中经常可以看到,这个文件会include产品目录下自定义的definitions.mk,最终在main.mk中展开。
envsetup.mk:定义了编译时用到的环境变量,在config.mk中被inlcude,注意与envsetup.sh区分开来。
shared_library.mk:负责BUILD_SHARED_LIBRARY的具体实现,在config.mk中设置了这个环境变量,一般在Android.mk中include使用,表示编译目标为一个共享库。其它以BUILD_开头的表示编译目标类型的也有类似的Makefile来实现。
products_config.mk:产品配置,属于envsetup.mk中的一部分。
version_defaults.mk:用于生成版本信息。
...

2、droidcore与dist_files

在编译整个Android系统时,根节点droid依赖于droidcore和dist_files。

droidcore——

下面先来分析一下droidcore的生成过程,其依赖规则为:

# 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) \
    $(INSTALLED_FILES_FILE_VENDOR)

systemimage用于生成system.img,其它的INSTALLED_*_TARGET也是用来生成对应的img,至于生成过程可根据依赖关系一层一层剥离。

dist_files——

# dist_files only for putting your library into the dist directory with a full build.
.PHONY: dist_files

dist_files只出现过一次,一般没什么作用。

3、Android.mk

当我们编译某个具体的模块时,就需要用到Android.mk了,那这个Android.mk该如何编写呢?Android系统中集成了许多开源项目,有非常多的Android.mk,最好的办法就是参考这些Android.mk,下面以Android中抓取内存信息的procrank工具为例,其源码位置在system/extras/procrank,Android.mk内容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_SRC_FILES := procrank.c
LOCAL_CFLAGS := -Wall -Wextra -Wformat=2 -Werror
LOCAL_SHARED_LIBRARIES := libpagemap
LOCAL_MODULE := procrank
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_MODULE_TAGS := debug
include $(BUILD_EXECUTABLE)

LOCAL_PATH通过调用my-dir函数保存了当前的路径。
CLEAR_VARS指向build/core/clear_vars.mk,用以清空以LOCAL_开头的系统变量,LOCAL_PATH除外。
LOCAL_SRC_FILES指定了编译用到的源文件。
LOCAL_CFLAGS指定了编译参数,如熟悉的-Wall等。
LOCAL_SHARED_LIBRARIES指出编译需要用到哪些共享库。
LOCAL_MODULE为编译目标的名字。
LOCAL_MODULE_PATH为编译目标的输出目录。
LOCAL_MODULE_TAGS指出编译模式为debug。
BUILD_EXECUTABLE告诉我们编译结果为一个可执行文件。
上面的Android.mk是一个非常简单的文件,实际应用中可能远比这个文件复杂,不过用法类似,在Android源码中会看到各种形式的Android.mk,这是一个学习Android.mk的好资源。

查看评论

android makefile 编译分析及 android.mk分析

http://www.xuephp.com/main/detail.php?cid=23545 下面是main.mk文件包含关系,本文档主要说明的就是这些文件里到底做了什么。(这个文件被根目...
  • heiding215
  • heiding215
  • 2012-08-13 16:28:36
  • 1845

Android应用随系统编译makefile中如何添加so库

主要介绍某个项目跟随系统一起编译如何通过makefile添加so库。   帮另外一个项目救火,需要用到百度定位的sdk,一个依赖的jar包,一个需要放到armeabi中的liblocS...
  • u012242853
  • u012242853
  • 2015-01-27 20:47:12
  • 1258

android里makefile的写法

android里makefile的写法 (1)Android.mk文件首先需要指定LOCAL_PATH变量,用于查找源文件,宏函数’my-dir’, 由编译系统提供。由于一般情况下Android.m...
  • lx627776548
  • lx627776548
  • 2016-08-24 10:39:42
  • 1218

Android编译系统简析

Android 编译系统 的简单理解 一,Makefile 入门  :简单来说,Makefile提供了一种机制,让使用者可以有效的组织“工作”,这里说的是“工作”,而不是“编译”,因为Makefile...
  • lin20044140410
  • lin20044140410
  • 2016-04-04 22:09:06
  • 596

利用makefile将添加的资源文件编译到Android系统中

利用makefile编译新增资源文件
  • Le_773
  • Le_773
  • 2016-05-28 21:02:03
  • 535

Android 中Makefile的详细分析

Android 中Makefile的详细分析
  • ztguang
  • ztguang
  • 2016-10-30 21:31:49
  • 3166

<em>Android编译</em>流程_<em>makefile</em>流程

<em>Android编译</em>流程_<em>makefile</em>流程 综合评分:4(2位用户评分) 收藏评论(1)举报 所需: 3积分/C币 下载个数: 12 开通VIP C币充值 立即下载 ...
  • 2018年03月19日 00:00

i2c

i2ctools是一个简单好用的工具,该工具使得I2C设备的调试更加方便可解压到安卓源码目录external/i2c-tools-3.1.2,在该目录下新建<em>Android</em>.mk 用mm<em>编译</em>后,out目录...
  • 2018年03月26日 00:00

Android实战技巧之三十六:Makefile快速入门

目标通过一篇文章的介绍达到能够编写简单Makefile以及能够看懂普通的Makefile之目的。make简介make是一个老牌的构建(build)工具,1970年问世以来已经度过了45年的时光而魅力不...
  • lincyang
  • lincyang
  • 2015-06-13 13:12:20
  • 4110
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 41万+
    积分: 7103
    排名: 4005
    HELLO WORLD
    博客专栏
    文章分类