Android源码和内核的编译就是一场马拉松,每一个节点都耗时漫长,下载源码、编译源码、下载内核、编译内核,下载中途会断掉,编译中间会失败,求解再重来,又是一轮马拉松,于是每一步都要做好备份和记录,可是30G的源码(编译后已经达到70G)备份一次都需要好久。好在春节伊始我放弃了其他的学习,全力搞这个过程,终于算是拿下了。不过,漫漫长路,这只是一个开头。

我编译的是Android最新稳定版本android-6.0.1_r11,内核是android-goldfish-3.4,平台是Mac OS 10.11。

  • 一、Android源码下载和编译

source.android.com官网对Mac OSX下的编译说的挺详细的了,不过因为你懂的原因,去到官网很不方便,我还是把自己的心路历程记录下来,以便以后再做的时候查找方便。

  • 1、前期准备

这是为后面下载和编译做好环境设置和工具的准备。

  • (1)创建大小写敏感的磁盘镜像文件

Launchpad - 其它 - 磁盘工具,点击菜单 文件 - 新建映像 - 空白映像

如下,在格式中必须选择“OS X 扩展(区分大小写,日志式)”,我在映像格式中选择了“稀疏磁盘映像”,以便未来比较容易地扩展:

不过我发现mac的磁盘工具貌似有bug:点击存储之后,实际生成的磁盘映像文件还是“OS X 扩展(日志式)”的,而不是大小写区分,需要点击该分区文件 - 分区,此时你会发现在“格式”中选择的是“OS X 扩展(日志式)”,把它改为“OS X 扩展(区分大小写,日志式)”,再点应用。

  • (2)确认JDK、XCode版本、make版本

在命令行下输入java -version,确认已经是最新的Java 8了:

输入make -v,确认是3.8.1,据说最新的3.8.2有bug,如果装的是3.8.2,需要退到3.8.1:

我的XCode版本是7.2.1

  • (3)安装所需要的packages

到http://www.macports.org/install.php下载和安装macports,再利用macports下载几个packages:

$ POSIXLY_CORRECT= sudo port install gmake libsdl git gnupg
  • (4)调高文件描述符的限制

编辑~/.bash_profile文件,加入如下内容,把单个进程可打开的文件描述符上限改为1024:

# set the number of open files to be
ulimit -S -n

然后执行source ~/.bash_profile

  • 2、优化编译环境

编辑~/.bashrc文件,添加如下内容,有助于加速编译过程:

export USE_CCACHE=

然后执行source ~/.bashrc

  • 3、安装repo

编辑 ~/.bash_profile文件,添加:

export PATH=~/bin:$PATH

然后执行source ~/.bash_profile。

下载repo工具,并设为可执行:

$ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
$ chmod a+x ~/bin/repo
  • 4、初始化repo

挂载1-(1)中创建的大小写敏感磁盘映像文件,并在里面创建目录android-6.0.1_r11,假设它的全目录名为WORKING_DIRECTORY,

执行如下命令初始化repo客户端:

cd WORKING_DIRECTORY
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-6.0.1_r11

我把源指向的清华的镜像服务器,它将下载分支android-6.0.1_r11,点击此处查看Android分支的名称列表

如果要下载最新主干代码,则执行:

repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest
  • 5、下载Android代码树

注意,接下来我们将进入长夜漫漫的下载过程,执行:

repo sync

我下过几次,每次都要花上四五个小时,而且常常中途会断掉,建议晚上睡觉前走起,运气好的话,第二天早上搞定。如果失败了,还是执行这个命令,会接着上文继续下载。

  • 6、编译Android源码

Android源码的编译步骤仅如下三步:

  • (1)设置环境变量

$ source build/envsetup.sh
  • (2)选择编译目标

$ lunch aosp_arm-eng

官网说这个参数将为模拟器打开所有的调试开关。不带参数直接调用lunch会列出所有的目标选项,但是我没找到每个选项的具体描述。

  • (3)编译

$ make -j4

又是一个漫漫长夜的过程,我的编译大概花了三四个小时,但我没有使用-j4参数,打开这个参数将开启多线程编译。后来缀上这个参数再重新编译,果然效果明显,只用了2个小时12分钟,建议打开。

  • (4)编译问题

build/core/combo/mac_version.mk:: *****************************************************
build/core/combo/mac_version.mk:: * Can not find SDK 10.9 at /Developer/SDKs/MacOSX10..sdk
build/core/combo/mac_version.mk:: *****************************************************
build/core/combo/mac_version.mk:: *** Stop.. Stop.

原因是本机的XCode SDK已经升级到10.11,打开目录:

/Applications/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs,

检查其下的MacOSXxx.xx.sdk即可确认本机的SDK版本,然后修改WORKING_DIRECTORY/build/core/combo/mac_version.mk,将

mac_sdk_versions_supported :=  10.6 10.7 10.8

改为

mac_sdk_versions_supported :=  10.9 10.10 10.11

然后重新启动lunch aosp_arm-eng即可。

fatal error: linux/netfilter/xt_DSCP.h: No such file or directory

我在WORKING_DIRECTORY/external/iptables/extensions/../include/linux/netfilter下面能找到该文件,只不过是xt_dscp.h,我把它改名为xt_DSCP.h即可。我不知道为什么会出这样的问题,我的文件系统已经是大小写敏感的了,而且我是直接repo到该文件系统的,如果真的有错误,应该是可重现的。

  • 7、运行emulator

经过两个多小时的编译,终于看到如下结果:

在命令行下直接运行

$emulator

即可启动模拟器。启动过程很慢,需要耐心等待:

编译过程做好了各种环境变量的设置:

内核使用的是WORKING_DIRECTORY/prebuilts/qemu-kernel/arm64/kernel-qemu

sysdir默认是WORKING_DIRECTORY/out/target/product/generic/

系统镜像文件分别是sysdir下的system.img、ramdisk.img和userdata.img

赶紧把磁盘卸载掉,备份磁盘映像文件!未来就可以在它的基础上做更多尝试,万一踩到屎了,还可以拿这个备份直接来用,不需要再编译一次了。

以后再挂载该磁盘映像文件以后,需要先执行

$cd WORKING_DIERCTORY
$source build/envsetup.sh

再执行$emulator即可。

  • 二、编译内核

Android源码默认不包含他所使用的Linux内核源码,因此需要额外下载和独立编译。

1、确认自己的内核版本号

在刚刚的模拟器中查看手机信息,如下:

确认内核版本是3.4

  • 2、下载内核源码

在WORKDING_DIRECTORY目录下

$cd WORKING_DIRECTORY
$mkdir kernel
$cd kernel
$git clone https://android.googlesource.com/kernel/goldfish.git

这个仓库有970M,我下了三四个小时,悲催的是我没有找到它在国内的镜像服务器,而且这东西不能续传,我中途VPN断掉了,连上之后,git就不认之前下载了一半的文件了,需要从头再来,T T

下完之后,可以看一下该内核仓库包含的分支:

$ git branch -a
* (头指针分离于 origin/android-goldfish-3.4)
master
remotes/origin/HEAD -> origin/master
remotes/origin/android-3.10
remotes/origin/android-3.18
remotes/origin/android-3.4
remotes/origin/android-goldfish-2.6.
remotes/origin/android-goldfish-3.10
remotes/origin/android-goldfish-3.10-l-mr1-dev
remotes/origin/android-goldfish-3.10-m-dev
remotes/origin/android-goldfish-3.18-dev
remotes/origin/android-goldfish-3.4
remotes/origin/android-goldfish-3.4-l-mr1-dev
remotes/origin/linux-goldfish-3.0-wip
remotes/origin/master

checkout3.4的分支代码:

$git checkout remotes/origin/android-goldfish-3.4

在kernel下创建子目录goldfish,并把刚刚检出的代码都放到goldfish下面。

  • 3、编译内核源码

依次执行如下命令:

