🌑

Mozcをオフラインでビルドするには?

2024/09/23に公開

Bazelでネットワーク接続なしでビルドする。

repository_cacheを用いる場合

  • 事前にMozcソースと依存関係があるモジュールなどを用意しておきます。
  1. Mozcソースの準備
    Ibus-Mozcのみでいい場合

    git clone --filter=tree:0 https://github.com/google/mozc
    

    Fcitx5-Mozcも必要な場合。

    git clone --filter=tree:0 https://github.com/fcitx/mozc
    
    cd mozc/src
    git submodule update --init
    cd ../..
    
  2. Bazel-central-registryの用意

    git clone --filter=tree:0 https://github.com/bazelbuild/bazel-central-registry.git bcr
    
  3. モジュールのダウンロード
    --repository_cache=$BASE/bazel-cacheフォルダにビルドに必要なファイルがダウンロードされます。
    bazel build --nobuild --build_event_json_file=bep.json --experimental_repository_resolved_file=resolved.bzlオプションを使って、ビルドに必要な依存モジュールなどの情報を集めます。
    bazel build --nobuildの前に、bazel clean --expungeを実行して、キャッシュを削除しておきましょう。

    export BASE=$PWD
    cd mozc/src
    bazel clean --expunge
    

    Ibus-Mozcの場合

    _BUILD_TARGETS="package"
    

    Fcitx5-Mozcの場合

    _BUILD_TARGETS="unix/fcitx5:fcitx5-mozc.so server:mozc_server gui/tool:mozc_tool"
    

    ビルドに必要な情報を集めます。あとでスクリプトで同じことを実行するので、ここでは参考として、コマンドラインの提示のみ。

    bazel build --nobuild --build_event_json_file=$PWD/bep.json --experimental_repository_resolved_file=$PWD/resolved.bzl --repository_cache="$BASE/bazel-cache" --registry=file://$BASE/bcr --config oss_linux --config release_build $_BUILD_TARGETS
    

    resolved.bzlファイルに詳細な情報が集まります。

  4. 郵便番号のアーカイブについて
    更新されてチェックサム(SHA256)が変更されているかもしれないので、それをチェックしてパッチを更新します。
    以下のスクリプトで、bazel build --nobuildコマンドで情報を収集して、resolved.bzlが生成されます。
    その後、それを加工してresolved.jsonファイルと、更に加工されて、mozc-deps.yamlが作成されます。
    mozc-deps.yamlのSHA256を更新し、zip-code.patchのチェックサム値(SHA256)も更新されます。

    cd $BASE
    wget https://github.com/phoepsilonix/flatpak-fcitx5/raw/refs/heads/test/update-sha256.sh
    wget https://github.com/phoepsilonix/flatpak-fcitx5/raw/refs/heads/test/resolved.jq
    wget https://github.com/fcitx/flatpak-fcitx5/raw/refs/heads/master/update_mozc_zip_code_patch
    wget https://github.com/fcitx/flatpak-fcitx5/raw/refs/heads/master/zip-code.patch
    _MOZC_BAZEL_CACHE="$BASE/bazel-cache" _BUILD_TARGETS=${_BUILD_TARGETS} bash update-sha256.sh --registry=file://$BASE/bcr
    
  5. ビルドチェック
    その後、ネットワークなしで、ビルドできるか試します。
    bazelのキャッシュを削除して、ネットワークを遮断して試しましょう。
    --repotitory_cache=$BASE/bazel-cache --registry=file://$BASE/bcrがポイントです。

    bazel clean --expunge
    cp -a $BASE/bazel-cache $BASE/bazel-cache-backup
    patch -p2 -i ../../zip-code.patch
    bazel build --config oss_linux --config release_build $_BUILD_TARGETS --repotitory_cache=$BASE/bazel-cache --registry=file://$BASE/bcr
    

    ビルドできたなら、ビルドする前の$BASE/bazel-cache-backupフォルダとbazel central registryのファイル群を、Mozcのソースとともにアップロードできれば、ビルド可能ということになります。
    手順の概略は、こんな感じです。

