Android的编译系统

article/2025/10/11 15:01:55

一、Makefile的主要流程

以下主要流程都在build/core/main.mk里安排。

l         初始化相关的参数设置(buildspec.mkenvsetup.mkconfig.mk)

l         检测编译环境和目标环境

l         决定目标product

l         读取product的配置信息及目标平台信息

l         清除输出目录

l         检查版本号

l         读取Board的配置

l         读取所有Module的配置

l         根据配置产生必要的规则(build/core/Makefile)

l         生成image

 

主要配置文件:

      build/core/config.mk         summary of config

      build/core/envsetup.mk    generate dir config and so on

      build/target/product         product config

      build/target/board            board config

      build/core/combo              build flags config

这里解释下这里的boardproductborad主要是设计到硬件芯片的配置,比如是否提供硬件的某些功能,比如说GPU等等,或者芯片支持浮点 运算等等。product是指针对当前的芯片配置定义你将要生产产品的个性配置,主要是指APK方面的配置,哪些APK会包含在哪个product中,哪 APK在当前product中是不提供的。
      config.mk
是一个总括性的东西,它里面定义了各种module编译所需要使用的HOST工具以及如何来编译各种模块,比如说 BUILT_PREBUILT就定义了如何来编译预编译模块。envsetup.mk主要会读取由envsetup.sh写入环境变量中的一些变量来配置 编译过程中的输出目录,combo里面主要定义了各种HostTarget结合的编译器和编译选项。

配置部分主要完成以下几个工作:

a) 基于Android 产品的配置(product config):选择构建安装的运行程序(user package)

b) 设置 target 等相关变量TARGET_ARCH, TARGET_OS,TARGET_BUILD_TYPE, TARGET_PREBUILT_TAG

c) 根据编译环境设置 host等相关变量HOST_OS, HOST_ARCH,HOST_BUILD_TYPE, HOST_PREBUILT_TAG

d) 编译 target上运行程序所需的工具链及编译参数设置,如linux-arm-cccflaginclude目录等。

e) 编译 host上运行程序所需的工具链及编译参数设置。

下图简要介绍了Android build system的配置部分的主要构成及相互关系。

 

 

二、初始化参数设置

main.mk里,简单设置几个主要编译路径的变量后,来到config.mk

——————————————config.mk——————————————

其中设置了源文件的一系列路径,包括头文件、库文件、服务、API已经编译工具的路径。(前36行)

40行开始,定义一些编译模块的生成规则:

除了CLEAR_VARS是清楚本地变量之外,其他所有的都对应了一种模块的生成规则,每一个本地模块最后都会include其中的一种来生成目标模块。

 

 

 

回到config.mk,接着会尝试读取buildspec.mk的设置:

 

如同注释所说,会尝试查找buildspec.mk,如果文件不存在会自动使用环境变量的设置,如果仍然未定义,会按arm默认的设置去build

这里的buildspec.mk可以自己创建,也可以将原先build/下的buildspec.mk.default直接命名为buildspec.mk并移到根目录。

实际上,buildspec.mk配置都被屏蔽了,我们可以根据需要直接打开和修改一些变量。在这里我们可以加入自己的目标产品信息:

ifndef TARGET_PRODUCT

TARGET_PRODUCT:=generic_x86

endif

以及输出目录设置:

OUT_DIR:=$(TOPDIR)generic_x86

 

三、读取Product的设定

回到config.mk,接着进行全局变量设置,进入envsetup.mk

——————————————envsetup.mk——————————————

里面的大部分函数都在build/envsetup.sh中定义。

首先,设置版本信息,(11)build/core/version_defaults.mk中具体定义平台版本、SDK版本、Product版本,我们可以将BUILD_NUMBER作为我们产品generic_x86version信息,当然,也可以自定义一个版本变量。

回到envsetup.mk,接着设置默认目标产品(generic),这里由于我们在buildspec.mk里设置过TARGET_PRODUCT,事实上这个变量值为generic_x86

然后读取product的设置(41),具体实现在build/core/product_config.mk中,进而进入product.mk,从build/target/product/AndroidProducts.mk中读出PRODUCT_MAKEFILES,这些makefile各自独立定义product,而我们的产品generic_x86也应添加一个makefile文件generic_x86.mk。在generic_x86.mk中我们可以加入所需编译的PRODUCT_PACKAGES

下面为generic_x86.mk

 

四、读取BoardConfig

接着回到config.mk(114)这里会搜索所有的BoardConfig.mk,主要有以下几个地方:

 

这里的TARGET_DEVICE就是generic_x86,就是说为了定义我们自己的产品generic_x86,我们要在build/target/board下添加一个自己的目录generic_x86用来加载自己的board配置。

BoardConfig.mk中会决定是否编译bootloaderkernel等信息。

 

五、读取所有Module

结束全局变量配置后,回到main.mk,马上对编译工具及版本进行检查,错误便中断编译。

142行,包含文件definitions.mk,这里面定义了许多变量和函数供main.mk使用。main.mk446行,这里会去读取所有的Android.mk文件:

 

