編譯V8引擎
由於專案專案中最近用到v8引擎,專案由sparkmonkey切換到v8後,效能有了較大的提升,不過美中不足的是,啟動時間較長,檢視v8相關的文件,可以使用snapshot快照技術加快啟動速度,因此覺得自己編譯v8,加速啟動。
在編譯過程中遇到各種問題,首先說編譯環境,專案需求是在android中使用v8快照,一般生成android平臺的v8連結庫有三種形式,在windows環境編譯,在windows環境下使用cgwin編譯,在linux環境下編譯。
使用window環境編譯
v8最新版本會強制繫結到vs2017,就算指定僅編譯android平臺也不能拿避免,沒有裝vs2017,目前專案使用vs2015,升級設計比較多的人,故舍棄此方案。(可能有其他引數避免這種繫結,不瞭解暫時沒有深究)
使用window環境下cgwin編譯
在cgwin環境下前期正常,但在相關指令碼的呼叫中,遇到一個路徑中斜槓”\”和反斜槓”/”的報錯,由於關聯指令碼是從遠端庫自動下載,無法本地修改,如果要一一修改,需要將指令碼加入到本地索引中,因此也沒有使用這種方案。
使用linux環境編譯
使用linux環境編譯目前遇到問題最少,基本都是自動指令碼執行完成,linux中還缺少部分系統庫,手動新增一下就好。
開始編譯v8,分為三個部分,第一個準備環境,linux使用虛擬機器wmware,裝centos最新穩定版本,注意硬碟要分配30G以上,因為要下載ndk以及一大堆第三方程式碼,建議留足編譯空間。
前期準備
裝完centos後,先需要安裝gcc gcc-c++
yum install -y gcc yum install -y gcc-c++
安裝depot_tools,主要用來下載指令碼,有兩個工具 fetch,gclient
git clone https://chromium.googlesource.com/chromium/tools/depot_tools
修改系統環境變數,將depot_tools加入到系統命令當中
vim /etc/profile ... export PATH=/*(目錄)/depot_tools:$PATH
編譯可以使用fetch v8來預設編譯,這條命令相當於先建立一個預設的.gclient配置描述檔案,然後再指向gclient sync下載相關依賴專案,我們可以採用自己建立.gclient檔案定製下載選項
gclient config https://github.com/v8/v8.git
這個時候,在當前工作目錄下會生成一個.gclient檔案,使用編輯器開啟它
solutions = [ { "name" : "v8", "url" : "https://github.com/v8/v8.git", "deps_file" : "DEPS", "managed" : True, "custom_deps" : { }, }, ] cache_dir = None target_os = ["android"] target_os_only = True target_cpu = "arm" is_component_build = True
根據需要自己定製編譯目標,修改完成後,再執行
執行命令
gclient sync
編譯指定版本
這之後gclient會自動下載v8原始碼,以及相關依賴專案。如果要指定某個v8版本編譯,則需要先下載這個v8工程,再切換到對應版本,然後檢出一個本地分支
git clone https://github.com/v8/v8.git git checkout 6.0.328 git checkout -b myv8 gclient sync --with_branch_heads --jobs=1
會遇到是否下載合併程式碼,選skip跳過,就可以在當前分支版本繼續執行編譯命令
錯誤處理
在編譯過程中可能會遇到指令碼報錯,基本上是系統的某些庫檔案找不到,例如:
ninja: Entering directory `out/foo/' [1252/1707] ACTION //:run_mksnapshot(//build/toolchain/android:android_arm) FAILED: gen/snapshot.cc snapshot_blob.bin python ../../tools/run.py ./clang_x86_v8_arm/mksnapshot --startup_src gen/snapshot.cc --random-seed 314159265 --startup_blob snapshot_blob.bin ./clang_x86_v8_arm/mksnapshot: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory [1253/1707] CXX obj/v8_base/code-stub-assembler.o ninja: build stopped: subcommand failed.
找到出錯指令碼單獨執行就可以看到報錯
python ../../tools/run.py ./clang_x86_v8_arm/mksnapshot --startup_src gen/snapshot.cc --random-seed 314159265 --startup_blob snapshot_blob.bin ./clang_x86_v8_arm/mksnapshot: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory
定位到問題,系統缺少libstdc++.so.6,使用yum命令安裝對應庫即可
編譯靜態庫
由上述步驟,已經下載好整套編譯環境,預設會下載到當前目錄下的v8目錄,切換隻目錄到v8資料夾,進入編譯流程,先配置編譯引數,使用gn命令生成編譯引數gn args out/foo
這時會開啟一個名為args.gn的文字檔案,根據需要填入以下引數
# Build arguments go here. # See "gn args <out_dir> --list" for available build arguments. target_cpu = "arm" target_os = "android" v8_target_cpu = "arm" v8_static_library = true v8_enable_i18n_support = false v8_use_snapshot = true is_component_build = false
敲入一下命令啟動編譯過程,執行完成就可以獲得相應的靜態庫
gn gen out/foo ninja -C out/foo
最後遇到一個找不到libplatform.a的問題,看了網上的大多數解決方案,都不是很靠譜,自行研究發現其實挺簡單,修復ninja編譯命令引數檔案,將libplatform.stamp檔案編譯為libplatform.a檔案
在執行完 gn gen out/foo 後先修改out/foo/build.ninja檔案中v8_libplatform.stamp 改為 v8_libplatform.a,一共有三個地方
build v8_libbase: phony obj/v8_libbase.stamp build v8_libplatform: phony obj/v8_libplatform.stamp ## => v8_libplatform.a build v8_libsampler: phony obj/libv8_libsampler.a build v8_maybe_snapshot: phony obj/v8_maybe_snapshot.stamp build v8_nosnapshot: phony obj/libv8_nosnapshot.a
再修改out/foo/obj/build.ninja,參照其他.a檔案的生成規則,將最後一行改為生成.a檔案
build obj/v8_libplatform.stamp: stamp obj/v8_libplatform/default-platform.o obj/v8_libplatform/task-queue.o obj/v8_libplatform/trace-buffer.o obj/v8_libplatform/trace-config.o obj/v8_libplatform/trace-object.o obj/v8_libplatform/trace-writer.o obj/v8_libplatform/tracing-controller.o obj/v8_libplatform/worker-thread.o || obj/v8_libbase.stamp obj/build/config/exe_and_shlib_deps.stamp ##=> build obj/libv8_libplatform.a: alink obj/v8_libplatform/default-platform.o obj/v8_libplatform/task-queue.o obj/v8_libplatform/trace-buffer.o obj/v8_libplatform/trace-config.o obj/v8_libplatform/trace-object.o obj/v8_libplatform/trace-writer.o obj/v8_libplatform/tracing-controller.o obj/v8_libplatform/worker-thread.o || obj/v8_libbase.stamp obj/build/config/exe_and_shlib_deps.stamp arflags = output_extension = .a output_dir = obj
最後執行 ninja -C out/foo編譯專案,生成靜態庫
總結一下就是,專案中引入的依賴太多,才導致編譯變得比較複雜,而且很多都是google的指令碼,找不到命令文件,所以執行起來比較容易出問題。