Distcc

提供: ArchWiki
移動先: 案内検索

関連記事

Distcc は C, C++, Objective C, Objective C++ のコードのビルドをネットワーク上の複数のマシンに分散させるプログラムです。distcc は常にローカルビルドと同じ結果を生成し、インストールと使用方法がシンプルで、ローカルコンパイルよりもずっと高速です。makepkg などの Arch のビルドツールで使うことができます。

用語

マスター
コンパイルを開始して設定済みのスレーブにコンパイルを分散させるコンピューター。
スレーブ
distcc デーモンが動いており、マスターからコンパイルリクエストを受け取る。

インストール

公式リポジトリからクラスタの PC 全てに distcc パッケージをインストールしてください。

他のディストロや、Cygwin を使用する Windows など他の OS を使う場合は、distcc のドキュメント を参照してください。

設定

スレーブ

スレーブの設定は /etc/conf.d/distccd に保存します。利用できるコマンドラインオプションは distcc(1) に記載されています。最低でも、許可するアドレスの範囲を CIDR 形式で指定してください:

DISTCC_ARGS="--allow 192.168.0.0/24"

アドレスの範囲を CIDR 形式に変換するツールが次のページにあります: CIDR Utility Tool

コンパイルに参加する全てのスレーブで distccd.service起動してください。起動時に distccd.service を実行させるには、全てのマシンでサービスを有効化してください。

マスター

スタンドアロン

マスターで設定する distcc の最小設定は、利用するスレーブの設定です。環境変数 DISTCC_HOSTS$DISTCC_HOSTS, $DISTCC_DIR/hosts, ~/.distcc/hosts, /etc/distcc/hosts などの設定ファイルでアドレスを指定することで設定できます。

DISTCC_HOSTS を使ってスレーブのアドレスを設定する例:

$ export DISTCC_HOSTS="192.168.0.3,lzo,cpp 192.168.0.4,lzo,cpp"
ノート: このリストは空白で分けられています。

hosts 設定ファイルでスレーブのアドレスを設定する例:

~/.distcc/hosts
192.168.0.3,lzo,cpp 192.168.0.4,lzo,cpp

サーバーのアドレスを明示的に指定する代わりに、avahi の zeroconf モードを使うこともできます。このモードを使うにはサーバーアドレスのところに +zeroconf と記述して、スレーブ側で distcc デーモンを --zeroconf オプションを使って起動するようにしてください。このオプションは pump モードをサポートしてないので注意してください。

上記の例ではアドレスに以下のオプションを追加しています:

  • lzo: TCP と SSH ホスト (スレーブ) で LZO 圧縮を使う。
  • cpp: ホスト (スレーブ) で distcc-pump モードを使う。サーバーを起動するにはビルドコマンドを pump スクリプトでラッピングする必要があるので注意。

pump モードの説明は次のページにあります: HOW DISTCC-PUMP MODE WORKSdistcc's pump mode: A New Design for Distributed C/C++ Compilation

スレーブで distcc-pump モードを使うには、pump スクリプトを使ってコンパイルを開始する必要があります。そうしないとコンパイルは失敗します。

Makepkg

/etc/makepkg.conf の以下の3つのセクションを編集してください:

  1. BUILDENV で distcc の前のエクスクラメーションポイントを外して有効にしてください。
  2. DISTCC_HOSTS 行をアンコメントして、スレーブの IP アドレスとスラッシュ、使用するスレッドの数を追加してください。後ろの IP アドレスとスレッドは空白で区切ります。リストは一番強力なサーバーから非力なサーバーの順で並べます (処理能力)。
  3. MAKEFLAGS 変数を個々のサーバーの最大スレッド数をすべて合計した数字にしてください。下の例の場合、5+3+3=11 になります。合計数以上を指定した場合、余った論理スレッドは distcc によってブロックされ、下で説明している distccmon-text などの監視ユーティリティでそのように表示されます。
ノート: よく物理コアとハイパースレッドのコア数に1を加えた数をスレッド数として定義することがありますが、この設定では MAKEFLAGS で1を加えないようにしてください。

例:

BUILDENV=(distcc fakeroot color !ccache !check)
MAKEFLAGS="-j11"
DISTCC_HOSTS="192.168.0.2/5 192.168.0.3/3 192.168.0.4/3"

SSH を通して distcc を使いたい場合、セクションの IP アドレスの前に "@" シンボルを追加してください。キーベースの認証をセットアップしていないときは、認証済みのホストのチェックを無視するように DISTCC_SSH 変数を設定してください: DISTCC_SSH="ssh -i"

警告: CFLAGSCXXFLAGS-march=native をセットしてはいけません。distccd が他のマシンに作業を割り振らなくなります。Arch のデフォルト設定を使うことを推奨します。