其中include $(ONE_SHOT_MAKEFILE)

这个ONE_SHOT_MAKEFILE是在前面提到的mm(envsetup.mk)函数中赋值的:

ONE_SHOT_MAKEFILE=$M make -C $T files $@

 

回到main.mk,最终将遍历查找到的所有子目录下的Android.mk的路径保存到subdir_makefiles变量里(main.mk里的470)

我们在package/apps下每个模块根目录都能看到Android.mk,里面会去定义当前本地模块的TagLOCAL_MODULE_TAGSAndroid会通过这个Tag来决定哪些本地模块会编译进系统,通过PRODUCTLOCAL_MODULE_TAGS来决定哪些应用包会编译进系统。(前面说过,你也能通过buildspec.mk来制定你要编译进系统的模块)

这个过程在mian.mk445行开始,最后需要编译的模块路径打包到ALL_DEFAULT_INSTALLED_MODULES(602)

 

六、产生相应的Rules,生成image

所有需要配置的准备工作都已完成,下面该决定如何生成image输出文件了,这一过程实际上在build/core/Makefile中处理的。

这里定义各种img的生成方式,包括ramdisk.imguserdata.imgsystem.imgupdate.ziprecover.img等。具体对应的rules可以参考下图:

http://img154.ph.126.net/5ekAHoRqfPf17ALmDJGDYA==/2269251262242871911.png

Make include所有的文件,完成对所有make文件的解析以后就会寻找生成对应目标的规则,依次生成它的依赖,直到所有满足的模块被编译好,然后使用相应的工具打包成相应的img

 

具体make操作:

完整编译

我们在根目录下输入make命令即可开始完全编译。这个命令实际编译生成的默认目标是droid

也就是说,大家敲入make实际上执行的make droid。而接下来大家看看main.mk文件里最后面的部分,会有很多伪目标,如sdkcleanclobber等,这些在默认的make droid的命令下是不会执行的。我们可以在make后加上这些标签来单独实现一些操作。如:输入make sdk 将会生成该版本对应的SDK,输入make clean会清除上次编译的输出。

模块编译

有时候我们只修改了某一个模块,希望能单独编译这个模块而不是重新完整编译一次,这时候我们要用到build/envsetup.sh中提供的几个bash的帮助函数。

在源代码根目录下执行:

. build/envsetup.sh(.后面有空格)

这样大家相当于多了几个可用的命令。

这时可以用help命令查看帮助信息:

其中对模块编译有帮助的是tapasmmmmmm这几个命令。

1tapas——以交互方式设置build环境变量。

   输入:tapas

第一步,选择目标设备:

第二步,选择代码格式:

第三步,选择产品平台:

 

 注意:这里,Google源代码里默认是generic,而我们针对自己的产品应修改成generic_x86

 具体在build/envsetup.sh里的函数chooseproduct()中对相应代码进行修改。

2mmmmmm使用独立模块的make命令。

几个命令的功能使用help命令查看。

举个例子,我们修改了Camera模块的代码,现在需要重新单独编译这一块,这时可以使用mmm命令,后面跟指定模块的路径(注意是模块的根目录)

具体如下:

mmm packages/apps/Camera/

为了可以直接测试改动,编译好后需要重新生成system.img

可以执行:make snod

单独编译image文件

一般我们完整编译后,会生成三个重要的image文件:ramdisk.imgsystem.imguserdata.img。当然我们可以分开单独去编译这三个目标:

make ramdisk —— ramdisk.img

make userdataimage —— userdata.img

make systemimage  —— system.img

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


http://chatgpt.dhexx.cn/article/ixh9kVQL.shtml

相关文章

AOSP安卓源码编译

写在前面 继上次安卓源码下载篇以后已经过了很久了 这里需要补充一些内容,在现在安卓源码是建议只下载自己需要的某个版本,这样更快 #初始化仓库,-b 指示分支,这里使用 android10 repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/A…

Android源码编译

简要说明 现在的Android应用开发开源项目感觉就像春秋战国时期,各种思想雨后春笋,百花齐放,如算法,如图形,如数据库,如网络协议,林林总总、煞是好看,Github也成为了开源者及受益者的…

Android编译系统介绍

1. 编译系统变化 Android 最初是用 Android.mk 来定义模块的, Android.mk 本质上就是 Makefile。随着 Android 工程越来越大,包含的模块越来越多,以 Makefile 组织的项目编译花费的时间越来越多。google 在 Android 7.0 开始引入了 ninja 编…

Android 编译系统

主要是没有一个完整的Android Build System 中文版,所以写了一个也可以以后作为参考。 1.Makefile & Android build system 在进行讲述Android编译系统之前,应该先了解一下编译时所使用的Makefile,或者说复习下这方面的知识,这…

自己编译安卓系统实践

一、需要的环境和信息来源 版本号与驱动匹配表:https://developers.google.com/android/drivers#hammerheadmra58k android细分版本号:https://source.android.com/setup/start/build-numbers?hlzh_cn 编译环境需求:https://source.androi…

Android 源码编译详解【合集篇】

Android 源码编译详解【一】:服务器硬件配置及机型推荐 做 Android系统开发多年,开发环境都是入职就搭建好了,入职时拿个账号密码就直接开始搞开发了,年初换了新公司,所有的项目都是刚起步,一切环境都要重新…

java枚举类型字段与mysql中数据类型映射关系

java枚举类型字段与mysql中数据类型映射关系 domain对象数据库字段swagger测试 domain对象 public class Business {/*** 商家类型*/private Integer type;/*** 状态*/private Integer status;}数据库字段 枚举值设置 swagger测试 type值设置为1,status值也设置…

java枚举类型的构造和get\set方法

可以看出枚举时和类平级的,是定义类级别的关键字 因为枚举都是直接用.xxx的形式,所以里面的值等都是静态的!!! 但是其也有get和set方法,构造方法等 常量 枚举(enum)类型是Java 5新…

Java枚举类型与泛型

一、枚举类型 1、使用枚举类型设置常量 以往设置常量,通常将常量放置在接口中,这样在程序中就可以直接使用,并且该常量不能被修改,因为在接口中定义常量时,该常量的修饰符为final与static。常规定义常量的代码如下所示…

【Java系列】深入解析枚举类型

序言 即便平凡的日子仿佛毫无波澜,但在某个特定的时刻,执着的努力便会显现出它的价值和意义。 希望这篇文章能让你不仅有一定的收获,而且可以愉快的学习,如果有什么建议,都可以留言和我交流 问题 思考一下这寄个问题&a…

Java枚举类型(enum)详解

文章目录 理解枚举类型枚举的定义枚举实现原理枚举的常见方法Enum抽象类常见方法编译器生成的Values方法与ValueOf方法 枚举与Class对象枚举的进阶用法向enum类添加方法与自定义构造函数关于覆盖enum类方法enum类中定义抽象方法enum类与接口 枚举与switch枚举与单例模式EnumMap…

java枚举数字_Java枚举类型的使用,数值的二进制表示

一.Java枚举类型的使用 首先请看这段代码: packagejava上课;public classEnumTest {public static voidmain(String[] args) {Size s=Size.SMALL; Size t=Size.LARGE;//s和t引用同一个对象? System.out.println(s==t);//是原始数据类型吗? System.out.println(s.getClass().…

java枚举类型赋值_java枚举类型(转载)

public class TestEnum { /*最普通的枚举*/ public enum ColorSelect { red, green, yellow, blue; } /* 枚举也可以象一般的类一样添加方法和属性,你可以为它添加静态和非静态的属性或方法,这一切都象你在一般的类中做的那样. */ public enum Season { // 枚举列表必须写在最前…

java 枚举类 int_【转】掌握java枚举类型(enum type)

原文网址:http://iaiai.iteye.com/blog/1843553 1 背景 在java语言中还没有引入枚举类型之前,表示枚举类型的常用模式是声明一组具有int常量。之前我们通常利用public final static 方法定义的代码如下,分别用1 表示春天,2表示夏天,3表示秋天,4表示冬天。 Java代码 p…

java枚举类型转换_java枚举类型enum值与整数的转换

java编程中偶尔会用到枚举,为了直观,我们通常将枚举值设置为形象的单词,方便理解和使用。枚举类型相当于数据库 中字典表,但是枚举只有字典表的值,缺少其他用来表示和值一一对应的字段,当我们在数据库中保存…

Java中的枚举类型

文章目录 前言一、枚举类简介二、枚举底层原理总结 前言 这里复习一下Java中的枚举类型。实际上,枚举类型是特殊的类,和C语言C中的枚举不太一样,下面我们做详细说明。关于枚举类型有一个单独的设计模式:即单例设计模式。单例类是…

Java枚举类型

目录 一、前言: 二、枚举类型: 三、底层原理 四、应用 应用一:定义常量 底层原理详解 应用二:添加新方法 应用三:与switch结合使用 应用四:实现接口 应用五:使用接口组织枚举 一、前言…

深入理解Java枚举类型(enum)

【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/71333103 出自【zejian的博客】 关联文章: 深入理解Java类型信息(Class对象)与反射…

Python中对基本文件操作

Python中对基本文件操作 一、前言二、创建和打开文件1.打开一个不存在的文件时先创建该文件2.以二进制形式打开文件3.打开文件时指定编码方式 三、关闭文件四、打开文件时使用with语句五、写入文件内容六、读取文件1.读取指定字符2.读取一行3.读取全部行 一、前言 在Python中&a…

C语言——文件操作

文章目录 1. 为什么使用文件2. 什么是文件2.1 程序文件2.2 数据文件2.3 文件名 3. 文件的打开和关闭3.1 文件指针3.2 文件的打开和关闭 4. 文件的顺序读写4.1 fgetc与fputc4.2 fgets与fputs4.3 fscant与fprintf4.3.1 fprintf4.3.2 fscanf 4.4 fread与fwrite4.4.1 fwrite4.4.2 f…