由于CM团队不在提供服务而转战lineageOS,我们仍可以通过构建一个lineageOS来对Android源码进行学习。下面就对如何构建一个lineageOS的具体步骤进行一个描述,并且把我所遇到的问题进行展示,希望能够帮到同样需要学习的人。
先决条件
-
首先你需要一台Nexus6手机并且刷入了最新的lineageOS,我刷入的系统为14.1版本,具体如何刷入lineageOS,可参考https://wiki.lineageos.org/devices/shamu/,上面也有介绍如何build环境,这是本文的重要参考来源。
-
需要有一台装有Linux系统的电脑,我使用的是ubuntu16.04,个人感觉可能14.04的稳定性更好一些,因为网上有很多人和我一样使用16.04的系统在编译环节出现一些问题。这些会在后面提到。电脑最好为8G的内存,硬盘至少要有150G的大小。
-
需要一个稳定的代理,有问题上谷歌是必须的,而且我们需要从外网下载源码。
下面我们开始:
1 安装SDK并配置好SDK的路径。因为我们要使用到adb等工具。
2 我们还需要使用aptinstall <安装包>命令来安装一些包。我们可以再终端输入以下命令:
sudo apt install bcbison build-essential curl flex g++-multilib gcc-multilib git gnupggperf imagemagick lib32ncurses5-dev lib32readline-gplv2-devlib32z1-dev libesd0-dev liblz4-tool libncurses5-dev libsdl1.2-devlibssl-dev libwxgtk2.8-dev libxml2 libxml2-utils lzop pngcrush rsyncschedtool squashfs-tools xsltproc zip zlib1g-dev
如果你使用的是ubtuntu15.10你需要将命令中的lib32readline-gplv2-dev替换成lib32readline6-dev,如果你使用的是ubtuntu16.04,你还需要将命令中的libwxgtk2.8-dev替换成libwxgtk3.0-dev
如果你刷入的也是LineageOS14.1,则需要在你的linux系统中安装OpenJDK1.8的。
3 我们需要创建一些目录
$ mkdir -p ~/bin
$ mkdir -p ~/android/lineage
4
我们需要安装
repo
来下载源码到本地电脑,这里我遇到了
第一个问题
,官方文档中说只要我们执行以下命令。
$ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
$ chmod a+x ~/bin/repo
再将下面文本配置到配置文件~/.profile
中
,我们就可以使用
repo
了。
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
要确保在配置文件中加入文本后执行命令
source~/.profile
,这是为了更新运行环境。
随后我们执行命令
:
$cd ~/android/lineage
$ repo init -u https://github.com/LineageOS/android.git -b cm-14.1
会出现以下错误
:
fatal: Cannot get https://gerrit.googlesource.com/git-repo/clone.bundle fatal: error [Errno 101] Network is unreachable 具体解决方案:http://blog.youkuaiyun.com/xiaokeweng/article/details/46743409 该博客大神提供了两种解决方案,问题产生的原因也在博客里进行了说明,我使用的是第二种解决方案,下载了一个新的repo而不使用谷歌官方文档中提供的repo, 具体下载链接为http://download.youkuaiyun.com/detail/xiaokeweng/8872981,也是由上述博客大神提供的。 将repo下载好之后,在使用repo文件夹里的repo文件之前一定要执行命令:$
chmod a+x ~/
你下载的
repo
的路径
/repo
要不然会报权限问题的错误。一切准备就绪,我们需要使用
~/
你下载的
repo
的路径
/repo init -u https://github.com/LineageOS/android.git -b cm-14.1
命令来替换
repo init -u https://github.com/LineageOS/android.git -b cm-14.1
命令
再执行
repo sync
命令我们就可以把源码下载到本机电脑。然而代码下载经常失败,我们可以用
BASH
写一个循环不停下载。
#!/bin/bash
while :
do
reposync
done
如果下载过程中总有某个项目失败,则可单独下载该项目在项目根目录下运行
repo sync kernel/moto/shamu
切记
repo sync
一定要下载完全,要不然在后面的操作中经常会出现一些错误,说你缺少文件,有的时候
repo sync
已经提示下载完全,我第一次
repo sync
下载下来了
594
个项目,提示完成
100%
,然而在后面的操作中还是出现了问题
,一直不知道是哪里出现的问题,上
各种查也没找到很好的解决方案,结果我执行了一下
repo sync
命令,下载项目变成了
595
个,又下载下来一个子项目,解决了我后面的问题,我后面还会具体提到,切记
repo sync
一定要下载完全,切记!
5
接下来我们在目录
/android/lineage
中执行以下命令。
$ source build/envsetup.sh
$ breakfast shamu
结果出现了我遇到的
第二个问题
,是一个关于
shamu
不存在于库的问题,具体问题我没有保存下来,然而当我单独执行
breakfast
看清单列表时是有对应的
shamu
文件的,
没有查到太明确的解决方案。最后在我再次执行了
repo sync
之后,发现又多下载了一些文件,这个时候再执行上面两条命令就可以完美通过了,这时候
repo sync
的项目数达到了
595
个,后面遇到新问题还会达到
596
个,欲哭无泪。
6
接我来我们在目录
/android/lineage/vendor/moto
中执行命令
$ ./extract-files.sh
(第三个问题)
该命令会提取你手机设备的相关信息
,我一开始是在
Windows
系统中
安装
了一个虚拟机,然后在虚拟机中的
ubuntu
环境下来
build lineageOS
的,在这条命令执行的过程中总是卡主,或者执行到一半就卡住了,这个问题没有很好的解决,最后发现应该是虚拟机
usb
驱动存在问题,使得
adb
经常会莫名其妙被
Kill
,所以我换了一台纯
linux
系统的电脑,该命令就没有遇到任何的障碍,一次性通过了。
(第四个问题)
但是在执行这个命令的时候有一个文件
libfsdk.so
文件不存在,我当时没有在意,这在我后面编译的时候造成了新的麻烦,所以说在编译源码的过程中一点点错误都不能存在的,要不然就会导致编译不成功,或者编译成功了刷机也会让手机开不开机,一定要谨小慎微。具体解决方案在后面问题出现的时候会提到。
值得一提的是不知道为何
,我在执行该命令时需要在
root
用户权限下才能执行,在普通用户权限下执行会提示各种没有权限,身边人说应该在普通用户下就能操作的,
root
用户下提取可能会出现一些问题,好在最后编译成功,但是这个问题我也不知道是什么原因造成的,如果有哪位朋友知道可以帮我解惑,多谢。
7
接下来为了提升编译的速度我们会对系统进行一些配置,这些步骤很简单,我就不重复描述,在文章开始提供的官方文档中一步步操作就可以,也没有遇到什么问题。
8
最后我们只需要执行
$ croot
$ brunch shamu
就可以开始编译我们的源码了,如果这里提示
croot
或者
brunch
命令不存在之类的问题,要确保终端先执行了以下命令。
$ source build/envsetup.sh
下面进入编译环节
:
(第五个问题)
编译一开始就出现了问题,大概是
kernel
文件夹什么的不存在,我
到文
件目录中去看,确实缺少它说的文件夹,
无果之后,由于吃过
repo sync
的亏,我就又执行了一遍
repo sync
,这个时候项目数从
595
变成了
596
,又下载了许多新的项目文件夹。这个问题很奇怪,我
repo sync
执行过很多遍,在不出现问题的时候你怎么操作他都不会下载下来新的项目文件,也不会报任何错误,会告诉你最后完成度为
100%
,一旦出现了问题,你再回首去操作,就会下载下来新的东西,这是我百思得其解的地方。反正总之下载下来一些新的文件之后,这个问题也得到了完美的解决。
(第六个问题)
问题层出不穷,特别是编译环节出现的问题,非常难排查,这个问题也是出现在编译开始的阶段,
remote object '/system/vendor/lib/libfrsdk.so' does not exist
大概意思是说缺少
libfsdk.so
文件,这就是前面所说执行
./extract-files.sh
命令的时候存在的隐患,然而一开始我并不知道,因为在编译源码的过程中会打印出大量的信息,你不可能每条都看到都看懂,所以一开始我并不知道这个文件是干什么用的,应该怎么解决。惯性思维让我觉得是
repo
时又下载少了东西,所以我一直各种执行
repo sync
但是结果并没有改变,最后项目数字也是停留在
596
。
596
这个数字并不适用于所有人,随着
lineageOS
的更新这个数字肯定是一直在变化的,变多变少都有可能
,所以它只能作为一个参考。
由于是缺失文件所以肯定是哪个步骤出现了问题,导致文件没有下载完全或者没有提取完全,在尝试了大量的办法之后我开始去执行前面可能会造成这个问题的命令,直到执行到
./extract-files.sh
时
,我发现终端上打印了一条信息就是说
libfsdk.so
文件不存在。所以我知道该文件应该存在于手机中,我在手机对应的文件夹下去搜索该文件确实没有。
这个里提供一个网站
https://github.com/TheMuppets/proprietary_vendor_motorola
在这个网站提供的链接中找到你对应的手机型号,在对应的文件夹里下载你所缺少的
.so
文件,我在这里将
libfsdk.so
下载下来并直接拷贝到了对应的文件夹中
,该问题就得到了良好的解决,切记不能随便百度一个
libfsdk.so
文件进行下载,即使这样你能编译过去,也会导致无法适配让你在刷机阶段出现问题。一定要下载与你手机匹配的
.so
文件!
解决了这个问题之后,我的编译终于开始了。编译一路高歌猛进,直到编译到
54%
的时候,出现了一个让我最头疼的问题。
(第七个问题)
FAILED: /bin/bash -c"(./vendor/cm/build/tasks/http_curl_prebuilt.sh https://github.com/LineageOS/android_packages_apps_Gello/releases/download/40/gello.apk.md5sumvendor/cm/prebuilt/archive/Gello/md5sum ) && (if [ ! -fvendor/cm/prebuilt/archive/Gello/gello.apk ]; then echo\"Downloading: gello.apk (version 40) ->vendor/cm/prebuilt/archive/Gello/gello.apk\"; ./vendor/cm/build/tasks/http_curl_prebuilt.sh https://github.com/LineageOS/android_packages_apps_Gello/releases/download/40/gello.apkvendor/cm/prebuilt/archive/Gello/gello.apk; elsetemp_checksum=\$(md5sum vendor/cm/prebuilt/archive/Gello/gello.apk |cut -d ' ' -f1); if [ \"\$temp_checksum\" != \"\$(catvendor/cm/prebuilt/archive/Gello/md5sum | cut -d ' ' -f1)\" ];then echo \"Downloading: gello.apk (version 40) ->vendor/cm/prebuilt/archive/Gello/gello.apk\"; rm -rfvendor/cm/prebuilt/archive/Gello/gello.apk; ./vendor/cm/build/tasks/http_curl_prebuilt.sh https://github.com/LineageOS/android_packages_apps_Gello/releases/download/40/gello.apkvendor/cm/prebuilt/archive/Gello/gello.apk; fi; fi; rm -fvendor/cm/prebuilt/archive/Gello/md5sum ) && (echo \"Copying:gello.apk ->/home/yangzhiyu/android/lineage/out/target/common/obj/APPS/Gello_intermediates/\") && (mkdir -p/home/yangzhiyu/android/lineage/out/target/common/obj/APPS/Gello_intermediates/) && (cp vendor/cm/prebuilt/archive/Gello/gello.apk/home/yangzhiyu/android/lineage/out/target/common/obj/APPS/Gello_intermediates//gello.apk)"
%Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 596 0 596 0 0 47 0 --:--:-- 0:00:12 --:--:-- 131
0 0 0 0 0 0 0 0 --:--:-- 0:02:23 --:--:-- 0curl: (7) Failed to connect to github-cloud.s3.amazonaws.com port443: 连接超时
[54% 18850/34493] target thumb C++: libv8 <=external/v8/src/compiler/simplified-lowering.cc
ninja:build stopped: subcommand failed.
build/core/ninja.mk:151:recipe for target 'ninja_wrapper' failed
make:*** [ninja_wrapper] Error 1
make:Leaving directory '/home/yangzhiyu/android/lineage'
####make failed to build some targets (54:09 (mm:ss)) ####
这个问题在
google
中搜索竟然没有找到一个和我问题一样的人。问题非常的长
,分析这些信息
,
最直观的是有两个
faild
。一个是
FAILED:/bin/bash -c "(./vendor/cm/build/tasks/http_curl_prebuilt.sh https://github.com/LineageOS/android_pack………………
还有一个是
Failedto connect to github-cloud.s3.amazonaws.com port 443:
连接超时
。
打印出来的信息里面还有两个
URL
:
https://github.com/LineageOS/android_packages_apps_Gello/releases/download/40/gello.apk.md5sum
以及
https://github.com/LineageOS/android_packages_apps_Gello/releases/download/40/gello.apk
用浏览器访问这个这两个链接
,分别下载下来了两个文件
gello.apk.md5sum
和
ge
llo.apk
。
再看打印信息里的这句话
./vendor/cm/build/tasks/http_curl_prebuilt.sh
,使用到了
http_curl_prebuilt.sh
脚本文件
,打开这个文件里面的内容很简单,如下所示:
#!/bin/bash
url=$1
output=$2
curl-L "$url" --create-dirs -o $output --compressed -H"Accept-Encoding: gzip,deflate,sdch" && exit 0 ||exit 1
代码很直观就是下载
url
里面的文件到对应的目录,为什么失败了呢,在命令行里单独执行
./vendor/cm/build/tasks/http_curl_prebuilt.shhttps://github.com/LineageOS/android_packages_apps_Gello/releases/download/40/gello.apk.md5sumvendor/cm/prebuilt/archive/Gello/md5sum
这部分指令
,会发现开始下载文件,但是过一会会提示连接超时。我意识到可能是我
curl
代理没有配置好,于是我重新配置了
linux
系统的网络代理,但还是不行。网络时而有速度时而没有速度,文件总是下载失败,至此我确定了是网络问题致使这部分编译失败,我不知道为什么我的网络就这两个文件下载不下来,按理说我的电脑连接外网的速度是没有问题的,但是没有办法,网络问题不是我能解决的,所以我想对源码文件
http_curl_prebuilt.sh
进行修改
,让他不去下载这两个文件,从而使得编译过程中不会出现网络连接超时的情况。因为这两个文件我是通过浏览器都可以下载下来的,所以我在
http_curl_prebuilt.sh
文件里做了判断
,如果当
URL
等于
https://github.com/LineageOS/android_packages_apps_Gello/releases/download/40/gello.apk.md5sum
时
,就从下载目录里将
gello.apk.md5sum
拷贝到相应的文件夹
vendor/cm/prebuilt/archive/Gello/md5sum
,从打印的信息里可以看到下载的文件会放到
vendor/cm/prebuilt/archive/Gello
中
,而下载下来的文件名为
md5sum
,所以不要忘记将下载下来的
gello.apk.md5sum
重命名为
md
5sum
,同理当
URL
等于
https://github.com/LineageOS/android_packages_apps_Gello/releases/download/40/gello.apk
时将
gello.apk
文件拷贝到对应的文件目录。
在
http_curl_prebuilt.sh
中添加的代码如下所示
:
if[ "$url" ="https://github.com/LineageOS/android_packages_apps_Gello/releases/download/40/gello.apk.md5sum"] ;
then
cp~/
下载
/md5sumvendor/cm/prebuilt/archive/Gello
exit0
fi
if[ "$url" ="https://github.com/LineageOS/android_packages_apps_Gello/releases/download/40/gello.apk"] ;
then
cp~/
下载
/gello.apkvendor/cm/prebuilt/archive/Gello
exit0
fi
shell
里的编程语言对格式要求特别严格,有很多的空格,关于格式的问题可以自行查阅。添加的代码内容也很直观也不再做解释,再补充一句每次编译失败后要执行
makeclean
再进行下一次编译。祝大家编译成功
!