distdirオプションを用いる場合

レポジトリキャッシュそのままではなくて、モジュールのアーカイブを纏めていても可能です。
その場合には、distdirオプションを使います。
ますはモジュールのURL情報を整理します。

  1. 依存モジュールの情報の整理
    下記の手順は、スクリプトのupdate-sha256.shで一通り行われています。
    sedコマンドでresolved.bzrを加工してjqコマンドで処理しやすくします。

    cd $BASE
    wget https://github.com/phoepsilonix/flatpak-fcitx5/raw/refs/heads/test/resolved.jq
    sed -e 's/^resolved = //' -e 's/ False/ "False"/g' -e 's/ None/ "None"/g' resolved.bzl > resolved.json
    jq -r -f resolved.jq resolved.json > mozc-deps.json
    yq -y "." mozc-deps.json > mozc-deps.yaml
    

    resolved.jqをダウンロードしない場合

    jq -r '[ .[] | select(.repositories != null) | .repositories[] | select(.attributes.name != null) | select(.rule_class != null) | { url: ( if .attributes.url == "" then ( .attributes.urls[0] // "") else (.attributes.url // (.attributes.urls[0] // "")) end ), sha256: ( .attributes.sha256 // "" ), downloaded_file_path: ( .attributes.downloaded_file_path // null ), } | select(.url != "") | { type: "file", url: .url, dest: "bazel-deps", } + ( if .downloaded_file_path != "" and .downloaded_file_path != null then { "dest-filename": .downloaded_file_path, } else {} end ) + { sha256: .sha256, } ]' resolved.json > mozc-deps.json
    yq -y "." mozc-deps.json > mozc-deps.yaml
    

    mozc-deps.jsonファイルに必要なモジュールのURLが集まりました。

  2. 依存モジュールのダウンロード
    distdirオプション用にダウンロードして、一つのフォルダに纏めておきます。

    mkdir -p $BASE/bazel-deps
    cd $BASE/bazel-deps
    cp -a $_MOZC_BAZEL_CACHE/distdir/* ./
    cat $BASE/mozc-deps.json |jq -r '.[]| ( if ."dest-filename" != null and ."dest-filename" != "" then "\(.url) -O \(."dest-filename")" else "\(.url) -O \(.url |split("/")|last)" end )'|xargs -n3 wget -nc
    
  3. オフラインでのビルドチェック
    そして、そのフォルダをdistdirで指定してビルドします。

    cd $BASE/mozc/src
    patch -p2 -i $BASE/zip-code.patch
    bazel build --config oss_linux --config release_build --linkopt "${LDFLAGS}" $_BUILD_TARGETS --distdir=$BASE/bazel-deps --registry=file://$BASE/bcr/
    

    distdirオプションは将来的になくなるかもしれないそうです。
    それまでは、distdirオプションを利用するのが簡単そうです。
    bcrフォルダの中身とbazel-depsフォルダにまとめたモジュールをMozcソースとともにアップロードできれば、--distdirオプション,--registryオプションを利用して、オフラインでのビルドが可能になると思います。

(まとめ)bzlmodを有効にした状態でのオフラインビルド

概略

  1. ソースファイルの準備
  2. bazel-central-registryの準備(bazel regitryオプション用)
  3. resolved.bzrから依存関係のモジュールの一覧を取得
  4. モジュールを一通りダウンロードしておく(bazel distdirオプション用)
  5. オフラインビルド

1. ソースファイルの準備。

依存モジュール解析のために、ソースを準備します。

export BASE=$PWD
git clone --filter=tree:0 https://github.com/fcitx/mozc
wget https://github.com/phoepsilonix/flatpak-fcitx5/raw/refs/heads/test/update-sha256.sh
wget https://github.com/phoepsilonix/flatpak-fcitx5/raw/refs/heads/test/resolved.jq
wget https://github.com/fcitx/flatpak-fcitx5/raw/refs/heads/master/update_mozc_zip_code_patch
wget https://github.com/fcitx/flatpak-fcitx5/raw/refs/heads/master/zip-code.patch
wget https://github.com/google/mozc/pull/1063.patch
cd mozc/src
git submodule update --init
bazel clean --expunge
patch -p2 -i $BASE/1063.patch

2. bazel-central-registryの準備

cd $BASE
git clone --filter=tree:0 https://github.com/bazelbuild/bazel-central-registry.git bcr

3. 依存ファイルの解析と情報の更新

resolved.bzlから、URL情報を収集します。

Fcitx5-Mozcの場合

export BASE=$PWD
cd mozc/src
export _BUILD_TARGETS="${_BUILD_TARGETS:-unix/fcitx5:fcitx5-mozc.so server:mozc_server gui/tool:mozc_tool}"
export _MOZC_BAZEL_CACHE="$BASE/bazel-cache"

郵便番号辞書の元データなどが、更新されてチェックサム(SHA256)が変更されているかもしれないので、それをチェックしてパッチを更新します。
resolved.bzlを元に、mozc-deps.yamlが作成されます。そしてmozc-deps.yamlのSHA256を更新し、zip-code.patchのチェックサム値(SHA256)も更新されます。

wget https://github.com/phoepsilonix/flatpak-fcitx5/raw/refs/heads/test/update-sha256.sh
wget https://github.com/phoepsilonix/flatpak-fcitx5/raw/refs/heads/test/resolved.jq
wget https://github.com/fcitx/flatpak-fcitx5/raw/refs/heads/master/update_mozc_zip_code_patch
wget https://github.com/fcitx/flatpak-fcitx5/raw/refs/heads/master/zip-code.patch
_MOZC_BAZEL_CACHE="$BASE/bazel-cache" _BUILD_TARGETS=${_BUILD_TARGETS} bash update-sha256.sh --registry=file://$BASE/bcr

4. 依存モジュールのダウンロード

ダウンロードして、一つのフォルダに纏めておきます。

mkdir -p $BASE/bazel-deps
cd $BASE/bazel-deps
cat $BASE/mozc-deps.json |jq -r '.[]| ( if ."dest-filename" != null and ."dest-filename" != "" then "\(.url) -O \(."dest-filename")" else "\(.url) -O \(.url |split("/")|last)" end )'|xargs -n3 wget -nc

5. オフラインビルド

ここからは、ネットワークを閉じても大丈夫です。

cd $BASE/mozc/src
patch -p2 -i $BASE/zip-code.patch
bazel build --config oss_linux --config release_build $_BUILD_TARGETS --distdir=$BASE/bazel-deps --registry=file://$BASE/bcr/ 

オフラインビルド その2

--experimental_downloader_configオプションの利用。
wengxtさんのPR #23での提案に基づいたものです。
このオプションを用いるとproxyサーバーを経由して、ダウンロードさせることができます。
簡易的なproxyサーバーのPythonスクリプトを用意して、中継させることで、URLやチェックサムなど、必要な情報が収集できます。
またローカルのフォルダに、URL名などを含んだ形でダウンロードさせることで、一覧作成が行いやすくなっています。
Fcitx5-Mozcでは、これだけで問題はないのですが、Ibus-Mozcの場合、アイコン名が複数同じファイル名のため、distdirオプション用に、保存先の名前まで反映することが必要になります。この部分はresolved.bzlのファイルから情報を持ってくることで対応しています。
これらのまとめた情報をもとに、proxyサーバーが保存したファイルを、bazel-depsフォルダにコピーしています。

概略

  1. bazel build --nobuildで情報収集
  2. 解析ファイル生成
  3. distdirオプション用のファイルの準備
  4. オフラインビルド

1. bazel build --nobuildで情報収集

ソースの準備は上記と同じなので、割愛します。
必要なファイルのダウンロード。

wget https://github.com/fcitx/flatpak-fcitx5/raw/refs/heads/master/bazel_mirror.py
wget https://github.com/fcitx/flatpak-fcitx5/raw/refs/heads/master/downloader.cfg
wget https://github.com/fcitx/flatpak-fcitx5/raw/refs/heads/master/update_mozc_zip_code_patch
wget https://github.com/fcitx/flatpak-fcitx5/raw/refs/heads/master/zip-code.patch

Ibus-Mozcの場合

_BUILD_TARGETS="package"

Fcitx5-Mozcの場合

_BUILD_TARGETS="unix/fcitx5:fcitx5-mozc.so server:mozc_server gui/tool:mozc_tool"

--experimental_downloader_config --experimental_repository_resolved_file --registry オプションを使用します。

BASE=$PWD
_DOWNLOADER_CACHE="$BASE/downloader_cache"

pushd .
mkdir -p $_DOWNLOADER_CACHE
cd $_DOWNLOADER_CACHE
python $BASE/bazel_mirror.py &
popd
pushd .
cd mozc/src
bazel build --nobuild --experimental_downloader_config=$BASE/downloader.cfg --registry=file://$BASE/bcr --build_event_json_file=$BASE/bep.json --experimental_repository_resolved_file=$BASE/resolved.bzl --repository_cache="$_MOZC_BAZEL_CACHE" --config oss_linux --config release_build $_BUILD_TARGETS
popd

2. 解析ファイル生成

sed -e 's/^resolved = //' -e 's/ False/ "False"/g' -e 's/ None/ "None"/g' $BASE/resolved.bzl > $BASE/resolved.json
jq -r '[ .[] | select(.repositories != null) | .repositories[] | select(.attributes.name != null) | select(.rule_class != null) | { url: ( if .attributes.url == "" then ( .attributes.urls[0] // "") else (.attributes.url // (.attributes.urls[0] // "")) end ), sha256: ( .attributes.sha256 // "" ), downloaded_file_path: ( .attributes.downloaded_file_path // null ), } | select(.url != "") | { type: "file", url: .url, dest: "bazel-deps", } + ( if .downloaded_file_path != "" and .downloaded_file_path != null then { "dest-filename": .downloaded_file_path, } else {} end ) + { sha256: .sha256, } ]' $BASE/resolved.json > $BASE/mozc-deps.json

dest-filenameがすべてURLからダウンロードするファイル名と同じなら、下記の手順でもURL一覧を生成できます。

jq -r 'select(.id.fetch.url != null )|.id.fetch.[]|select( contains("http"))|.' $BASE/bep.json

プロキシーにダウンロードされたファイルを基にして、mozc-deps.yamlを作成します。

pushd .
cd $_DOWNLOADER_CACHE
for f in `find -type f` ; do
    if [[ ! "$f" =~ "./bcr.bazel.build/" ]];then
        url="https://${f#*/}"
        echo "- type: file"
        echo "  url: $url"
        echo "  dest: bazel-deps"
        sha=`sha256sum $f|cut -f1 -d" "`
        echo "  sha256: $sha"
	    dest=$(jq -r '.[]|select(.url=="'$url'")|."dest-filename"' $BASE/mozc-deps.json)
	    if [[ "$dest" != "null" ]];then
	        filename=$(basename $url)
	        [[ "$dest" != "$filename" ]] && echo "  dest-filename: $dest"
	    fi
    fi
