当前位置: 首页 > 安卓培训 > Android开发 > Android系统源码学习:Android内核编译教程
Android系统源码学习:Android内核编译教程 时间:2018-08-16     来源:未知

之前分享过一些关于Android源代码学习方法的文章,初次接触Android源代码的朋友建议去看一下。今天我们主要分享具体Android系统源码学习中的Android内核编译的相关知识。

Android系统源码学习:Android内核编译教程
Android内核编译教程

1、编译Android源码

关于android系统的编译,Android的官方网站上也给出了详细的说明。

//source.android.com/source/building.html

Ø 初始化编译环境:

切换到Android源码目录:

$ cd android_source

执行下面命令,加载编译过程中用到的命令、环境变量:

$ source build/envsetup.sh

Ø 选择编译选项:

执行下面的命令,从列表中选择一个编译项:

$ lunch

You're building on Linux

Lunch menu... pick a combo:

1. full-eng

2.full_x86-eng

3.vbox_x86-eng

4.full_maguro-userdebug

5.full_tuna-userdebug

6.full_panda-eng

我们选择1,也就是说,编译full-eng的目标,当然我们也可以直接指定编译项,如下:$ lunch full-eng。

其中,lunch命令是指打印或设置出当前系统中设置的编译项,full-eng这个编译项由两部分组成,其中前半部分full表示目标设备为Android的模拟器,官方解释为:fully configured with all languages,apps, input methods,全部的应用程序及语言,输入法等。后半部分eng表示带有调试功能的工程机。lunch命令打印全部的信息,如下表所示:

lunch命令打印全部的信息

Ø 编译前的准备:

由于我们使用ubuntu12.04对Android进行编译,Android对Ubuntu12.04的编译平台的支持不是很推荐,有些库的兼容方面会有一些问题,在编译过程中会产生一些错误,我们要进行一些修正。

具体错误会在编译过程中表现出来,可以根据错误信息,然后搜索解决方案。

Ø 编译源码:

输入下面命令开始编译:

$ make -jn

其中,-jn表示,n个线程同时编译,一般n的值为CPU核的2倍,但是,也要和你的Ubuntu的内存有关系,每个线程在编译时少需要1G内存,如果你没有很多内存,还是直接使用make命令吧,否则,编译到后面会出错。

这个过程,如果是虚拟机的话,至少要4个多小时,如果是实体机的话,要看配置,一般在1个小时以上。

编译成功结果如下图所示:

Android内核源码编译成功界面

2、编译goldfish内核源码:

编译Linux源码必然要先指定gcc交叉编译器,我们直接使用Android自带的arm-eabi-4.4.3编译器,它在android_source/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin路径下。

$ ls android_source/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin

编译goldfish内核源码

我们编辑下面一个编译脚本make_kernel.sh,让这个脚本去编译goldfish的内核:

#!/bin/bash

export PATH=/home/android/android_source/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin:$PATH

export ARCH=arm #指定目标体系的架构

export SUBARCH=arm #指定目标体系的子架构

export CROSS_COMPILE=arm-eabi- #配置交叉编译器

make goldfish_armv7_defconfig

make

为了确保环境参数正确,接下来执行下面两条指令,否则有可能不能正常启动模拟器。(注:以下两条指令是在Android源码根目录下执行)

$ source build/envsetup.sh #缺少这条指令,可能会导致无法编译通过

$ lunch full-eng

//缺少这条指令,可能会导致无法启动模块器,系统报无法找到AVD,并要求你创建AVD。

注:用$make goldfish_defconfig这样配置也可以编译通过,模拟器也可以启动,但是Android的开机画机就显示不了,$adb shell也死活连不上,原因就是这个goldfish_defconfig这个配置文件问题。

给make_kernel.sh添加可执行权限,然后执行该编译脚本:

$ chmod a+x make_kernel.sh

$ ./ make_kernel.sh

当我们看到下面的结果时,表示goldfish的内核编译出来了:

goldfish的内核编译成功界面

$ ls arch/arm/boot/

可以看到zImage文件。

zImage文件

在模拟器中启动编译好的内核:

$ emulator -kernel /home/android/android_source/kernel/goldfish/arch/arm/boot/zImage

模拟器启动界面:

模拟器启动界面

进入模拟器从设置里看版本信息:

进入模拟器从设置里看版本信息

从上图可以看出当前Android版本是4.0.1,内核版本是2.6.29,说明成功了。

同样也可以通过adb shell来查看内核版本信息,如下图:

$adb shell

#cd proc

#cat version

通过adb shell来查看内核版本信息