コンパイル

スタンドアロン

distcc の pump モードを使ってソースファイルをコンパイルするには、次のコマンドを使用します:

$ pump distcc g++ -c hello_world.cpp

この場合 pump スクリプトは distcc を実行してから "-c hello_world.cpp" をパラメータとして g++ を呼び出します。

Makefile プロジェクトをコンパイルするには、まずコンパイラによって設定される変数を確認する必要があります。例えば、gzip-1.6 の場合、Makefile の中に次の行を見つけることができます: CC = gcc -std=gnu99。基本的に CC は C プロジェクトで使われる変数で、CXX は C++ プロジェクトで使われる変数です。distcc を使ってプロジェクトをコンパイルするには以下のようにします:

$ wget ftp://ftp.gnu.org/pub/gnu/gzip/gzip-1.6.tar.xz
$ tar xf gzip-1.6.tar.xz
$ cd gzip-1.6
$ ./configure
$ pump make -j2 CC="distcc gcc -std=gnu99"

上記例では distcc の pump モードによって2つのコンパイルスレッドを使って gzip をコンパイルします。-j の設定については What -j level to use? を見て下さい。

Makepkg

通常通り makepkg でコンパイルしてください。

進捗を見る

複数の方法で進行状況を確認することができます。

  1. distccmon-text
  2. ログファイルを tail で表示する

distccmon-text を実行してコンパイル状況をチェックします:

$ distccmon-text
29291 Preprocess  probe_64.c                                 192.168.0.2[0]
30954 Compile     apic_noop.c                                192.168.0.2[0]
30932 Preprocess  kfifo.c                                    192.168.0.2[0]
30919 Compile     blk-core.c                                 192.168.0.2[1]
30969 Compile     i915_gem_debug.c                           192.168.0.2[3]
30444 Compile     block_dev.c                                192.168.0.3[1]
30904 Compile     compat.c                                   192.168.0.3[2]
30891 Compile     hugetlb.c                                  192.168.0.3[3]
30458 Compile     catalog.c                                  192.168.0.4[0]
30496 Compile     ulpqueue.c                                 192.168.0.4[2]
30506 Compile     alloc.c                                    192.168.0.4[0]

プログラムを持続的に実行させるには、watch を使うか、コマンドに空白と繰り返す待機秒数を加えます:

$ watch distccmon-text

または

$ distccmon-text 2

ジャーナルのログを監視しても良いでしょう:

# journalctl -f -u distccd

distcc で "クロスコンパイル"

X86

現在、x86_64 環境から i686 のパッケージをビルドするのに、distcc でクラスタに作業を分散させる方法は2つ存在します。どちらも理想的とは言いがたいですが、今のところ、この2つの方法しかドキュメントになっていません。

chroot からなのか、ネイティブ環境からのビルドなのかに関係なく各ノードで一度だけ distccd を実行すれば未修正の ARCH パッケージを使用して makepkg が動作するようになるのが理想ですが、現在のところそのような方法はありません。

議論スレッド があるので、自由に参加してください。

Chroot を使う方法 (推奨)

ノート: 以下の方法は全てのノードに distccd をインストールして32ビットの chroot も必要なのであまりエレガントな方法とは言えません。

32ビットの chroot を distcc クラスタの各ノードに設定したら、各ノードで2つの distccd インスタンスを別々のポートで実行させます。片方はネイティブの x86_64 環境で実行させ、もう片方は x86 chroot で動かします。makepkg は schroot コマンドを通して実行します。

i686 chroot の DISTCC_HOSTS にポート番号を追加する

以下のように /opt/arch32/etc/makepkg.conf の各ホストにポート番号 (3692) を追加してください:

DISTCC_HOSTS="192.168.1.101/5:3692 192.168.1.102/5:3692 192.168.1.103/3:3692"
ノート: 上記の設定が必要なのはマスターの i686 chroot だけです。マスターとはコンパイルを実行するマシンを示します。
ネイティブ環境から makepkg を呼び出す

ネイティブの x86_64 環境に schroot をセットアップしてください。ネイティブの x86_64 環境から makepkg を実行して i686 パッケージのビルドをするには:

$ schroot -p -- makepkg -src

Multilib GCC を使う方法 (非推奨)

警告: 以下の方法を使ってネイティブの x86_64 環境から i686 の linux パッケージをビルドするとエラーが発生することが報告されています。カーネルパッケージをビルドする場合 chroot を使用する方法を推奨します。

/etc/pacman.conf を編集して [multilib] リポジトリをアンコメントしてください:

[multilib]
Include = /etc/pacman.d/mirrorlist