done > $BASE/mozc-deps.yaml
popd
yq -y -i 'sort_by(.url)' $BASE/mozc-deps.yaml

1-2の手順をまとめたスクリプト

wget https://github.com/phoepsilonix/flatpak-fcitx5/raw/refs/heads/test/update-sha256_.sh
./update-sha256_.sh

3. distdirオプション用のファイルの準備

proxyで保存されたフォルダにあるファイルを、dest-filenameがある場合は、その名前を、それ以外はそのままのファイル名でコピーしています。
cp -alでハードリンクでコピーしています。

mkdir -p bazel-deps
jq -r '.[]| ( if ."dest-filename" != null and ."dest-filename" != "" then "\(.url) ./bazel-deps/\(."dest-filename")" else "\(.url) ./bazel-deps/\(.url |split("/")|last)" end )' $BASE/mozc-deps.json | sed 's|https://|"'$_DOWNLOADER_CACHE'"/|'|xargs -n2 cp -al

4. オフラインビルド

ここからは、ネットワークを閉じても大丈夫です。

cd $BASE/mozc/src
patch -p2 -i $BASE/zip-code.patch
bazel build --config oss_linux --config release_build $_BUILD_TARGETS --distdir=$BASE/bazel-deps --registry=file://$BASE/bcr/ 