备注:可以在源码的根目录下运行emulator –help查看模拟器的帮助信息。其中,可以通过-kernel指定你自己编译出的kernel;-partition-size系统分区的大小;-memory指定内存RAM的大小;-skin指定模拟器的皮肤;-avd指定模拟器的名字等。

3、 Android编译过程分析:

按照google给出的编译步骤如下:

Ø source build/envsetup.sh:加载命令;

Ø lunch:选择目标平台编译选项;

Ø make:执行编译;

我们按照编译步骤来分析编译过程的细节,终添加自己的平台产品的编译选项。

3.1、source build/envsetup.sh:

该命令是用来将envsetup.sh里的所有用到的命令加载到环境变量里去。主要几个命令如下:

function help() #显示帮助信息

function check_product() #检查product

function check_variant() # 检查变量

function printconfig() #打印配置

function add_lunch_combo() # 添加lunch项目

function print_lunch_menu() # 打印lunch列表

function lunch() #配置lunch

function m() #make from top

function mm() #make from current directory

function mmm() #make the supplied directories

build/envsetup.sh其主要作用如下:

加载了编译时使用到的函数命令,如:help,lunch,m,mm,mmm等;

添加了两个编译选项:generic-eng和simulator,这两个选项是系统默认选项

查找vendor/*/*/vendorsetup.sh和device/*/*/vendorsetup.sh,也就是说从vendor/<厂商目录>/<平台设备目录>/目录和device/<厂商目录>/<平台设备目录>/目录下,查找vendorsetup.sh,如果找到的话,加载执行它,添加厂商自定义产品的编译选项。

如果想要添加自己的目标设备编译选项,我们就要在device或vendor目录下创建设备厂商,然后在设备厂商目录下,创建一个vendorsetup.sh文件,在里面添加上自己的编译项。

$mkdir -p device/farsight/fsdevice

$touch device/farsight/fsdevice/vendorsetup.sh

$echo "add_lunch_combo fs100-eng" > device/farsight/fsdevice/vendorsetup.sh

注:

farsight:厂商名

fsdevice:平台设备名

fs100-eng:自定义的目标产品名为fs100,eng为编译目标类型

所有的编译项的格式都是:设备名-编译目标类型,编译目标类型为:eng,user,userdebug,三种类型之一(详细见3.1节)。

下面验证一下我们的结果,当在Android目录下,再次执行source build/envsetup.sh时,我们可以看到我们新添加的编译项:

查看新添加的编译项

3.2、执行lunch full-eng:

我们当然也可以直接执行lunch命令,然后在弹出菜单里面来选择我们的编译项,如下图所示:

执行lunch full-eng

注:我们添加的编译项这时已经存在了,但是如果你选择了它,在编译时会出错,因为我们还没有对应编译项的配置文件。

lunch命令可以带参数和不带参数,终导出一些重要的环境变量,从而影响编译系统的编译结果。导出的变量如下(以lunch full-eng为例):

TARGET_PRODUCT=full

TARGET_BUILD_VARIANT=eng

TARGET_BUILD_TYPE=release

3.3、执行make命令:

当我们输入make命令后,就开始android系统的编译了,所有的Makefile都通过build/core/main.mk这个文件组织在一起,它定义了一个默认goals:droid,当我们在TOP目录下,敲make实际上就等同于我们执行make droid。

当make include所有的文件,完成对所有make文件的解析以后就会寻找生成droid的规则,依次生成它的依赖,直到所有满足的模块被编译好,然后使用相应的工具打包成相应img。其中,config.mk,envsetup.mk,product_config.mk文件是编译用户指定平台系统的关键文件。Android的编译系统比较复杂,详细的说明请参照前面给出博文内容。

下面列出在编译过程中经常使用的一些命令:

1、source build/envsetup.sh:加载编译命令,产生编译选项;

2、lunch或lunch xxx-yyy:打印编译选项菜单或指定编译选项,xxx表示产品,yyy表示编译类型;

3、make:根据lunch选项,编译Android系统,后产出为:system.img,ramdisk.img,userdata.img;

4、m:和make命令一样;

5、mm:从当前目录下开始向下编译目标;

6、mmm:指定一个目录,仅编译指定目录下的目标;

7、make snod:只将out/target/product/XXX/system/目录下的内容打包生成system.img,不会检查依赖关系;

8、make bootimage:只将out/target/product/XXX/root/目录下的内容打包生成ramdisk.img。

前台专线:010-82525158 企业培训洽谈专线:010-82525379 院校合作洽谈专线:010-82525379 Copyright © 2004-2022 北京华清远见科技发展有限公司

Android培训

版权所有 ,京ICP备16055225号-5,京公海网安备11010802025203号