前言
新年第一天,这篇文章本来是想放到昨天写的,不过拖延症发作,拖着拖着便第二天了。这几天连续加班解决问题,有时候想,为什么这问题这么多坑,为什么这机器速度那么慢,诸如此类的抱怨,感觉每一天的进度都是慢得不行。不过当问题解决后,突然感觉有一种豁然开朗的感觉,回头看,这些所谓的坑貌似也不过尔尔。我想踩坑,折腾的过程就是成长的过程吧,有抱怨,有痛苦,不过完成之后那种柳暗花明的感觉,让我有了一种成长的感觉(笑)。
Android源码编译
直接来到了Android源码的编译过程,所以我就默认大家源码都是存在的吧。我的编译环境是:
Ubuntu14.04
JDK1.6
首先cd到你的源码主目录下,然后运行:
. build/envsetup.sh
这个脚本会引入很多其他的脚本,具体如下:
vendor/cm/vendorsetup.sh
#add_lunch_combo mini_armv7a_neon-userdebug
device/generic/armv7-a-neon/vendorsetup.sh
#add_lunch_combo mini_armv7a-userdebug
device/generic/armv7-a/vendorsetup.sh
#add_lunch_combo mini_mips-userdebug
device/generic/mips/vendorsetup.sh
#add_lunch_combo mini_x86-userdebug
device/generic/x86/vendorsetup.sh
#add_lunch_combo cm_jflteatt-eng
device/samsung/jflteatt/vendorsetup.sh
# add_lunch_combo full_panda-userdebug
device/ti/panda/vendorsetup.sh
# add_lunch_combo zte_blade-eng
device/zte/blade/vendorsetup.sh
我自己并没有在家里搭建源码环境,所以,以上的部分信息是在网上搜寻的,不过大体的 信息都是如此的。
以上完成之后,直接输入:
lunch
然后就会有不同的编译内容供选择,具体如下:
Lunch menu... pick a combo:
1. aosp_arm-eng
2. aosp_arm64-eng
3. aosp_mips-eng
4. aosp_mips64-eng
5. aosp_x86-eng
6. aosp_x86_64-eng
7. aosp_manta-userdebug
8. aosp_flo-userdebug
9. aosp_deb-userdebug
10. full_fugu-userdebug
11. aosp_fugu-userdebug
12. aosp_tilapia-userdebug
13. aosp_grouper-userdebug
14. aosp_mako-userdebug
15. aosp_hammerhead-userdebug
16. aosp_flounder-userdebug
17. aosp_shamu-userdebug
18. mini_emulator_x86-userdebug
19. mini_emulator_arm64-userdebug
20. mini_emulator_x86_64-userdebug
21. mini_emulator_mips-userdebug
22. m_e_arm-userdebug
具体需要怎样的选项,各位可以根据实际的需求进行选择,而且这里你完全可以自己在脚本里配置自己平台的选项进行编译,当然感觉这一步还是比较麻烦的,不过一个思路是根据此脚本在此处的源码执行逻辑来探索具体的内容,然后自己在这些流程中根据自己的需求来定制自己的内容。
上一步完成之后,会进行提示:
Which would you like? [aosp_arm-eng]
一般的首选项都是aosp_arm-eng ,这是官网的默认选项。这里不一定需要输入具体的选项信息,直接输入1.2等的阿拉伯数字也是完全没有问题的。
然后就可以正式开始编译了:
make -j4
由于我是在虚拟机下面进行的,所以只选择了 -j4.如果电脑配置不错的话,完全可以设置参数 -j8。接下来就是漫长的编译过程,不出意外的话会等上1-3小时的。
完成了编译之后,所产生的内容,一般在此目录下:
out/target/product/*
在product后是具体的平台目录。
如果按照Google官方推荐的源码编译环境进行编译一般也不会有什么错,到此步,整个原生代码的编译也就完成了,可以使用模拟器运行,也可以使用开发板进行烧写。
以上完成之后,就可以开始源码的修改与开发了,与应用开发不同,源码的修改没有方便的IDE,所以代码的编写纯粹靠的是开发人员本身,所以难免会有错误。(如果各位有源码下可以进行IDE一样方便进行开发的工具,还请赐教)。代码的编写是在SourceInsight下完成的。个人感觉这已经是代码编辑器中比较好用的一种了。
代码编写完成之后,就可以进行代码的合入,这里我们所采用的是:BeyondCompare这个工具,个人感觉同样是必不可少的工具。在合入之前,首先将你要修改代码的Android原生源代码进行备份,然后使用BeyondCompare进行对比合入。
完成之后,就执行以上的编译过程,之前说过这里的代码编写纯粹靠的是开发人员本身,所以一般来说,编译上是肯定会有错误的,不过不要紧,终端同样会打印出错误的代码位置,以及原因。根据这些信息就可以进行代码的修正了,在此过程中,我总结了大概会有以下一些问题:
代码本身的语法格式错误
这应该是初期最容易遇到的错误了,同样也是最容易修复的地方。特别要提到的是,一定要注意接口与实现函数之间的命名一致,大小写也必须一致。源码修改通知
这一步的话,在编译出错的话,会有提示,那就是你自己添加了接口,需要执行:
make update-api
因为内存不足而编译不通过
说到这一点,真心推荐各位在进行编译的时候尽量使用较好的电脑进行,这样可以避免很多莫名其妙的问题。代码本身逻辑上的错误
这一点错误其实是最难修改的,因为需要对Android的机制有一个比较清晰的认识,比如在添加接口的时候,根据Android原生的实现照葫芦画瓜,这样也能通过编译,但是在运行时就会出错,这就是对这个流程不清晰,代码细节没有跟踪完全造成的。我觉得这也是我需要更加去努力的一个方向,同样这也提醒我,作为一个从业人员,不能想当然,要追求细节。具体的修改不是本文的重点,暂且不诉了。
在以上的修改能够完成之后,应该是已经能将自己的代码修改编写进Android源码之中了,不过这还没有完,我怎么知道自己的代码是否修改正确了呢?这个流程是否能从应用层出发,顺利调用到Android底层呢?要做到这些,我们就需要一份我们这份源码的对应SDK,而非Android的官方版本SDK,所以这里需要进行SDK的编译,这个编译流程其实和源码流程差不多,具体如下:
. build/envsetup.sh
lunch sdk-eng
make sdk
細心的人可能应该已经注意到了,在lunch的时候,没有sdk-eng这个选项,但是执行这个参数确实是有效的,这个原因我也不是很清楚,有知道的哥们,还请赐教。
在进行sdk的编译的时候,同样有很大的报错可能性,但是因为具体的情况不同,不好一概而论。基本的编译错误与我以上提到的源码编译错误类似,值得一提的是,因为具体的情况不同,对于这个编译脚本也不要百分之百的信任,有些具体情况,它可能无法处理,所以在实际中,根据提示错误一步一步进行修改便可,一般不会有问题。
源码调试
这里我们已经编译好了源码,调试我这里选择了Android Studio来进行,在这之前,需要进行一些准备工作,生成Android Studio的配置文件:
mmm development/tools/idegen/
编译完成之后,执行如下的脚本:
development/tools/idegen/idegen.sh
然后在你的源码根目录下会生成以下文件:
android.ipr、android.iml
然后就是在AS中open android.ipr就可以进行导入了。整个过程有些缓慢,不过也不见得有多慢,推荐在第一次全部载入。方便以后的研究。
完成之后,先在module中挂载上你的android framework,然后将我们刚刚生成的SDK设置成AS的默认SDK,这就完成了android framework的调试环境。(目前据我所知,AS也只能调试到framework层,如果有可以调试到native层代码的工具,或者说如何调试native层代码,还请赐教)。
接下来,编写一个使用你自定义流程的demo app。然后将其安装到模拟器或者是开发板上,我这里是使用了开发板,然后切换到挂载了Android源码的AS中,连接上你的开发板,在以下地方:
可以发现很多framework的进程,以及你的APP进程,这里需要强烈指出的是,一定要清晰的知道你所修改的源码所在进程,不然是无法调试的。接下来,在合适的地方打上断点即可开始进行调试,具体断点打在哪儿,具体情况有所不同。我所使用的是AS2.2.2 ,非常方便的一个地方就是会根据你单步调试的流程,即时显示出当前变量中所存储的值。
至于native代码的调试,我目前已知的是在源码中添加日志,然后只能使用ADB工具,观察日志的执行情况。更细一步的调试我目前不知道,如果有哪位兄台知道这方面的内容,还请赐教!
PS:对了,还忘了指出,如果你修改的代码中有AIDL文件,那么一定要手动将这些文件路径导入到framework目录下的Android.mk中。
还有,更加详细地相关编译文档,没有比官网更好的了: