はじめに
以前の記事で、Apple Container の Rosetta 経由で amd64 の Ubuntu を動かし、Chromium のビルドを試した。
Linux 版 Chromium のビルドは amd64 が前提になる。そのため arm Mac では amd64 コンテナを使うが、前回はビルド中に下記の地点で止まり、コンテナごと固まって失敗した。
[9475/52852] CXX obj/net/net/http_proxy_connect_job.o
今回は同じ手順を再実行した。ビルドは最後まで通り、chromium が起動して YouTube を再生できた。
- ビルド完走:Chromium 159.0.8143.0 を57,744ステップ、129分19秒でビルド完了
- バイナリ実行:x86-64 ELFの chrome をRosetta環境で起動し、headlessモードでDOM出力を確認
- GUI動作:Xvfb + x11vnc経由でMacから操作し、Googleの日本語ページ表示とYouTube動画再生まで確認
実施した内容は、手順を追う形で書いた。再現だけが目的であれば、後半の「再現手順」の章に、必要なコマンドを順に並べてある。
環境
前回との違い
| 項目 | 今回 | 前回 |
|---|---|---|
| 機種 | Mac Studio(Mac15,14) | MacBook Pro(Mac15,6) |
| チップ | Apple M3 Ultra | Apple M3 Pro |
| コア数 | 32(パフォーマンス 24、効率 8) | 11(パフォーマンス 5、効率 6) |
| メモリ | 256GB | 36GB |
| macOS | 26.5.1 | 記載なし |
| container CLI | 1.6.1 | 0.1.0 |
| イメージ | ubuntu:24.04(--arch amd64) |
ubuntu:24.04(--arch amd64) |
| コンテナの割り当て | 24 CPU、64GB | 8 CPU、16GB |
| Chromium | 159.0.8143.0 | 115.0.5737.2 |
ホスト、割り当て、Chromium のバージョンがすべて変わっているため、前回の失敗が何で解消したかは切り分けていない。
長時間のビルドを container exec で投入して監視するため、コンテナはバックグラウンドで起動した。
container run -d --name chrome-build --arch amd64 --cpus 24 --memory 64g ubuntu:24.04 sleep infinity
記事の手順から変えたところ
前回の記事のコマンドにあった DEBIAN_FRONTEND=noninterractive は typo で、noninteractive が正しい。
./build/install-build-deps.sh は file コマンドが無いと FileNotFoundError: 'file' で失敗する。前回の apt-get install の一覧に file が無かったため、追加した。install-build-deps.sh には --no-prompt も付けた。
apt-get install -y curl git python3 sudo lsb-release pkg-config file
ビルド前に止まった二つの問題
ビルドを始める前に、ソース取得で二回止まった。
cipd ensure が進まない
fetch --nohooks --no-history chromium を実行すると、出力が出ないまま 10 分以上経った。ps で見ると、depot_tools のブートストラップが呼ぶ .cipd_client ensure が CPU を使い続けていた。.cipd_client version は即座に終わるので、Rosetta 上でも cipd 自体は動く。
ensure を -log-level debug で手動実行すると、各パッケージの展開が 0.0/25.1 MB (0%) のまま進まなかった。並列度を下げて実行すると完了した。
GOMAXPROCS=2 ./.cipd_client ensure -max-threads 1 -log-level warning \
-ensure-file cipd_manifest.txt -root .cipd_bin
-max-threads 1 と GOMAXPROCS=2 を同時に指定したので、どちらが効いたかは分かっていない。また、Rosetta 上の並列処理が原因かどうかは確認していない。
gclient sync の途中でも同じ症状が出た。Chromium のチェックアウトには depot_tools が二か所ある(/root/depot_tools と src/third_party/depot_tools)。どちらの .cipd_client も、ensure のときだけ上の引数を付けるラッパーに置き換えた。
cd <depot_tools のディレクトリ>
mv .cipd_client .cipd_client.real
cat > .cipd_client <<'EOF'
#!/bin/bash
if [ "$1" = "ensure" ]; then shift; GOMAXPROCS=2 exec "$(dirname "$0")/.cipd_client.real" ensure -max-threads 1 "$@"; fi
exec "$(dirname "$0")/.cipd_client.real" "$@"
EOF
chmod +x .cipd_client
ラッパーを入れる前の gclient sync は、cipd ensure が約 55 分、CPU を使ったまま進まなかった。ラッパーを入れてからの再実行は 51 秒で完了した。
HTTP 429
最初の fetch は 24 分かけて失敗した。ログには HTTP 429 が出ていた。gclient sync の並列数が多すぎて、chromium.googlesource.com からレート制限を受けたためで、Rosetta とは関係がない。並列数を 4 に絞って再実行した。
gclient sync --nohooks --no-history -j 4 --force
その後の install-build-deps.sh は約 6 分、gclient runhooks は 1 分 44 秒だった。runhooks では、リモートビルド用の reclient のインストールだけが一時ファイルの競合で失敗した。今回のビルドには使わないので、そのままにした。
ビルド
gn gen の引数は前回と同じにした。
gn gen out/Default --args="is_official_build=true is_debug=false symbol_level=0 blink_symbol_level=0 v8_symbol_level=0 chrome_pgo_phase=0 enable_nacl=false"
time autoninja -C out/Default chrome
enable_nacl は現在の Chromium には定義が無く、Build argument has no effect の警告が出るだけで、ビルドは続行した。
autoninja は siso を使って実行された。進捗表示の総ステップ数は、開始直後に 94,560 だった。完了時は 57,744 になった。
前回止まった 9,475 付近は問題なく通過した。ビルド中の負荷平均は 24 から 36 で、途中で止まることはなかった。
Build Succeeded: 57744 steps - 7.44/s
real 129m19.361s
user 2721m12.627s
sys 204m13.982s
out/Default/chrome は 550MB の x86-64 ELF で、/root/chromium 全体のディスク使用量は 41GB だった。
$ ./chrome --version
Chromium 159.0.8143.0
$ ./chrome --headless=new --no-sandbox --disable-gpu --dump-dom about:blank
<html><head></head><body></body></html>
chrome_sandbox はビルドしていないため、実行には --no-sandbox が必要になる。
Mac の画面に表示する
Apple Container には GUI を Mac に転送する機能が無い。コンテナ内で Xvfb の仮想ディスプレイを動かし、x11vnc で公開して、Mac から VNC で接続した。コンテナには Xvfb が入っていたため、追加したのは x11vnc、ウィンドウマネージャの openbox、日本語フォントの fonts-noto-cjk である。
apt-get install -y x11vnc openbox fonts-noto-cjk
export DISPLAY=:1
Xvfb :1 -screen 0 1920x1080x24 &
openbox &
x11vnc -display :1 -forever -shared -rfbauth /root/.vncpass -listen 0.0.0.0 -rfbport 5900 &
/root/chromium/src/out/Default/chrome --no-sandbox --disable-gpu --lang=ja &
-rfbauth は VNC のパスワードを使う指定で、x11vnc -storepasswd で事前に /root/.vncpass を作る。最初は認証なしの -nopw で起動したが、macOS の画面共有で接続するとパスワードを求められて先へ進めなかった。パスワードを設定すると接続できた。
接続先はコンテナの IP で、container ls で確認できる。
open vnc://192.168.64.4:5900
Google の日本語ページの表示と、YouTube の動画再生を確認した。
macOS の画面共有では、マウスクリックが効かないことがあった。TigerVNC 1.16.2 で接続すると、画質は下がったが、操作は問題なくなった。
サーバー側の原因を調べるため、Xvfb 上で xev を動かし、vncdotool から 20 回のクリックをクリック間隔 0 秒、0.05 秒、0.3 秒で送った。X に届いたクリックは、どの間隔でも 20 回だった。サーバー側ではクリックが落ちていないが、画面共有側のどの設定が原因かは調べていない。
再現手順
ここまでの内容から、再現に必要なコマンドだけを順に並べる。この順序は今回のログを整理したもので、全体を最初から一括で実行し直したわけではない。新しいコンテナで確認したのは、depot_tools の準備から fetch の開始までである。
ホスト(Mac)
container run -d --name chrome-build --arch amd64 --cpus 24 --memory 64g ubuntu:24.04 sleep infinity
container exec -it chrome-build bash
コンテナ内: 準備
depot_tools を取得し、.cipd_client を先に入れておく。./cipd --version で .cipd_client が取得される。ensure を -max-threads 1 で呼ぶラッパーは、ブートストラップが走る前に置く。
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y curl git python3 sudo lsb-release pkg-config file
cd /root
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
wrap_cipd() { # 引数: depot_tools のディレクトリ
cd "$1" && mv .cipd_client .cipd_client.real
cat > .cipd_client <<'EOW'
#!/bin/bash
if [ "$1" = "ensure" ]; then shift; GOMAXPROCS=2 exec "$(dirname "$0")/.cipd_client.real" ensure -max-threads 1 "$@"; fi
exec "$(dirname "$0")/.cipd_client.real" "$@"
EOW
chmod +x .cipd_client
}
/root/depot_tools/cipd --version
wrap_cipd /root/depot_tools
/root/depot_tools/update_depot_tools
export HOME=/root DEPOT_TOOLS_UPDATE=0 GCLIENT_SUPPRESS_GIT_VERSION_WARNING=1
export PATH=$PATH:/root/depot_tools
コンテナ内: ソース取得
429 が出て fetch が失敗したときは、gclient sync を並列数 4 で再実行する。
mkdir -p ~/chromium && cd ~/chromium
fetch --nohooks --no-history chromium
gclient sync --nohooks --no-history -j 4 --force
チェックアウトに含まれる depot_tools にもラッパーを入れる。
wrap_cipd /root/chromium/src/third_party/depot_tools
コンテナ内: ビルド
cd ~/chromium/src
./build/install-build-deps.sh --no-prompt
gclient runhooks
gn gen out/Default --args="is_official_build=true is_debug=false symbol_level=0 blink_symbol_level=0 v8_symbol_level=0 chrome_pgo_phase=0 enable_nacl=false"
time autoninja -C out/Default chrome
今回の所要時間は、install-build-deps.sh が約 6 分、runhooks が 1 分 44 秒、autoninja が 129 分 19 秒だった。runhooks で reclient のインストールが失敗するが、今回のビルドには影響しなかった。
コンテナ内: Mac から画面を見る
apt-get install -y x11vnc openbox fonts-noto-cjk
x11vnc -storepasswd '<8文字以内のパスワード>' /root/.vncpass
export DISPLAY=:1
Xvfb :1 -screen 0 1920x1080x24 &
openbox &
x11vnc -display :1 -forever -shared -rfbauth /root/.vncpass -listen 0.0.0.0 -rfbport 5900 &
/root/chromium/src/out/Default/chrome --no-sandbox --disable-gpu --lang=ja &
Mac では、container ls で確認したコンテナの IP を使って接続する。
open vnc://<コンテナの IP>:5900
まとめ
arm Mac の Apple Container で amd64 の Ubuntu を動かし、Chromium 159.0.8143.0 のフルビルドが 129 分で完了した。前回止まった地点も通過した。
前回の失敗が何で解消したかは分かっていない。ビルド前の cipd のハングは、並列度を下げると回避できた。1 回しか実行していないため、再現性は確認していない。
