打造专属的Chromium for Android
自从写了上篇《chrome源码研究启航篇》后,到今天已经有了近一个月的时间,这段时间做了啥呢?研究到啥程度了呢?后续节奏是否有调整呢?
针对上边疑问,下面做逐个解答:
这段时间做了啥?
总体来讲,这段时间主要利用闲余在编译和熟悉源码,完成了对源码的编译和Gradle构建,并将项目开源,命名为:公英小蒲。Git地址:https://github.com/derry/delion.git
具体的:
1,获得源码
和预期计划的一样,要深入研究Chrome首先要拿到完整的代码,进行完整的编译,先从宏观上搞清楚他的整体结构,搞清楚他开源的代码是否完整可用,进而确定下一步研究思路。
获取源码官方有文档,http://dev.chromium.org/developers/how-tos/get-the-code,获取过程虽然等待时间漫长但总体还算比较顺利。fetch --nohooks android完成后,代码基本就都拉下来了。过程中如果中断了,可以执行gclient sync继续。
因为这时候使用的—nohooks,所以真正编译需要的资源这时候还没有下。这一步一般没啥问题。
2,编译
代码下完后,下一步选择编译方式:使用GYP或GN。
GYP的编译方式出来的比较早(网上查找也基本都是GYP的编译,我们现在项目里的编译方式就是GYP,市面上开源的如365浏览器也是,早期版本GYP方式确实可行,为什么说早期可行看后边)。我优先选择了使用GYP方式编,考虑这样的话还有成功的案例可以参考。(后来为此决定付出了折腾一晚上的代价)
根据官方说明:
echo "{'GYP_DEFINES': 'OS=android target_arch=arm', }" > chromium.gyp_env
指定编译类型。
然后运行gclient runhooks获取真正的GYP需要的构建所需的资源。
正常情况执行后会把需要的所有资源下载下来。但是实践过程中发现里面有坑。
经历的那些坑:
a,运行gclient runhooks
If you really want to run this, either run
`python build/gyp_chromium.py`explicitly by hand
or set the environment variableGYP_CHROMIUM_NO_ACTION=0.
b,You have PROXYvalues set in your environment, but gsutil in depot_tools does not (yet) obeythem.
c,设置GYP编译,运行gclient
runhooks报文件找不到(most_visited_sites.cc,most_visited_sites.h)IOError:[Errno 2] No such file or directory:'browser/android/ntp/most_visited_sites.cc'
折腾一圈后总会回到找不到most_visited_sites.cc这个文件这。具体去查这个文件,在历史版本里确实是有的,在新版本里也确实没有。查看GIT记录有发现有删除了该文件的记录,排除了各种可能后,最后决定放弃这种编译方式,现在Google也不推崇这种方式,建议使用GN编译。(推测是从google推崇了GN后,后续新的版本GYP的编译脚本没有同步上)
在GYP编译的问题上折腾了一晚无果后,选择GN来编译(官方推荐使用该种方式,构建效率大大提高且较强的支持增量编译),根据官方文档,使用GN编一路走下来非常顺利。
开始使用分支最新的代码编,后来发现打出APK安装运行有问题(beta版本不稳定的原因),最后切到了最新Tag尝试编译(54.0.2789.1)。结果比较理想,编译OK,运行OK。
3,使用gradle构建Chromium项目
完整编译完整个项目还是比较兴奋的,但这只是开始,如何构建成开发环境下可调的呢?(总不能靠sublime查着看,那只能满足研究的需求,解决不了要方便的调试和开发的需求)
开始考虑使用简单直接的方式,保持原有的源码结构,在各项目里添加gradle文件,顺着脚本构建的流程,把项目整理理顺,实现整体的项目Control。
但是真正实践起来,感觉比较吃力,主要原因是一方面涉及的构建问题太多,另外就是对项目代码还不太了解。并且中间因为解决编译问题做得改动不容易记录,即使最后构建成功,以后想升级版本也会比较被动。所以折腾了一晚上,把整体架子搭出来但是编译还各种问题的时候,果断放弃了这条路。想一口气吃个胖子真心没那么容易。
还有一种方式就是:不基于原有的项目结构搞了,单独构建一套简单的。通过摘取有用的资源,直接使用编译过程中生成的中间文件(jar,so,src等),最小限度的改动项目的原有代码。这样等整体构建成功后,再根据研究进度,需要研究哪块,把哪快源码形式构建进来。
这样可以最大限度的使用源码自己构建的结果,减少代码层面改动,在构建成本上能省不少功夫。通过搭起大框架,填充编译结果文件,然后遇到啥问题解决啥问题。整体来讲,这条路绝对是最简单的。如果这条路走不通,也就没得其他路可走了。
通过开始的分析发现了因为命名空间的原因,资源放置分开是比较合适的,比对了下最新的代码,结构变化不大,所以最后延用了365的结构。(有365这个前行者感觉还是蛮好的。虽然该踩的坑还是要自己去踩,但是比看不到方向的往前走感觉好多了,由他证明了这条路是可行的,并给出了思路,对此心存感激)
使用的项目的结构如下:
4,编译过程中趟的那些坑
构建方向确定了,剩下就是一步步趟坑了(最耗时间的就耗在了这一步)
根据构建过程中遇到的问题顺序:
1,org.chromium.base.BuildConfig找不到
修复方式:
创建base Modules,最后提示:NoSuchMethodError:org.chromium.base.BuildConfig.isMultidexEnabled
发现该文件是动态生成的(具体参考
https://groups.google.com/a/chromium.org/forum/#!topic/chromium-checkins/auM6vUukpno)
文件在Gen文件夹找到并拷贝
2,缺少local_paks(ChromeApplication.Class中报array.locale_paks找不到)
修复方式:
新建locales.xml添加array.locale_paks,指定
@raw/zhcn
@raw/enus
3, floats找不到(NoClassDefFoundError:org.chromium.chrome.R$floats)
而代码中查看floats作为resource type使用,编译环境下直接报错
修复方式:floats改为dimen。
本来想先不用代码,直接使用chrome_jar,但是因为floats的问题不得不改代码,所以接下来使用工程代码替换chrome_jar。
4,使用工程代码替换chrome_jar会报一些列的类找不到,原因是很多配置类是在构建过程总动态生成的,所以想编译成功必须要类倒进来。(缺的类有很多,但都在chrome_jar中能找到,所以处理起来比较简单)
5,styleable.AppCompatTheme找不到
都使用最新的support包(具体参照项目)
6, NativeLibraries类找不到
发现该类是动态生成的,新建文件,把值填充进去。
7, Unable to load library:libaccessibility.cr.so
更新so文件,使用未压缩的文件
8, Unable to instantiate
application com.android.tools.fd.runtime.BootstrapApplication:
Disable Instant Run(Preferences -> Build,
Execution, Deployment -> Instant Run -> Enable Instant Run)
9,locale_paks资源找不到:排查一圈发现问题出现在问题2的修复上,通过搜脚本(locale_pak_resources.py)发现需要文件小写,并改'-’变’_’ 最终改资源名需为“zh_cn.lpak”,”en_us.lpak"
10,Suppressed:java.lang.ClassNotFoundException: org.chromium.mojom.device.BatteryMonitor
引入相应文件
解决上述问题后,编译运行,OK一切正常。
5,解决了完整编译的工作,下面就是打造专属浏览器了
制定包名:com.delion.browser
浏览器命名:公英小蒲
取名公英小蒲,寓意该项目是基于Chromium衍生的一枚“蒲公英“的种子,希望能秉承Chromium的开源精神和强大的技术基因,以及做为种子的传播使命,在国内生根发芽,茁壮成长,能够将前沿的相关知识分享扩散出去,应用在更多的场景和领域。
至此,公英小蒲浏览器正式诞生。
二,目前研究到啥程度了呢?
所谓万事开头难,目前阶段还出在刚开完了头的阶段。实现了项目的完整编译,并将项目开源。
剩下的就是一步步分析和定制了。当然定期跟进最新代码也是必不可少的工作。
过程中熟悉了Chromium源码的整体结构,但也感受到了他的发展速度,相比对比早期的版本,他的代码的改动量和频率都还是很大的。万里长征这才刚刚开始。
过程中遇到的问题的前期修复主要靠全局查找,到后期发现顺着GN的构建流程是最有效的,很多中间文件配置文件都是通过脚本动态生成的。顺着脚本的实现思路走,是最有效的。相关构建资料目前可以说还没有,要缕顺构建过程,脚本就是最好的老师。而通过他们也可以看出,超过百人的开发团队去维护的项目,强大的脚本能力是必不可少的。所幸这点是我的强项(Ant构建,Gradle构建,Python脚本等在平时的项目管理过程中都会用到,所以炼出来了)。
后边用到脚本的地方还会很多,比如:
1,最理想功能的改动就是靠脚本去改,这样以后更新代码,冲突会降到最低。
2,最理想的构建过程也是靠脚本,只要能人工操作的流程,需要频繁操作的,都可以写成脚本,操作成本降到最低。
针对这一点,后续的各功能开发和维护过程中会逐步的体现出来。
三,后续节奏是否会有调整呢?
目前来看节奏不会变,延续开始构想的思路,以研究和解决问题为目的,过程会比较难,但会做到底。
另外讲一下要把过程写出来和开源的目的:
1,项目庞大,不是一个人就可以完全Hold住的,学习的速度赶不上谷歌一百多号技术开发变化的速度,需要一帮志同道合的人一起研究一起弄。共同成长。(最好是有这方面基础在研究这方面的人)
2,准备把专属的项目《公英小蒲》持续做下去,无任何商业目的和功利掺杂,自驱动的纯把浏览器作为一个中立的工具性产品去打磨。以简单好用为第一宗旨去发展。打造专属品牌。
3,浏览器开发涉及的技术非常广,有很高的研究价值,对谷歌而言这也是战略级的产品。跟进他的发展节奏持续研究和开发,可以接触到谷歌第一手的技术资料和使用这样的世界级应用框架。
4,《公英小蒲》项目构建初衷是方便研究Chromium源码,推广相关前沿技术,构建独立应用的同时,将成果应用到其他项目。目前笔者负责着国内某手机浏览器的项目管理和开发工作。针对线上应用的业务和实现技术不便透露(有研究成果也会体现到公司专利上),这也是为什么之前博客不撰写这方面文章的原因,技术交流没有问题。《公英小蒲》基于最新的chromium构建,基于源码分享源码,秉承开源开放的天性,最为适合作为研究性应用开源。
具体的:
1,完整编译构建chromium_Android项目
2,项目开源,携手更多的同行者
3,业务定制,通过分析各主要模块,并实现痛点问题的逐步定制。(过程都体现在开源项目上)
4,深度挖掘,针对V8引擎,硬件加速,VR等逐步挖掘
附CSDN地址:http://blog.csdn.net/yangdeli888/article/details/52060088
欢迎关注博客:delion研发专栏
欢迎关注项目:公英小蒲(delion)