Google Chrome (Chromium)を自分でビルドする

いろいろとやる必要があり、Chromiumを手元でコンパイルしたのでその記録。

(2018-06-23) @tzik_tackさんに指摘いただき、一部修正しました。ありがとうございます。

ChromeChromium

まず、予備知識。

Chromiumオープンソースプロジェクト名であり、そのプロダクトがChromiumというWebブラウザ。そして、ChromiumをベースにGoogleが固有機能を追加したものが、我々がふだん使っているGoogle Chromeである。

もっとも、Chromiumプロジェクト自体Googleが深く関わっているし、普通にそこでの実装の意思決定もGoogleのエンジニアによるものが多いので、実質どっちもGoogleがやってるという理解でおおむね問題ない。

Google Chrome自体はGoogleの著作物なので、自分でビルドするならばChromiumをビルドする、ということになる。

ビルド準備

基本的には、ドキュメントに書いてある通りにやればいい。ここに私が書いてあることもすぐ陳腐化すると思うので、ドキュメントを読もう。

ビルドには、Ubuntuを使った方が良い。WindowsでもVisual Studio Community 2017でビルドできるけど、Core i5, RAM 8GB, SSDのマシンでsln(プロジェクトファイル)開くだけで1時間、ビルドは10時間かけても終わらなかったので、やめた方がいい。

なおドキュメントには「8GB以上のメモリ(16GB以上を推奨)、100GB以上のディスク空き容量」が必要と書かれているので頑張ろう。私はESXi上の、Ubuntu 16.04.4を使った。

ビルドに必要なパッケージはだいたいソースコード一式に同梱されているので、事前準備としてはpython, build-essential, gitくらいあればいいはず。(最近のChromeはClang使っているが、chromiumリポジトリに同梱されているためclangパッケージは不要)

ビルド手順

depot_tools

はじめに、ビルドに必要なdepot_toolsというリポジトリをcloneする。

$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

この中にある色々なツールを使うので、PATHを通しておくこと。たとえば.bashrcに以下のように加える。

export PATH="$PATH:/home/ozuma/local/depot_tools"

続いて適当な作業ディレクトリ内で、dep_toolsのfetchコマンドでソースコードを取得する。この際、--no-historyを付けて最新版のみ取得すると良い。

$ fetch --nohooks --no-history chromium

ドキュメントのとおり、このfetchには30分ほどかかる。するとsrcディレクトリができるので移動する。

$ cd src

ここまでで、ソースコードのcheckoutができた。続いてUbuntuの場合、依存性を解決してくれるシェルスクリプトが用意されているので実行する。

$ sudo build/install-build-deps.sh

追加パッケージ入手。

$ gclient runhooks

ここまでで、ビルドの準備が整った。

Ninjaビルド

Chromeのビルドは、depot_tools付属のninjaというコマンドで行う。ninjaについては以下。

Ninjaがビルドするためのディレクトリout/Defaultを、depot_tools付属のgnコマンドで作成する。

$ gn gen out/Default

さて、このままビルドしても良いのだが、それだと大変に時間がかかるのでここでいくつかオプションを加える。gnコマンドにargsを付けてオプションを設定する。

$ gn args out/Default

ドキュメントに書いてあるが、まずJumbo buildsという設定をすると早くなる。多くのソースコードがヘッダファイルを共有しているのだから、それらを一緒にコンパイルする……と書いてあるけど、具体的な動きはよく分からない。

また、NaCl(Native Client)をビルドしないようにする。

それから、デバッグ用に使うわけではないの、デバッグシンボルを全部OFFにする。

これらの設定は、上記gn argsコマンドを打つとvimが起動するので、そこに以下のように記述する。実際には、out/Default/args.gnファイルに書かれる。

use_jumbo_build=true
enable_nacl=false
symbol_level=0
remove_webcore_debug_symbols=true
is_debug=false
is_component_build=true

最後に、ninjaコマンドでビルドする。timeコマンドを頭に付けて、どのくらいの時間がかかるか見ておいた方がいい。

ozuma@ubuntu16:~/local/depot_tools/src$ time ninja -C out/Default chrome
ninja: Entering directory `out/Default'
[19686/19686] LINK ./chrome

real    331m41.029s
user    320m3.768s
sys    8m46.260s
ozuma@ubuntu16:~/local/depot_tools/src$

私の手元では、全ビルドに5時間半ほどかかった。Windowsに比べればメチャクチャ早い。

Chromiumの起動

できあがったバイナリはout/Default/chrome。これをたたくと、ちゃんと起動した。

おしまい。

特定のバージョンのビルド

上記の手順では最新のビルド(Canary相当)が入るので、Stableなど古いバージョンを指定してビルドする場合。

上記にやり方が書いてあるが、この通りだとエラーを吐く。

で言われているように、

$ gclient sync --with_branch_heads --with_tags -Rv --disable-syntax-validation

と-Rv --disable-syntax-validationを指定する必要がある。(syntax validation無しでいいのだろうか)

これでタグが持ってこれたので、タグを指定してチェックアウトする。以下のようになる。

$ git checkout -b branch_67.0.3396.87 67.0.3396.87

(Gitでは、コミットIDの代わりにタグ名を指定してcheckoutできる)

なおgclient syncは、checkoutしたあとに依存性の更新をするためにもう一度実行する必要がある。

あとは同じようにビルドする。

$ gclient runhooks
$ gn gen out/67.0.3396.87
$ gn args out/67.0.3396.87
$ time ninja -C out/67.0.3396.87 chrome