公式リポジトリから gcc-multilibインストールしてください。

$HOME/.makepkg.conf に以下の行を追加するだけで x86_64 で i686 用のパッケージをコンパイルできます:

CARCH="i686"
CHOST="i686-pc-linux-gnu"
CFLAGS="-march=i686 -O2 -pipe -m32"
CXXFLAGS="${CFLAGS}"

次のコマンドで makepkg を呼び出して下さい:

$ linux32 makepkg -src

i686 パッケージをコンパイルし終わった後は $HOME/.makepkg.conf を忘れずに削除または修正してください。

他のアーキテクチャ

Arch Linux ARM

Arch Linux ARM デバイスでビルドをする場合、開発者は公式のプロジェクトツールチェインを使用することを強く推奨しています:

必要なアーキテクチャのツールチェインをスレーブのファイルシステムのどこかに展開して /etc/conf.d/distccd を編集し、ツールチェインが使えるように PATH を通してください。

例えばツールチェインを /mnt/data に展開した場合:

PATH=/mnt/data/x-tools8/aarch64-unknown-linux-gnueabi/bin:$PATH

設定ファイルが読み込まれるように、distcc.service再起動する必要があります。

makepkg を使用しないでビルドする場合、任意でユーザーのホームディレクトリにリンクを作成してください。例:

$ ln -s /mnt/data/x-tools8 x-tools8

pacman でバージョンを制御することができ distccd の設定が含まれている distccd-alarm パッケージも存在します。

追加ツールチェイン

ツールチェインを入手する方法は複数存在します:

  • EmbToolkit: クロスコンパイルツールチェインを作成するためのツール。ARM と MIPS アーキテクチャをサポートしており、LLVM ベースのツールチェインのビルドをサポートしています。
  • crosstool-ng: EmbToolkit と同じようなツール。EmbToolkit よりも多数のアーキテクチャをサポートしています (詳しくはウェブサイトを参照)。
  • Linaro: ARM 開発用のツールチェインを提供しています。

EmbToolkit にはツールチェインを設定するためのグラフィカルな設定メニュー (make xconfig) が付属しています。

トラブルシューティング

Journalctl

問題が発生したときは journalctl を使って原因を確認してください:

$ journalctl $(which distccd) -e --since "5 min ago"

code 110

distcc デーモンのプロセスが起動されるユーザーアカウント (デフォルトは nobody) でツールチェインが正しく機能することを確認してください。以下ではユーザー nobody でツールチェインが動作することをテストします。/etc/passwd で nobody ユーザーのログインを以下のように変更してください:

$ cat /etc/passwd
...
nobody:x:99:99:nobody:/:/bin/bash
...

それからクロスコンパイラのバイナリが存在するディレクトリに cd してからコンパイラの実行を試行します:

# su nobody
$ ./gcc --version
bash: ./gcc: Permission denied

上記のエラーが発生する場合、#他のアーキテクチャ に記述されているグループパーミッションの設定を正しく行ったか確認してください。

変更を行った後は /etc/passwd を元に戻すようにしましょう。

もしくは、sudo を使うことで /etc/passwd でシェルを変更しなくても実行できます:

# sudo -u nobody gcc --version

ログレベルを設定する

デフォルトでは、distcc は /var/log/messages.log にログを出力します。このログはファイルに直接出力することができます (distccd の man ページで実際に推奨されています)。ログファイルを /tmp を使って RAM 上に配置することも可能です。また、ログファイルに出力されるエラーのログレベルを下げることもできます。接続のエントリよりもエラーメッセージを見たいというときに有用です。LEVEL は標準的な syslog のレベルで設定でき critical, error, warning, notice, info, debug などを指定します。

以下の行を /etc/conf.d/distccd の DISTCC_ARGS に追記してください:

DISTCC_ARGS="--user nobody --allow 192.168.0.0/24 --log-level error --log-file /tmp/distccd.log"

$HOME/.distcc を移動して HDD/SSD の使用量を制限する

デフォルトでは、distcc は $HOME/.distcc を作成して、一時的に情報を保存してノードにコンパイルさせる作業を割り当てます。/tmp などの RAM に .distcc という名前のディレクトリを作成して $HOME の .distcc にソフトリンクします。これで無駄な HDD の読み書きが減ります。特に SSD の場合は効果的です。

$ mv $HOME/.distcc /tmp
$ ln -s /tmp/.distcc $HOME/.distcc

systemd を使って再起動時にこのディレクトリを再作成 (他のファイルと同じように手動で削除されるまでソフトリンクは消えません) します。以下の tmpfile を作成:

/etc/tmpfiles.d/tmpfs-create.conf
d /tmp/.distcc 0755 <username> users -