備考

上記手順でもbazel-7.1.1では、ネットワークアクセスを要求されることを確認しました。
flatpak-builderで--sandboxオプションでビルドした場合です。sandboxなのでbuild-argsに--share=networkは含まれません。
なおbazel-7.3.1では、同じ手順で問題がなかったので、flatpak版のbazelが更新されることが望まれます。bazelが更新されるまでは、若干依存ライブラリのバージョンなどが異なりますが、bazelのビルド時に--noenable_bzlmodオプションを追加することも、一つの手ではないでしょうか?
bazel-7.1.1などでは、--noenable_bzlmodオプションを情報の収集の時点と、ビルドの時点の両方で指定すれば、回避できるかもしれません。

追記:
10月2日時点で、bazel-7.3.2に更新されています。(メンテナに加わって、更新してもらいました。)

注意点

  1. ビルドする環境に、Fcitx5やQt6のライブラリがあることが前提です。
    ビルド環境に、ライブラリがあるか確認しましょう。
pkg-config --cflags --libs Fcitx5Core Qt6Core
  1. distdirオプション
    --distdirオプションはdeprecatedとされているようで、bazel-7系ですでに廃止予定の機能らしいのですが、bazel-7.3.1でも、まだ使えているオプションです。
    類似の機能が残されるのか、別途実装されるのかはわかりませんが、その時に類似の機能がない場合には、--repository_cacheオプションを使うことになりそうです。repository_cacheをそのまま送れない環境なら、関連ファイルを元にrepository_cacheをbazelの機能以外で、別のスクリプトなどで再構築することが必要になるかもしれません。内部的な決まり毎が整理されていたら、可能かもしれませんが、ちょっと大変そうですね。
    ただ、まだ来ても居ないことを心配しても仕方がありませんし、その時にはその時で、古いバージョンのbazelでビルドができるのなら、先延ばしもできますから、慌てることはないでしょう。

関連PR

https://github.com/google/mozc/pull/1062
https://github.com/fcitx/flatpak-fcitx5/pull/23
https://github.com/fcitx/flatpak-fcitx5/pull/29
https://github.com/flathub/org.freedesktop.Sdk.Extension.bazel/pull/5

参考サイト

下記サイトのorg.fcitx.Fcitx5.Addon.Mozc.yamlの手順が参考になります。
flatpak-builderでsandbox(ネットワーク無し)でビルドする手順を構築されています。
https://github.com/fcitx/flatpak-fcitx5

その他、Mozc関連記事

Mozc を応援するいくつかの方法

大概のLinuxで使えそうな日本語入力(Flatpak版Fcitx5-Mozc)
UbuntuでMozcの新しいバージョンをビルドするには

郵便番号辞書 Mozc形式作成手順

DockerでビルドしたMozcをUbuntu 22.04 LTSにインストールする
Ubuntu 20.04 LTS/20.10でFcitx5を使用する

謝辞

PRにご対応くださった、Hiroyuki Komatsuさん、ありがとうございました。
macosなどでのビルド確認が出来ないので、閉じたほうが良さそうですね。
いろいろとご確認にお手間をとらせることになり、申し訳ありません。

Discussion