一、背景介绍
CyanogenMod(简称CM):Cyanogen团队是基于开源的AOSP源码的,目前全球最大的Android第三方编译团队。用户可以通过CM源码编译出适用特定机型的刷机包,并将编译出来的刷机包刷到相应的手机里。
Cyanogenmod官方支持的手机设备类型有Htc、Samsung、Huawei、Sony等其各自旗下的主流型号,通过以下网址可以查看Cyanogenmod官方支持的手机设备及对应CM版本。
http://wiki.cyanogenmod.org/w/Devices#vendor=;
编译环境的相关信息如下:
源码下载编译环境 |
Ubuntu 12.04 32bit虚拟机 |
2g 内存 60g硬盘 处理器1 |
虚拟机信息 |
VMware Workstation 10.0.3 |
|
测试机 |
HTC Wildfire Buzz(G8) |
|
CM源码版本 |
gingerbread-release (CM7) (android 2.3.7) |
(Android 2.3系统限制必须使用32位的操作系统)
(处理器核心数越多编译速度越快)(虚拟机的硬盘容量最好设置的足够大)
二、编译环境搭建
1、修改Ubuntu的hosts
使用
sudo gedit /etc/hosts
修改hosts信息,使用
sudo /etc/init.d/networking restart
重启网络连接。Hosts文件内容如下:
173.194.123.68 www.google.com 173.194.123.68 code.google.com 203.208.46.172 cache.pack.google.com 173.194.72.82 android.googlesource.com 192.30.252.129 github.com
2、安装JDK6和安卓sdk,并配置相应的环境变量
3、安装编译所需要的包(ubuntu 12.04 32bit)
sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev libc6-dev libncurses5-dev x11proto-core-dev libx11-dev libreadline6-dev libgl1-mesa-dev tofrodos xsltproc python-markdown libxml2-utils schedtool
4、下载repo
在新建的CM源码目录下执行以下命令(本文使用~/CMSOURCE文件夹):
$ curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo $ chmod a+x ~/bin/repo $ export PATH=${PATH}:~/bin
初始化repo参数 (-j16表示开启多个网络连接,提高下载速度)
$ repo init -u git://github.com/CyanogenMod/android.git -b gingerbread-release $ repo sync -j16
断网自动下载脚本down.sh(放在CM源码目录下),使用sh命令执行:
#!/bin/sh repo sync -j16 while [ $? -ne 0 ] do repo sync -j16 done
5、下载过程中出现的问题整理:
5.1 svox相关问题
fatal: remote error: Repository unavailable due to DMCA takedown. See the takedown notice for more details: https://github.com/github/dmca/blob/master/2014-12-22-Cambridge-Mobile.md. Fetching projects: 99% (277/279) fatal: remote error: Repository unavailable due to DMCA takedown. See the takedown notice for more details: https://github.com/github/dmca/blob/master/2014-12-22-Cambridge-Mobile.md. error: Cannot fetch CyanogenMod/android_external_svox
解决方法:
使用”<!--注释内容-->”注释掉~/CMSOURCE/.repo/manifest/default.xml中svox所在行
5.2 硬盘空间不足
正在检出文件: 100% (1942/1942), 完成.在检出文件: 11% (228/1942) error: unable to write file WebKitTools/DumpRenderTree/mac/ PerlSupport/DumpRenderTreeSupportTiger.pm fatal: cannot create directory at 'WebKitTools/DumpRenderTree/pthreads': ??????? Traceback (most recent call last): File "/home/ubuntu/.repo/repo/main.py", line 408, in <module> _Main(sys.argv[1:]) File "/home/ubuntu/.repo/repo/main.py", line 388, in _Main result = repo._Run(argv) or 0 File "/home/ubuntu/.repo/repo/main.py", line 138, in _Run result = cmd.Execute(copts, cargs) File "/home/ubuntu/.repo/repo/subcmds/sync.py", line 585, in Execute project.Sync_LocalHalf(syncbuf) File "/home/ubuntu/.repo/repo/project.py", line 1015, in Sync_LocalHalf self._InitWorkTree() File "/home/ubuntu/.repo/repo/project.py", line 1801, in _InitWorkTree raise GitError("cannot initialize work tree") error.GitError: cannot initialize work tree
解决方法:
推测是因为空间不足而导致的无法创建目录行为。
检出文件的过程是将.repo中的文件抽取/复制到初始化repo命令的文件夹内,因此所占的硬盘空间容量较大。之前若设置的虚拟机硬盘空间不够大,可采用虚拟硬盘扩展及清理硬盘空间的方式来解决。
6、下载完毕
Fetching projects: 100% (278/278), done. Checking out files: 100% (2540/2540), done. Checking out files: 100% (3855/3855), done. ...(省略了多个Checking out files...) Checking out files: 100% (1330/1330), done. Syncing work tree: 100% (278/278), done.
7、配置ubuntu虚拟机下的usb访问权限
将手机连接到虚拟机,运行$ lsusb 命令查看当前连接的信息:
ubuntu@ubuntu:~$ lsusb Bus 001 Device 029: ID 0bb4:0c8b High Tech Computer Corp. Bus 002 Device 002: ID 0e0f:0003 VMware, Inc. Virtual Mouse Bus 002 Device 003: ID 0e0f:0002 VMware, Inc. Virtual USB Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 002 Device 008: ID 0e0f:0008 VMware, Inc.
记录下ID 0bb4:0c8b,作为HTC buzz手机adb协议id信息。再将手机重启到fastboot模式(htc手机是电源键+音量减键),
运行lsusb命令,记录fastboot协议id信息。 随后运行$sudo gedit /etc/udev/rules.d/51-android.rules命令,新建/编辑文件,内容如下:
# adb protocol on passion (Nexus One) SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e12", MODE="0600", OWNER="<ubuntu>" # fastboot protocol on passion (Nexus One) SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4", ATTR{idProduct}=="0fff", MODE="0600", OWNER="<ubuntu>" # adb protocol on crespo/crespo4g (Nexus S) SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e22", MODE="0600", OWNER="<ubuntu>" # fastboot protocol on crespo/crespo4g (Nexus S) SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e20", MODE="0600", OWNER="<ubuntu>" # adb protocol on stingray/wingray (Xoom) SUBSYSTEM=="usb", ATTR{idVendor}=="22b8", ATTR{idProduct}=="70a9", MODE="0600", OWNER="<ubuntu>" # fastboot protocol on stingray/wingray (Xoom) SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="708c", MODE="0600", OWNER="<ubuntu>" # adb protocol on maguro/toro (Galaxy Nexus) SUBSYSTEM=="usb", ATTR{idVendor}=="04e8", ATTR{idProduct}=="6860", MODE="0600", OWNER="<ubuntu>" # fastboot protocol on maguro/toro (Galaxy Nexus) SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e30", MODE="0600", OWNER="<ubuntu>" # adb protocol on panda (PandaBoard) SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d101", MODE="0600", OWNER="<ubuntu>" # fastboot protocol on panda (PandaBoard) SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d022", MODE="0600", OWNER="<ubuntu>" # usbboot protocol on panda (PandaBoard) SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d00f", MODE="0600", OWNER="<ubuntu>" # usbboot protocol on panda (PandaBoard ES) SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d010", MODE="0600", OWNER="<ubuntu>" # adb protocol on grouper/tilapia (Nexus 7) SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e42", MODE="0600", OWNER="<ubuntu>" # fastboot protocol on grouper/tilapia (Nexus 7) SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e40", MODE="0600", OWNER="<ubuntu>" # adb protocol on manta (Nexus 10) SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4ee2", MODE="0600", OWNER="<ubuntu>" # fastboot protocol on manta (Nexus 10) SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4ee0", MODE="0600", OWNER="<ubuntu>" # adb protocol on wildfire (HTC G8 buzz)(HT0B6PY06404) SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4", ATTR{idProduct}=="0c8b", MODE="0666", OWNER="<ubuntu>" # fastboot protocol on wildfire (HTC G8 buzz)(HT0B6PY06404) SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4", ATTR{idProduct}=="0fff", MODE="0666", OWNER="<ubuntu>"
其中OWNER为虚拟机使用者的名称,加粗的内容就是利用之前记录下的id号添加的连接识别信息,对应规则如下:
Bus 001 Device 029: ID 0bb4:0c8b High Tech Computer Corp. ATTR{idVendor}=="0bb4", ATTR{idProduct}=="0c8b"
编辑完毕并保存之后,调用adb devices命令即可查看当前连接到虚拟机的手机设备信息:
ubuntu@ubuntu:~$ adb devices
List of devices attached
HT0B6PY06404 device
不进行配置的手机通过adb devices查看时,会给出insufficient permissions for device的提示信息。
三、编译源码
源码下载完毕之后的整个CMSOURCE文件夹内容如图所示:
打开~/CMSOURCE/device/htc可以看见buzz文件夹。(即测试机对应文件夹)
1、读取手机上的私有配置文件
$cd ~/CMSOURCE/device/htc/buzz $./extract-files.sh
输出:
(读取失败可能是由于手机处于offline的状态,把手机多连接几次,用adb devices查看时处于device状态就可以了)
2、生成编译脚本,配置Rom Manager
$cd ~/CMSOURCE/vendor/cyanogen
$./get-rommanager
输出:
3、初始化编辑配置信息
$ cd ~/CMSOURCE/ $ source build/envsetup.sh $ lunch
Source一句输出:
including device/advent/vega/vendorsetup.sh including device/htc/bravoc/vendorsetup.sh including device/htc/bravo/vendorsetup.sh including device/htc/buzz/vendorsetup.sh ...(省略了including device/多款机型...) including vendor/cyanogen/vendorsetup.sh
lunch一句输出:
You're building on Linux Lunch menu... pick a combo: 1. full-eng ...(省略多个选项) 91. cyanogen_bravoc-eng 92. cyanogen_buzz-eng ...(省略多个选项) 152. cyanogen_zeusc-eng Which would you like? [full-eng]
本次编译选择的是 92. cyanogen_buzz-eng ,输入完92点击回车后会输出(正常情况下):
============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=2.3.7 TARGET_PRODUCT=cyanogen_buzz TARGET_BUILD_VARIANT=eng TARGET_SIMULATOR=false TARGET_BUILD_TYPE=release TARGET_BUILD_APPS= TARGET_ARCH=arm TARGET_ARCH_VARIANT=armv6j HOST_ARCH=x86 HOST_OS=linux HOST_BUILD_TYPE=release BUILD_ID=GINGERBREAD ============================================
4、配置CCAHE(编译器缓存,提高二次编译速度)
export USE_CCACHE=1
5、开始编译,执行以下两条命令
$ croot
$ brunch buzz
croot命令的作用是:Changes directory to the top of the tree
brunch命令的作用是:执行breakfast命令和mka bacon命令,其中mka表示Builds using SCHED_BATCH on all processors
6、编译过程中的相关错误整理:
6.1 执行lunch命令,选择92后报错
Which would you like? [full-eng] 92 build/target/product/sdk.mk:185: external/svox/pico/lang/PicoLangDeDeInSystem.mk: 没有那个文件或目录 ...(省略了多个没有那个文件或目录...) external/svox/pico/lang/PicoLangFrFrInSystem.mk: 没有那个文件或目录 build/target/product/sdk.mk:190: external/svox/pico/lang/PicoLangItItInSystem.mk: 没有那个文件或目录 build/core/product_config.mk:194: *** _nic.PRODUCTS.[[vendor/cyanogen/products/cyanogen_olympus.mk]]: "device/motorola/olympus/olympus.mk" does not exist。 停止。 ** Don't have a product spec for: 'cyanogen_buzz' ** Do you have the right repo manifest?
从错误提示中可以看出错误原因有二,一是找不到svox目录下的相关文件,二是olympus设备的.mk文件不存在,因此针对这二者分别执行修正方案:
1) 将~/CMSOURCE/build/target/product目录内的sdk.mk中包含svox的行都注释掉(mk文件用#号注释掉)。
2) 修改~/CMSOURCE/vendor/cyanogen/products/AndroidProducts.mk 文件,删除:
$(LOCAL_DIR)/cyanogen_olympus.mk
6.2 没有external/webkit路径下的某个目录
external/webkit/Android.mk:83: external/webkit/bison_check.mk: 没有那个文件或目录 external/webkit/Android.mk:403: external/webkit/WebKitTools/android/webkitmerge/Android.mk: 没有那个文件或目录 find: `out/target/common/docs/gen': 没有那个文件或目录 find: `out/target/common/docs/gen': 没有那个文件或目录 find: `out/target/common/docs/gen': 没有那个文件或目录 find: `out/target/common/docs/gen': 没有那个文件或目录 find: `out/target/common/docs/gen': 没有那个文件或目录 build/core/Makefile:21: 警告:覆盖关于目标“out/target/product/buzz/system/usr/keychars/qwerty.kcm.bin”的命令 build/core/base_rules.mk:473: 警告:忽略关于目标“out/target/product/buzz/system/usr/keychars/qwerty.kcm.bin”的旧命令 build/core/Makefile:21: 警告:覆盖关于目标“out/target/product/buzz/system/usr/keychars/qwerty2.kcm.bin”的命令 build/core/base_rules.mk:473: 警告:忽略关于目标“out/target/product/buzz/system/usr/keychars/qwerty2.kcm.bin”的旧命令 build/core/Makefile:21: 警告:覆盖关于目标“out/target/product/buzz/system/usr/keylayout/AVRCP.kl”的命令 sdk/emulator/keymaps/Android.mk:18: 警告:忽略关于目标“out/target/product/buzz/system/usr/keylayout/AVRCP.kl”的旧命令 build/core/Makefile:21: 警告:覆盖关于目标“out/target/product/buzz/system/usr/keylayout/qwerty.kl”的命令 sdk/emulator/keymaps/Android.mk:13: 警告:忽略关于目标“out/target/product/buzz/system/usr/keylayout/qwerty.kl”的旧命令 No private recovery resources for TARGET_DEVICE buzz make: *** 没有规则可以创建目标“external/webkit/WebKitTools/android/webkitmerge/Android.mk”。 停止。
推测可能与文件创建权限等有关,因此根据报错内容在相应位置创建空白的文件,之后就不报错了。
6.3 找不到文件CSSGrammar.cpp、CSSGrammar.h、tokenizer.flex
去网上搜索下载到对应位置即可。参考链接:
http://sourceforge.jp/projects/gb-231r1-is01/scm/git/Gingerbread_2.3.3_r1_IS01/tree/master/
http://www.pudn.com/downloads551/sourcecode/unix_linux/detail2274635.html
6.4 CSSGrammar.y中调用方法出错
css/CSSGrammar.y: In function 'int cssyyparse(void*)': css/CSSGrammar.y:795: error: 'class WebCore::CSSParser' has no member named 'updateLastSelectorLine' css/CSSGrammar.y:803: error: 'class WebCore::CSSParser' has no member named 'updateLastSelectorLine' css/CSSGrammar.y:1176: error: 'class WebCore::CSSSelector' has no member named 'matchesPseudoElement' make: *** [out/target/product/buzz/obj/STATIC_LIBRARIES/libwebcore_intermediates/WebCore/CSSGrammar.o] 错误 1
注释掉
/out/target/product/buzz/obj/STATIC_LIBRARIES/libwebcore_intermediates/WebCore/CSSGrammar.cpp
中相应方法调用部分的内容即可。
7、编译成功的输出
...(省略了多个Optimizing .apk...) Optimizing CMStats.apk... Optimizing CMParts.apk... Optimizing Stk.apk... Zipping package... Signing package... Cleaning up... Package complete: /CMSOURCE/out/target/product/buzz/update-cm-7.1.0.1-buzz-KANG-signed.zip 10d9549bc45e81fe4b7b8e6fef415f98 update-cm-7.1.0.1-buzz-KANG-signed.zip
其中的update-cm-7.1.0.1-buzz-KANG-signed.zip就是刷机包zip文件。再次生成可调用脚本文件:
./vendor/cyanogen/tools/squisher
四、刷机
1、获得S-OFF,并在设备上安装自定义recovery
1.1 s-on刷s-off
Android智能手机在刷机过程中,SPL(Second Program Loader)需要根据CID校验ROM是否可用,并决定是否刷入。一般情况下要求一定要对应CID的ROM才可以用,CID不同的ROM是刷不上去的。
因此,要刷入不同手机平台版本(CID)的ROM需要在关闭安全锁,即S-OFF的状态下进行,其中的S代表 Security Lock安全锁。
对于本文中的测试机HTC buzz可以使用http://revolutionary.io中提供的工具将s-on刷成s-off。
1.2 安装自定义recovery
在编译成功后存放刷机zip包的相同目录下,包含了自定义的recovery.img。进入到该目录下,执行命令让手机重启,并且进入Fastboot模式:
$ adb reboot bootloader
刷入编译生成的Recovery。
$ fastboot flash recovery recovery.img
提示刷入成功后,执行以下命令正常重启手机:
$ fastboot reboot
2、通过recovery安装CM刷机文件
继续在刚才的路径下执行以下命令,将编译生成的刷机包上传到手机的sd卡上:
$adb push update-cm-7.1.0.1-buzz-KANG-signed.zip /mnt/sdcard/update-cm-7.1.0.1-buzz-KANG-signed.zip
执行以下命令让手机重启,并且进入Recovery模式:
$adb reboot recovery
在Recovery界面上,通过音量增大/减小键,选中“install zip from sdcard”选项,按下确认键,进入下一个界面。同样是通过音量增大/减小键,选中
choose zip from sdcard,按下确认键,找到之前上传到sdcard的zip文件,确认之后就可以进行刷机了。
安装完毕后,屏幕上会提示Install from sdcard complete。之后回到Recovery界面上,通过音量增大/减小键,选中reboot system now选项,按下确认键,正常启动系统。
(注:HTC Buzz手机的电源键表示退出,而非确定)
3、刷机后的效果图
五、参考资料
1、http://blog.csdn.net/andie_guo/article/details/16879443
2、http://blog.csdn.net/androiddevelop/article/details/8661120
3、http://blog.csdn.net/luoshengyang/article/details/29688041