$ export ARCH=arm
$ export SUBARCH=arm
$ export CROSS_COMPILE=arm-eabi-
$ export PATH=WORKING_DIRECTORY/prebuilts/gcc/darwin-x86/arm/arm-eabi-4.8/bin:$PATH
$ make goldfish_armv7_defconfig
$ make -j4
  • 4、编译问题

'elf.h' file not found

我把http://www.rockbox.org/tracker/9006?getfile=16683另存为elf.h拷贝到WORKDING_DIRECTORY/kernel/goldfish/scripts/mod下。

注意尽管在WORKING_DIRECTORY/kernel/goldfish/include/linux/elf.h下也有一个elf.h,但不能使用这个文件。

然后将WORKING_DIRECTORY/kernel/goldfish/scripts/mod下的mk_elfconfig.c和modpost.h两个文件里的

#include <elf.h>

改为

#include "elf.h"

file2alias.c中的ADD宏发生语法错误

把发生错误的那行做如下修改:

sprintf(str+strlen(str), \
sizeof(field) == ? "%2X" : \
sizeof(field) == ? "%4X" : \
sizeof(field) == ? "%8X" : "" // 最后的""改为"%8X"
……
  • 5、运行新编内核

内核的编译很快,几分钟就会看到如下结果:

产生的Linux内核文件放在了arch/arm/boot/zImage

运行

$ emulator -kernel WORKING_DIRECTORY/kernel/goldfish/arch/arm/boot/zImage

启动模拟器,找到关于手机的内核版本,可以看到编译机器的信息:

几天的探索终于开花结果,万里探索路终于可以迈出第一步了,内心小激动~~

  • 三、编译内核驱动模块

激动之后是艰难的撸码行军。

编译内核驱动模块需要在kernel/goldfish下面首先敲make menuconfig命令,来配置编译方式。今天发现在Mac OSX下面该命令是有问题的:

palancedeMacBook-Pro:goldfish palance$ make menuconfig
HOSTLD scripts/kconfig/mconf
Undefined symbols for architecture x86_64:
"_COLS", referenced from:
_dialog_checklist in checklist.o
_dialog_clear in util.o
_dialog_inputbox in inputbox.o
_dialog_textbox in textbox.o
_dialog_yesno in yesno.o
_dialog_menu in menubox.o ……………………
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code (use -v to see invocation)
make[]: *** [scripts/kconfig/mconf] Error
make: *** [menuconfig] Error \e[;31m#### make failed to build some targets ( seconds) ####\e[00m

解决方案是找到WORKING_DIRECTORY/kernel/goldfish/scripts/kconfig/lxdialog/check-lxdialog.sh文件,如下加入粗体的部分:

ldflags()
{
for extin so a dylib;do
for libi n ncursesw ncurses curses ;do
$cc-print-file-name=lib${lib}.${ext} | grep-q /
if [$?-eq0];then
echo"-l${lib}"
exit
fi
done for lib in ncursesw ncurses curses ; do
if [ -f /usr/lib/lib${lib}.${ext} ];then
echo "-l${lib}"
exit
fi
done

done
exit1 }

再执行make menuconfig,搞定:

Android源码、内核编译的更多相关文章

  1. 在Android源码下编译jni所需要知道的事~

    以下只是自己的一些总结,欢迎讨论 通过NDK编译jni网上有很多例子,在这我只总结在Android源码下编译 1.android源码环境下编译so包,编出来的.so的包前面不会自动给添加lib,NDK ...

  2. ubuntu10.04版本下android源码的编译

    首先是网址:http://software.intel.com/en-us/blogs/2012/03/06/hands-on-notesbuild-android-x86-ics-4-virtual ...

  3. Android源码的编译和下载【转】

    本文转载自:http://blog.csdn.net/banketree/article/details/9089827 网上介绍下载.编译Android方法一坨,读万卷书不如行万里路,以下是笔者亲身 ...

  4. Android:源码环境编译自定义的APP到ROM(System Image)中

    有时候我们需要在源码环境中增加自己的应用或模块,随ROM一起发布. 下面讲述相关步骤: 1. 首先可以在SDK环境下进行编码设计(如果你的APP不涉及到emulator无法模拟的硬件的话) 也可以参考 ...

  5. 通过清华大学镜像下载Android源码并编译源码

    之前看源码都是在Windows下用SourceInsight看,虽然达到了研究源码的效果,但终究还是有遗憾...趁着周末,准备在Ubuntu虚拟机上下载编译源码. 之前下源码时,有了解一些Androi ...

  6. Android源码下编译APK步骤

    1.进入android源码目录下的build下执行:source envsetup.sh 后继续在该路径下执行lunch. 2.编写完成工程 3.编写Android.mk文件,放入工程目录下     ...

  7. Android源码中编译出指定jar包

    今天想把android源码/vendor/letv/frameworks/base/java下的源码编译成 framework-letv.jar供乐乐语音客户端使用,编译完后,发现jar包文件虽然生成 ...

  8. Ubuntu下Chromium for Android 源码的编译

    转自:http://blog.csdn.net/leer168/article/details/9146689 一.环境Ubuntu10.4.4 -desktop-amd64 + VMware Wor ...

  9. android源码编译1

    一.环境说明: 1.liunx系统:Ubuntu12.04 2.jdk:sun-java6-jdk 3.g++4.5 gcc4.5 二.android源码的目录结构 |-- Makefile |-- ...

随机推荐

  1. hihoCoder#1121(二分图判定)

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 大家好,我是小Hi和小Ho的小伙伴Nettle,从这个星期开始由我来完成我们的Weekly. 新年回家,又到了一年一度大龄 ...

  2. Day2-Python基础2---字符串操作

    一.字符串操作 特性:不可修改 name = "my \tname is {name} and i am {year} old" #首字母大写.capitalize print(n ...

  3. 简单的windows作业管理(自己也没弄透彻)

    先把代码贴出来,以后有时间再研究!简单的说,作业就相当于沙箱,可以使程序在一定范围内活动. #include "stdafx.h"#include "windows.h& ...

  4. RegisterUserFunc为测试对象添加新方法或重写已有方法

    QTP中为了提高扩展性,提供了一个为测试对象添加一个新的自定义方法,或者重写测试对象已有的方法的函数RegisterUserFunc,在此给大家分享一下. RegisterUserFunc:为测试对象 ...

  5. 部署和调优 1.1 nfs部署和优化-2

    更改共享目录文件默认的所有者和所属组 已知道客户端有个user11用户 cat /etc/passwd user11:x:501:501::/home/user11:/bin/bash 服务端打开 v ...

  6. C#高级参数ref的使用

    ref关键字用于将方法内的变量改变后带出方法外.具体我们通过例子来说明: 例子中,将变量n1和n2交换了.如果没有加ref参数,由于没有swadDemo()方法没有返回值,调用后,n1和n2是不会交换 ...

  7. java之类的封装

    类和对象成员变量,成员函数特殊的成员变量和成员函数 函数重载 构造函数 静态变量 静态函数面向对象:封装 继承 多态封装 Encapsulation为什么需要封装?外界无法直接操作对象的具体的属性(安 ...

  8. POJ 1151 扫描线 线段树

    题意:给定平面直角坐标系中的N个矩形,求它们的面积并. 题解:建立一个四元组(x,y1,y2,k).(假设y1<y2)用来储存每一条线,将每一条线按x坐标排序.记录所有的y坐标以后排序离散化.离 ...

  9. 【转】nginx+memcached构建页面缓存应用

    如需转载请注明出处: http://www.ttlsa.com/html/2418.html nginx的memcached_module模块可以直接从memcached服务器中读取内容后输出,后续的 ...

  10. 一个ButtonDemo序(遇到的问题,以及在大牛的帮助下,如何解决的。)

    问题1: public ButtonDemo(){ //ImageIcon leftButtonIcon=new ImageIcon("images/a.png"); ImageI ...