打造專屬的Chromium for Android
自從寫了上篇《chrome源碼研究啟航篇》后,到今天已經(jīng)有了近一個月的時間,這段時間做了啥呢?研究到啥程度了呢?后續(xù)節(jié)奏是否有調整呢?
針對上邊疑問,下面做逐個解答:
這段時間做了啥?
總體來講,這段時間主要利用閑余在編譯和熟悉源碼,完成了對源碼的編譯和Gradle構建,并將項目開源,命名為:公英小蒲。Git地址:https://github.com/derry/delion.git
具體的:
1,獲得源碼
和預期計劃的一樣,要深入研究Chrome首先要拿到完整的代碼,進行完整的編譯,先從宏觀上搞清楚他的整體結構,搞清楚他開源的代碼是否完整可用,進而確定下一步研究思路。
獲取源碼官方有文檔,http://dev.chromium.org/developers/how-tos/get-the-code,獲取過程雖然等待時間漫長但總體還算比較順利。fetch --nohooks android完成后,代碼基本就都拉下來了。過程中如果中斷了,可以執(zhí)行gclient sync繼續(xù)。
因為這時候使用的—nohooks,所以真正編譯需要的資源這時候還沒有下。這一步一般沒啥問題。
2,編譯
代碼下完后,下一步選擇編譯方式:使用GYP或GN。
GYP的編譯方式出來的比較早(網(wǎng)上查找也基本都是GYP的編譯,我們現(xiàn)在項目里的編譯方式就是GYP,市面上開源的如365瀏覽器也是,早期版本GYP方式確實可行,為什么說早期可行看后邊)。我優(yōu)先選擇了使用GYP方式編,考慮這樣的話還有成功的案例可以參考。(后來為此決定付出了折騰一晚上的代價)
根據(jù)官方說明:
echo "{'GYP_DEFINES': 'OS=android target_arch=arm', }" > chromium.gyp_env
指定編譯類型。
然后運行gclient runhooks獲取真正的GYP需要的構建所需的資源。
正常情況執(zhí)行后會把需要的所有資源下載下來。但是實踐過程中發(fā)現(xiàn)里面有坑。
經(jīng)歷的那些坑:
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記錄有發(fā)現(xiàn)有刪除了該文件的記錄,排除了各種可能后,最后決定放棄這種編譯方式,現(xiàn)在Google也不推崇這種方式,建議使用GN編譯。(推測是從google推崇了GN后,后續(xù)新的版本GYP的編譯腳本沒有同步上)
在GYP編譯的問題上折騰了一晚無果后,選擇GN來編譯(官方推薦使用該種方式,構建效率大大提高且較強的支持增量編譯),根據(jù)官方文檔,使用GN編一路走下來非常順利。
開始使用分支最新的代碼編,后來發(fā)現(xiàn)打出APK安裝運行有問題(beta版本不穩(wěn)定的原因),最后切到了最新Tag嘗試編譯(54.0.2789.1)。結果比較理想,編譯OK,運行OK。
3,使用gradle構建Chromium項目
完整編譯完整個項目還是比較興奮的,但這只是開始,如何構建成開發(fā)環(huán)境下可調的呢?(總不能靠sublime查著看,那只能滿足研究的需求,解決不了要方便的調試和開發(fā)的需求)
開始考慮使用簡單直接的方式,保持原有的源碼結構,在各項目里添加gradle文件,順著腳本構建的流程,把項目整理理順,實現(xiàn)整體的項目Control。
但是真正實踐起來,感覺比較吃力,主要原因是一方面涉及的構建問題太多,另外就是對項目代碼還不太了解。并且中間因為解決編譯問題做得改動不容易記錄,即使最后構建成功,以后想升級版本也會比較被動。所以折騰了一晚上,把整體架子搭出來但是編譯還各種問題的時候,果斷放棄了這條路。想一口氣吃個胖子真心沒那么容易。
還有一種方式就是:不基于原有的項目結構搞了,單獨構建一套簡單的。通過摘取有用的資源,直接使用編譯過程中生成的中間文件(jar,so,src等),最小限度的改動項目的原有代碼。這樣等整體構建成功后,再根據(jù)研究進度,需要研究哪塊,把哪快源碼形式構建進來。
這樣可以最大限度的使用源碼自己構建的結果,減少代碼層面改動,在構建成本上能省不少功夫。通過搭起大框架,填充編譯結果文件,然后遇到啥問題解決啥問題。整體來講,這條路絕對是最簡單的。如果這條路走不通,也就沒得其他路可走了。
通過開始的分析發(fā)現(xiàn)了因為命名空間的原因,資源放置分開是比較合適的,比對了下最新的代碼,結構變化不大,所以最后延用了365的結構。(有365這個前行者感覺還是蠻好的。雖然該踩的坑還是要自己去踩,但是比看不到方向的往前走感覺好多了,由他證明了這條路是可行的,并給出了思路,對此心存感激)
使用的項目的結構如下:
4,編譯過程中趟的那些坑
構建方向確定了,剩下就是一步步趟坑了(最耗時間的就耗在了這一步)
根據(jù)構建過程中遇到的問題順序:
1,org.chromium.base.BuildConfig找不到
修復方式:
創(chuàng)建base Modules,最后提示:NoSuchMethodError:org.chromium.base.BuildConfig.isMultidexEnabled
發(fā)現(xiàn)該文件是動態(tài)生成的(具體參考
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使用,編譯環(huán)境下直接報錯
修復方式:floats改為dimen。
本來想先不用代碼,直接使用chrome_jar,但是因為floats的問題不得不改代碼,所以接下來使用工程代碼替換chrome_jar。
4,使用工程代碼替換chrome_jar會報一些列的類找不到,原因是很多配置類是在構建過程總動態(tài)生成的,所以想編譯成功必須要類倒進來。(缺的類有很多,但都在chrome_jar中能找到,所以處理起來比較簡單)
5,styleable.AppCompatTheme找不到
都使用最新的support包(具體參照項目)
6, ?NativeLibraries類找不到
發(fā)現(xiàn)該類是動態(tài)生成的,新建文件,把值填充進去。
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資源找不到:排查一圈發(fā)現(xiàn)問題出現(xiàn)在問題2的修復上,通過搜腳本(locale_pak_resources.py)發(fā)現(xiàn)需要文件小寫,并改'-’變’_’ 最終改資源名需為“zh_cn.lpak”,”en_us.lpak"
10,Suppressed:java.lang.ClassNotFoundException: org.chromium.mojom.device.BatteryMonitor
引入相應文件
解決上述問題后,編譯運行,OK一切正常。
5,解決了完整編譯的工作,下面就是打造專屬瀏覽器了
制定包名:com.delion.browser
瀏覽器命名:公英小蒲
取名公英小蒲,寓意該項目是基于Chromium衍生的一枚“蒲公英“的種子,希望能秉承Chromium的開源精神和強大的技術基因,以及做為種子的傳播使命,在國內生根發(fā)芽,茁壯成長,能夠將前沿的相關知識分享擴散出去,應用在更多的場景和領域。
至此,公英小蒲瀏覽器正式誕生。
二,目前研究到啥程度了呢?
所謂萬事開頭難,目前階段還出在剛開完了頭的階段。實現(xiàn)了項目的完整編譯,并將項目開源。
剩下的就是一步步分析和定制了。當然定期跟進最新代碼也是必不可少的工作。
過程中熟悉了Chromium源碼的整體結構,但也感受到了他的發(fā)展速度,相比對比早期的版本,他的代碼的改動量和頻率都還是很大的。萬里長征這才剛剛開始。
過程中遇到的問題的前期修復主要靠全局查找,到后期發(fā)現(xiàn)順著GN的構建流程是最有效的,很多中間文件配置文件都是通過腳本動態(tài)生成的。順著腳本的實現(xiàn)思路走,是最有效的。相關構建資料目前可以說還沒有,要縷順構建過程,腳本就是最好的老師。而通過他們也可以看出,超過百人的開發(fā)團隊去維護的項目,強大的腳本能力是必不可少的。所幸這點是我的強項(Ant構建,Gradle構建,Python腳本等在平時的項目管理過程中都會用到,所以煉出來了)。
后邊用到腳本的地方還會很多,比如:
1,最理想功能的改動就是靠腳本去改,這樣以后更新代碼,沖突會降到最低。
2,最理想的構建過程也是靠腳本,只要能人工操作的流程,需要頻繁操作的,都可以寫成腳本,操作成本降到最低。
針對這一點,后續(xù)的各功能開發(fā)和維護過程中會逐步的體現(xiàn)出來。
三,后續(xù)節(jié)奏是否會有調整呢?
目前來看節(jié)奏不會變,延續(xù)開始構想的思路,以研究和解決問題為目的,過程會比較難,但會做到底。
另外講一下要把過程寫出來和開源的目的:
1,項目龐大,不是一個人就可以完全Hold住的,學習的速度趕不上谷歌一百多號技術開發(fā)變化的速度,需要一幫志同道合的人一起研究一起弄。共同成長。(最好是有這方面基礎在研究這方面的人)
2,準備把專屬的項目《公英小蒲》持續(xù)做下去,無任何商業(yè)目的和功利摻雜,自驅動的純把瀏覽器作為一個中立的工具性產品去打磨。以簡單好用為第一宗旨去發(fā)展。打造專屬品牌。
3,瀏覽器開發(fā)涉及的技術非常廣,有很高的研究價值,對谷歌而言這也是戰(zhàn)略級的產品。跟進他的發(fā)展節(jié)奏持續(xù)研究和開發(fā),可以接觸到谷歌第一手的技術資料和使用這樣的世界級應用框架。
4,《公英小蒲》項目構建初衷是方便研究Chromium源碼,推廣相關前沿技術,構建獨立應用的同時,將成果應用到其他項目。目前筆者負責著國內某手機瀏覽器的項目管理和開發(fā)工作。針對線上應用的業(yè)務和實現(xiàn)技術不便透露(有研究成果也會體現(xiàn)到公司專利上),這也是為什么之前博客不撰寫這方面文章的原因,技術交流沒有問題。《公英小蒲》基于最新的chromium構建,基于源碼分享源碼,秉承開源開放的天性,最為適合作為研究性應用開源。
具體的:
1,完整編譯構建chromium_Android項目
2,項目開源,攜手更多的同行者
3,業(yè)務定制,通過分析各主要模塊,并實現(xiàn)痛點問題的逐步定制。(過程都體現(xiàn)在開源項目上)
4,深度挖掘,針對V8引擎,硬件加速,VR等逐步挖掘
附CSDN地址:http://blog.csdn.net/yangdeli888/article/details/52060088
歡迎關注博客:delion研發(fā)專欄
歡迎關注項目:公英小蒲(delion)