Android编译环境的搭建一向不太统一,官方只提供了Ubuntu的搭建方式,Fedora,Archlinux,MacOS的用户大多需要自己摸索编译环境。
Docker虚拟机相比裸机编译,最大的优势就是所有平台方法统一,无论本来的操作系统是什么,配置方法都是一样。
相比于其他虚拟机的方式,轻量级的Docker能够最大限度的利用系统资源,实编译时间与裸机编译差距不大。
1. 硬件需求
本机硬件:i7-7700HD,8G,5400HDD
完整编译米4(cancro)代码和生成文件大约113G,编译过程大概需要227分钟。
完整编译米6(sagit)代码和生成文件大约160G,完整编译时间大约310分钟。
2. 代码同步
下载repo
魔趣使用的repo是自己修改过的,墙内就可以下载mokee代码。github地址:https://github.com/MoKee/git-repo ,压缩包下载地址:repo。
解压后把里面的repo复制到~/bin目录下。
更新repo自己
$ ~/bin/repo selfupdate
同步mokee源码
$ ~/bin/repo init -u https://github.com/MoKee/android -b mkp --depth 1 --platform=auto
$ export MK_AOSP_REMOTE=tuna
$ ~/bin/repo sync
同步的过程非常漫长,而且因为网络不稳定,有中断的可能,repo sync命令可能需要做一些防打断的措施:
$ mysystemnothiscommand; while [ $? -ne 0 ]; do ~/bin/repo sync --current-branch --force-broken --no-clone-bundle ; done
这里的环境变量MK_AOSP_REMOTE指定了清华的镜像源。其他选项如下:
$ export MK_AOSP_REMOTE=caf (高通镜像)
$ export MK_AOSP_REMOTE=ustc (中国科学技术大学镜像)
$ export MK_AOSP_REMOTE=tuna (清华大学镜像)
$ export MK_AOSP_REMOTE=aosp (Google镜像)
3. 完整编译
这里提供两个方法,archlinux下裸机编译速度会更快一些,缺点是比较复杂,要改动系统文件,方法和别的平台不同用。
另一个是Docker编译,只用输入一行命令,前提是本机已经装上了Docker。
3.1 archlinux下裸机编译
archlinux的包和ubuntu不太一样,需要做点修改:
$ sudo ln -s /usr/bin/python2 /usr/local/bin/python
$ sudo ln -s /usr/lib/libncursesw.so /usr/lib/libtinfo.so.5
$ sudo ln -s /usr/lib/libncurses.so /usr/lib/libncurses.so.5
进入源码目录执行:
$ . build/envsetup.sh
$ lunch mk_cancro-userdebug
$ mka bacon
小米3和小米4的设备名称都是cancro,如果是小米6,就把上面的cancro改成sagit。
首次lunch的时候会同步小米4设备相关的代码,所以如果和之前的步骤不连续,需要再次声明镜像地址,避免repo又去拉Google仓库:
$ export MK_AOSP_REMOTE=tuna
3.2 docker中编译
docker的安装方法请自行求助于搜索引擎。
编译前进入android源码目录编译小米6:
$ docker run --rm -v ${PWD}:/android chenchacha/aosp:latest bash -c "MK_AOSP_REMOTE=tuna; cd /android; . build/envsetup.sh; lunch mk_sagit-userdebug; mka bacon"
sagit是小米6的代号,其他系统请根据设备名称替换。
如果遇到这样的报错:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
这是Docker没有启动,用systemctl启动docker:
$ systemctl start docker
如果本地没有chenchacha/aosp镜像,docker会在编译前下载。
如果代码是新的,执行lunch的时候也会下载代码,这里用MK_AOSP_REMOTE=tuna指定了清华的镜像源。从其他的镜像地址同步源码可以自行替换。
4. 增量编译
声明生成OTA包的位置:
$ export MK_OTA_TARGET_PATH=~/Templates/MoKee/ota/target
$ export MK_OTA_INPUT=~/Templates/MoKee/ota/target
$ export MK_OTA_EXTRA=~/Templates/MoKee/ota/patch
生成增量包:
$ ota_all UNOFFICIAL dumpling
5. Bug fix
5.1
执行repo sync的时候遇到类似这样的错误:
repo sync
remote: Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
Traceback (most recent call last):
File "/home/xxx/Workspace/android/mokee/source/.repo/repo/main.py", line 547, in
_Main(sys.argv[1:])
File "/home/xxx/Workspace/android/mokee/source/.repo/repo/main.py", line 522, in _Main
result = repo._Run(argv) or 0
File "/home/xxx/Workspace/android/mokee/source/.repo/repo/main.py", line 184, in _Run
result = cmd.Execute(copts, cargs)
File "/home/xxx/Workspace/android/mokee/source/.repo/repo/subcmds/sync.py", line 753, in Execute
if mp.HasChanges:
File "/home/xxx/Workspace/android/mokee/source/.repo/repo/project.py", line 3076, in HasChanges
elif self._revlist(not_rev(HEAD), revid):
File "/home/xxx/Workspace/android/mokee/source/.repo/repo/project.py", line 2619, in _revlist
return self.work_git.rev_list(*a, **kw)
File "/home/xxx/Workspace/android/mokee/source/.repo/repo/project.py", line 2819, in rev_list
(self._project.name, str(args), p.stderr))
error.GitError: manifests rev-list ('^HEAD', u'cba7c060ce06d8befa686c1033d1b5cc8639960c', '--'): error: Could not read 291f1cf611067e09f35494ca5190a88def84ed2d
fatal: revision walk setup failed
这是mokee的manifests变基之后扔了提交导致的。
进入.repo目录,删除下面的manifests目录,重新下载,并把本地分支关联到相应的版本:
$ git https://github.com/MoKee/android.git manifests
$ cd manifests
$ git checkout -b default origin/mkp
5.2
Fetching project platform/external/spirv-llvm
Exception in thread Thread-471:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "/home/xxx/Workspace/android/mokee/source/.repo/repo/subcmds/sync.py", line 282, in _FetchProjectList
success = self._FetchHelper(opt, project, *args, **kwargs)
File "/home/xxx/Workspace/android/mokee/source/.repo/repo/subcmds/sync.py", line 327, in _FetchHelper
prune=opt.prune)
File "/home/xxx/Workspace/android/mokee/source/.repo/repo/project.py", line 1261, in Sync_NetworkHalf
self._InitGitDir(force_sync=force_sync)
File "/home/xxx/Workspace/android/mokee/source/.repo/repo/project.py", line 2366, in _InitGitDir
raise e
GitError: --force-sync not enabled; cannot overwrite a local work tree. If you're comfortable with the possibility of losing the work tree's git metadata, use `repo sync --force-sync external/libpng` to proceed.
这样的错误是xml换了目录名或者库地址。按控制台提示,repo sync的时候加上--force-sync参数:
$ repo sync --force-sync
5.3
编译的过程中有以下报错:
ERROR: signapk.jar failed: return code 1
ninja: build stopped: subcommand failed.
13:44:04 ninja failed with: exit status 1
往前面还能看到出错的点:
running: java -Xmx2048m -Djava.library.path=/home/xxxxcorg.bouncycastle.cms.CMSException: data processing exception: java.io.IOException: No space left on device
以及这样的报错:
FAILED: /home/xxxx/Workspace/android/mokee/source/out/target/product/sagit/mk_sagit-ota-eng.chenchacha.zip
用IO监控看了看,发现这是/tmp目录太小,打包的时候空间不够导致的。
所以把/tmp目录大小改为10G:
$ mount -o remount,size=10G /tmp/
打包不再报错。
5.4
TWRP刷机的时候报错,显示类似错误:
wrong firmware
...
abort(), ERROR:7
这种错误一般称之为底包不对。我这里应该是小米6的MIUI升级导致TrustZone版本不对,可以去找老一点的稳定版MIUI线刷更新底包,也可以强行刷机。
解压zip文件, 编辑META-INF/com/google/android/updater-script,把其中的abort()函数删除,重新打包成zip。
再用adb刷上去即可。
强行刷机的系统TrustZone异常,指纹不能用,需要后期继续开发。
参考文献
https://bbs.mokeedev.com/t/topic/21
https://bbs.mokeedev.com/t/topic/627
https://bbs.mokeedev.com/t/topic/7806