Distcc
Distcc はネットワーク上のホストで分散コンパイルを行うためのプログラムです。
distcc は、サーバーの distccd とクライアントの distcc で構成されています。また、 ccache 、 Portage 、Automake との透過的な連携もちょっとしたセットアップで可能となります。
Gentooのインストールに distcc を使いたい場合は、 ブートストラップに使う を参照してください。
ホストで異なるアーキテクチャの distcc や異なるツールチェーンを実行するには、 Distcc/Cross-Compiling を参照してくください。
distcc はコンパイル時にバグ bug #691544 のような問題を引き起こすことがあるため、このような問題に遭遇した場合には、最初のトラブルシューティング手段として、distcc を無効化して問題が解決するか確認するようにしてください。
distcc のいくつかの使用事例においては、高速な2台目のコンピュータを使ってバイナリパッケージをビルドし、 バイナリパッケージホストを構成 した方がより利便性が高い可能性があります。この方法は、セットアップが簡単で、すべてのコンパイラとビルドシステムを対象にできるでしょう。
インストール
distcc を構築する前に、まずは使用するすべてのホストに sys-devel/distcc パッケージが導入されているかどうか確認しましょう。
全てのホストで必要なこと
distcc を使用するには、ネットワークのすべてのコンピュータのGCCが同じバージョンでなければいけません。例を挙げますと、3.3.x(xは任意の数字)を混在させるのは問題ありませんが、3.3.xと3.2.xを混在させた場合はコンパイルエラーや実行時エラーが起きるかもしれません。
すべてのシステムが同じバージョンのbinutilsを使用しているか確認してください( eselect binutils list )。そうでないと,多くのパッケージがテキストリロケーションのような様々なエラーが出てリンクに失敗するでしょう。
USE フラグ
USE flags for sys-devel/distcc Distribute compilation of C code across several machines on a network
gssapi
|
Enable support for net-libs/libgssglue |
gtk
|
Add support for x11-libs/gtk+ (The GIMP Toolkit) |
hardened
|
Activate default security enhancements for toolchain (gcc, glibc, binutils) |
ipv6
|
Add support for IP version 6 |
selinux
|
!!internal use only!! Security Enhanced Linux support, this must be set by the selinux profile or breakage will occur |
xinetd
|
Add support for the xinetd super-server |
zeroconf
|
Support for DNS Service Discovery (DNS-SD) |
Distccには分散コンパイルしているタスクを監視するグラフィカルモニタが付属しています。
gtk
USEフラグをセットすると、このユーティリティーを使えるようにできます。
Emerge
USEフラグの設定 が終わったら sys-devel/distcc パッケージをインストールします:
root
#
emerge --ask sys-devel/distcc
sys-devel/distcc は分散コンパイルに使う全てのホストにインストールしてください。
設定
サービス
distccd を自動的に起動するためには、次の方法に従ってください。
OpenRC
/etc/conf.d/distccd
を編集して、必ず
--allow
ディレクティブを信頼できるクライアントだけが許可されるように設定してください。さらにセキュリティを高めるには
--listen
ディレクティブを使ってどのIPで接続を受け付けるかを
distccd
デーモンに知らせてください(複数のネットワークに接続しているシステムの場合)。
distcc
のセキュリティについての詳細は、
Distcc security notes
を参照してください。
distccサーバのポートに接続できる人は誰でもdistccdのユーザとして恣意的なコマンドを実行することが出来ます。
次の設定例では、
192.168.0.4
と
192.168.0.5
で実行されている distcc クライアントは、ローカルで実行されている
distccd
サーバへの接続が許されます:
/etc/conf.d/distccd
ある特定のクライアントがdistccに接続できるようにする
DISTCCD_OPTS="--port 3632 --log-level notice --log-file /var/log/distccd.log -N 15 --allow 192.168.0.4 --allow 192.168.0.5"
/var/log 内のファイルにログを出力するには、そのログを作成して適切なパーミッションを与えてください:
root
#
touch /var/log/distccd.log
root
#
chown distcc:root /var/log/distccd.log
重要なことは、
--allow
と
--listen
を使用することです。
distccd
man ページか、もっと詳しくは上記のセキュリティについてのドキュメントをご覧ください。
それでは、分散コンパイルに参加する全てのコンピュータで distccd デーモンを起動しましょう:
root
#
rc-update add distccd default
root
#
rc-service distccd start
systemd
/etc/systemd/system/distccd.service.d/00gentoo.conf ファイルを編集して、 CIDR フォーマットにて許可するクライアントを追加してください。192.168.1.xxxの範囲にあるすべてのIPアドレスを追加する例をあげますと:
/etc/systemd/system/distccd.service.d/00gentoo.conf
ALLOWED_SERVERS の設定
Environment="ALLOWED_SERVERS=192.168.1.0/24"
複数のクライアントを設定し、ログレベルを手動で指定する例:
/etc/systemd/system/distccd.service.d/00gentoo.conf
ALLOWED_SERVERS を設定する
Environment="ALLOWED_SERVERS=127.0.0.1 --allow 192.168.1.0/24 --allow 10.1.1.1/24 --log-level error"
ここで使われている ALLOWED_SERVERS という変数名はいささか混乱を招きます。なぜなら、それはローカルの distccd サーバに接続を許されている クライアント (複数)を指し示しているからです。この変数は、 distccd サービスで使用される
--allow
オプションに引き渡されます。– さらなる情報については
/usr/lib/systemd/system/distccd.service
ファイルを参照してください。
OpenRC とは対照的に、 /etc/env.d/* に置かれた環境変数は env-update を実行して distccd サービスを再起動した後でも、systemd では効果がありません。これは、 env-update によって生成される /etc/environment.d は systemd ユーザインスタンスからしか source されない一方、 distccd は systemd システムインスタンスとして生成されるためです。
distccd 用の適切な環境変数を設定するには、以下のように、 /etc/systemd/system/distccd.service.d/00gentoo.conf に設定します:
/etc/systemd/system/distccd.service.d/00gentoo.conf
[Service]
Environment="ALLOWED_SERVERS=192.168.121.0/24"
Environment="DISTCC_VERBOSE=1"
Environment="DISTCC_SAVE_TEMPS=1"
Environment="CCACHE_DIR=/var/cache/ccache"
/etc/systemd/system/distccd.service.d/00gentoo.conf ファイルの
Environment=
ディレクティブは、変数展開に対応していません。
Environment="PATH=/usr/lib/ccache/bin:$PATH"
は文字通りに解釈され、意図したとおりには動作しないでしょう。
これを回避するには、以下のコマンドを実行して distccd.service を編集します:
root
#
systemctl edit --full distccd.service
このコマンドによって、エディタが開きます。
ExecStart=
ディレクティブの行を以下のように変更します:
ExecStart=/bin/bash -c "PATH=/usr/lib/ccache/bin:$PATH exec /usr/bin/distccd --no-detach --daemon --port 3632 -N 15 --allow $ALLOWED_SERVERS --log-level debug"
代わりに、シェルスクリプトで /usr/bin/distccd のラッパーを書くこともできます。
このような変更をした後は、ユニット・ファイルをリロードしましょう:
root
#
systemctl daemon-reload
distccd の自動起動を有効にして、サービスを開始します:
root
#
systemctl enable distccd
root
#
systemctl start distccd
参加するホストを記述する
ローカルクライアントで distcc-config コマンドを使用すれば、ホスト (distccd をサービスとして実行しているシステム) のリストを設定することができます。
ホストのリストの書き方の一例を下に記します。ほとんどのケースでは、1行目と2行目の書き方で十分でしょう。
2行目の書き方のように
/limit
シンタックスを使えば、
distcc
にこのノードで最大いくつのジョブを起動できるかを知らせることができます。
distcc マニュアルページ
では、3行目や4行目のような書き方の詳しい説明が載っています。
192.168.0.1 192.168.0.2 192.168.0.3
192.168.0.1/2 192.168.0.2 192.168.0.3/10
192.168.0.1:4000/2 192.168.0.2/1 192.168.0.3:3632/4
@192.168.0.1 @192.168.0.2:/usr/bin/distccd 192.168.0.3
ホストをセッティングする方法にはここで挙げたほかにもいくつかやり方がありますので、詳細については、man ページをご覧ください。
ローカルマシンでもコンパイル作業をさせたいのなら、ホストのリストに
localhost
を追加しましょう。逆に、ローカルマシンにコンパイル作業をさせたくない場合には、リストから外しましょう。遅いマシンで localhost を設定すると、実際すべてのことが遅くなってしまうでしょう。また、最高のパフォーマンスに調整するためには、設定したものをテストするのも忘れないでください。
例の中の最初の一行目で書かれたホストを使用して、 distcc の環境を設定してみます:
root
#
/usr/bin/distcc-config --set-hosts "localhost 192.168.0.1 192.168.0.2 192.168.0.3"
Distccは、 pump コマンドを実行することで、 pump モードもサポートします。これは、複数のファイルが並行ビルドされる場合のビルド時間を大幅に減少させます。このモードは、プリプロセス済みのヘッダーをサーバー側にキャッシュし、結果としてこれらのヘッダーファイルが繰り返しアップロード・プリプロセスされないようにします。
ホストをpumpモード用に設定するには、
,cpp,lzo
というサフィックスをホスト定義に加えます。pumpモードは
cpp
および
lzo
フラグを(ファイルがCであるかC++であるかに関わらず)必要とします:
root
#
/usr/bin/distcc-config --set-hosts "192.168.0.1,cpp,lzo 192.168.0.2,cpp,lzo 192.168.0.3,cpp,lzo"
また、ホストは以下のファイルに含まれている必要があります:
/etc/distcc/hosts
--set-hosts と一致している必要があります
192.168.0.1
192.168.0.2
192.168.0.3
オプションとして、各ホストの後ろにスラッシュ "/" を追加すると、ホストが使用するスレッド数の上限を設定できます:
/etc/distcc/hosts
スレッド数の上限を指定する
192.168.0.1/8
192.168.0.2/4
192.168.0.3/16
distcc-config コマンドについても同様です。スレッド数の上限が指定されていない場合のデフォルトは4です。
使い方
Portageで使用する
Portage が distcc を利用できるように設定するのは簡単です。 distcc feature を有効にして、同時に実行されるビルドジョブ数を適切な値に設定してやるだけです ( distcc によってビルドに使用されるリソースの量が増加するため)。
下に示したように、 MAKEOPTS 変数と FEATURES 変数を設定してください。
一般的な戦略としては:
-
Nの値を トータルの (ローカルとリモートの)CPUコアの個数の 2倍 + 1に設定し、 -
Mの値を ローカルの CPUコアの個数に設定します。
MAKEOPTS
変数で
-lM
を使用すると過剰なタスクが起動されてしまうのを防ぐことができます。例えば、
distcc
クラスタホストのいくつかが利用できなくなった時(他のシステムでの並列ジョブの量が増加します)や、ebuild でリモートビルドを禁止している時(gccなど)です。この仕組みは、システム負荷が
M
値以上になった時に、それ以上のジョブの追加を拒否することによって行われます。
/etc/portage/make.conf
MAKEOPTSとFEATURESの設定
# NとMを計算した正しい値に置き換えてください
MAKEOPTS="-jN -lM"
FEATURES="distcc"
例えば、 distccd を実行している4コアのホストPC2台と2コアのローカルPCがあったと仮定しましょう。すると MAKEOPTS 変数は次のようになります:
/etc/portage/make.conf
4コア2台(リモート)と2コア1台(ローカル)での MAKEOPTS の設定例
# 4コアのリモートホスト2台 = 8 コアのリモート
# 2コアのローカルホスト1台 = 2 コアのローカル
# コアの総数は、10 なので、 N = 2*10+1 、M=2
MAKEOPTS="-j21 -l2"
CFLAGS と CXXFLAGS
make.conf
ファイルを編集するとき、
CFLAGS
や
CXXFLAGS
変数で
-march=native
を設定してはいけません。これはよく確認してください。
march
が
native
に設定されていると、
distccd
は作業を他のマシンにうまく分散しなくなるでしょう。そうではなく、正確なプラットフォーム名と、その CPU のために必要な追加のフラグを列挙するべきです。例えば:
/etc/portage/make.conf
インライン化された *FLAGS
# 最小限のフラグのリストは以下で生成されます:
# $ diff -U0 <(LANG=C gcc -Q -O2 -march=sandybridge --help=target) <(LANG=C gcc -Q -O2 -march=native --help=target)
COMMON_FLAGS="-march=sandybridge -mtune=sandybridge -maes" # -march=native を使わないで!
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
詳しくは、
Inlining
-march=native
for distcc
をご覧ください。
代わりに、
app-misc/resolve-march-native
をインストールして
-march=native
がどのように展開されるか特定することもできます。
automake で使用する
これは、場合にもよりますが、Portageのセットアップよりも簡単です。 PATH 変数の gcc のあるディレクトリ( /usr/bin/ )よりも先頭に /usr/lib/ditcc/bin/ を書き込むだけでよいのです。ただし、ちょっと注意が必要です。もし ccache をご使用の場合は、 ccache のディレクトリよりも後ろに distcc のディレクトリを配置してください:
root
#
export PATH="/usr/lib/ccache/bin:/usr/lib/distcc/bin:${PATH}"
これをユーザの ~/.bashrc 等のようなファイルに書き込んでおき、ユーザがログインするたびに PATH が設定されるようにしておきましょう。 もしくは、 /etc/env.d/ ファイルに書き込んでグローバルに設定するのもよいかもしれません。
何もつけずに
make
を呼び出すより、
-jN
(
N
は整数)をつけましょう。
N
は、コンパイルに使用するコンピュータのネットワークとタイプによって違います。このアーティクルの最初のところで適切な値の見つけ方をすでに書いておきましたのでご参考ください。
ccache で使用する
Ccache を distcc と連携させるには、いくつかの前提条件を満たす 必要があります :
- Ccache が ローカルで 正しくセットアップされている
- Distcc が使用したいホストで正しくセットアップされている
以下のセットアップは、以下のように動作します:
[client] [remote]
'''ccache''' <ない?> → コンパイルしてキャッシュファイルを保存し、
<ある?> さらに他のソースコードを配布する → '''distcc''' → '''ccache''' <ない?> → コンパイルしてキャッシュファイルを保存し、クライアントにキャッシュファイルを返す
↓ <ある?>
ローカルのキャッシュファイルを使用する ↓
ローカルのキャッシュファイルをクライアントへ返す
以下の設定は、必ず全てのホストで行ってください!
distccd の設定
distccd
デーモンに
ccache
を使用させるためには、
/usr/bin
のパスを
/usr/lib/ccache/bin
でマスカレードする
必要があります
。さらに、この場合、
ccache
では
distcc
というプレフィックスを使用します:
/etc/conf.d/distccd
PATH="/usr/lib/ccache/bin:${PATH}"
CCACHE_PREFIX="distcc"
さらに、 distccd には DISTCC_DIR と CCACHE_DIR という環境変数を認識させる 必要があります :
これらの変数は、 /etc/env.d/ 内のどこかで設定されて いなければいけません 。さもないと、 ccache はキャッシュファイルを ${HOME}/.ccache/ に置こうとして、権限が不十分であるために COMPILE_ERROR を引き起こします。これを再現するには、前に触れた テストの例 と ここ で触れた export DISTCC_SAVE_TEMPS="1" を使用してください。こうすると、デフォルトでは /tmp/ にリモートサイトからのエラーログが保存されます。ログはこの様な名前になっているでしょう: distcc_server_stderr_*.txt 。これらの環境変数は、 /etc/conf.d/distccd 内では設定できないことに注意してください。このファイルは、ある理由から、 distccd から読み込まれません。
/etc/env.d/03distcc_ccache
CCACHE_DIR="/var/cache/ccache"
DISTCC_DIR="/var/tmp/portage/.distcc"
次に、環境変数を更新します:
root
#
env-update
>>> Regenerating /etc/ld.so.cache...
最後に、全ての変更を適用するため、 distccd を再起動します:
root
#
rc-service distccd restart
ccache の設定
distcc を ccache と併用する場合、 手動で キャッシュファイルを用意する必要があります。これは、ある理由から、 distccd デーモンが /var/cache/ccache/ 内にディレクトリを作成できない
distcc
ユーザーでしか動作しないためです。このユーザーを
portage
グループに追加するだけでは不十分です。また、
ccache.conf
で定義されている
cache_dir_levels
変数が作成するサブディレクトリの数を指定していることにも注意してください。以下の例では、デフォルト値の
2
が使用されています。
最初に、キャッシュディレクトリを用意します:
root
#
cd "/var/cache/ccache/"
root
#
mkdir {a..z} {0..9} tmp
root
#
for first_level_directory in $(find . -maxdepth 1 -type d -not -name "." -and -not -name "tmp"); do pushd "${first_level_directory}" >/dev/null; mkdir {a..z} {0..9}; popd >/dev/null; done
2つめの (
mkdir
) コマンドは、
a
から
z
まで、
0
から
9
までおよび
tmp
の
第1レベルディレクトリ
を作成します。続く
for
ループは、現在のディレクトリ
.
と
tmp
を除く(
-not -name "." -and -not -name "tmp"
)
第1レベルディレクトリ
を検索します (
find . -maxdepth 1 -type d
)。そして、それら1つ1つに入り (
pushd
)、
a
から
z
までと
0
から
9
までの
第2レベルディレクトリ
を作成 (
mkdir
) して、元のディレクトリ
/var/cache/ccache/
に戻ります (
popd
)。
現在のディレクトリ . は必ず
-not -name "."
として除外
しなければなりません
。さもないと、最初の
pushd
コマンドで
.
に行き、そして
popd
によって現在スタックにあるディレクトリに戻ってしまいます。こうなると、スタックが空になるまでスタック全体を渡り歩き、そこで
pushd
が失敗するようなフォルダを作成することになります。これが起こった場合、
find / -type d -name "0"
でそうしたフォルダを探し出し、
rm --recursive [a-z] [0-9]
で削除できます。この作業は
手動で
行うようにしてください!
準備が済んだら、全てのディレクトリ -
ccache
ディレクトリ自体も含めて - の所有者を
distcc
ユーザーに設定
しなければなりません
:
root
#
find /var/cache/ccache -type d -exec chown distcc:portage "{}" +
portage の設定
emerge で distcc と ccache を使用する場合は、両方の feature を有効化し、 /etc/portage/make.conf で CCACHE_DIR を設定します:
/etc/portage/make.conf
[...]
FEATURES="distcc ccache"
CCACHE_DIR="/var/cache/ccache"
CCACHE_DIR は、 ここ で触れたとおり、 /etc/env.d/03distcc_ccache で既に定義されているため、ここでの設定は冗長にも思えます。しかし、万全を期するため、このようにしておきましょう。
ccache を併用している distcc を手動でテストする
リモート
まず
/etc/conf.d/distccd
で
--log-level
を
debug
に設定して、詳細なログを有効にします:
/etc/conf.d/distccd
[...]
DISTCCD_OPTS="${DISTCCD_OPTS} --log-level debug"
[...]
続いて、変更を適用するためデーモンを再起動します:
root
#
rc-service distccd restart
また、
/var/cache/ccache
内に
distcc
が所有者になっていないディレクトリ -
ccache
ディレクトリ自体も含めて - がないか確認し、所有者の権限を修正します:
root
#
chown -R distcc:portage /var/cache/ccache
クライアント
以下の変数が現在のシェルで提供されていることを確認してください:
root
#
export PATH="/usr/lib/ccache/bin:${PATH}"
root
#
export CCACHE_DIR="/var/cache/ccache"
root
#
export DISTCC_DIR="/var/tmp/portage/.distcc"
root
#
export DISTCC_SAVE_TEMPS="1"
root
#
export DISTCC_VERBOSE="1"
次に、 /tmp/ 内の一時ディレクトリに移動し、先に触れた 例 をコンパイルします:
root
#
cd $(mktemp --directory)
root
#
distcc gcc -c main.c -o main.o
詳細な出力がされると同時に、リモートサイトから受信した一時ファイルもデフォルトでは /tmp/ に保持されます:
[...]
distcc[29466] (dcc_cleanup_tempfiles_inner) skip cleanup of /tmp/distcc_9c42f0a6.i
distcc[29466] (dcc_cleanup_tempfiles_inner) skip cleanup of /tmp/distcc_server_stderr_9cc0f0a6.txt
[...]
リモートサイトで発生した全てのエラーは /tmp/distcc_server_stderr_*.txt に保存されます。
コンパイルが成功した場合、以下の行が表示されます:
[...]
distcc[29466] compile main.c on 192.168.0.4 completed ok
[...]
リモートサイトでは、以下のようになります:
[...]
distccd[13296] (dcc_check_compiler_masq) /usr/lib/ccache/bin/gcc is a safe symlink to /usr/bin/ccache
[...]
distccd[13296] (dcc_job_summary) client: 192.168.0.4:33880 COMPILE_OK exit:0 sig:0 core:0 ret:0 time:20ms gcc main.c
ここで重要なのは、 /usr/lib/ccache/bin/ 内のシンボリックリンクがいずれも /usr/bin/ccache を指す安全なシンボリックリンクであることです。
また、リモートサイトでは、このwiki記事の例をファイル名も含めてコピーしたと仮定すると、 /var/cache/ccache/c/0/ 内に 2beaa22dc2a2873d6869d69411840c-17229.o というファイルがキャッシュされているはずです。一般的に、コンパイル中に watch "ccache --show-stats" を使用することで ccache のサイズを監視することができます。
ccache を併用している distcc を emerge を使用してテストする
ここ を参照して必要な環境変数が現在のシェルで提供されていることを、 ここ を参照して /etc/portage/make.conf が正しく設定されていることをそれぞれ確認してください。
リモートサイトでキャッシュファイルをいくつか生成するために、クライアントで
htop
や
bzip2
のような小さいパッケージをコンパイルします:
root
#
emerge --ask htop bzip2
今後のために
使用するシェルで以下の環境変数が常に設定されていることを確認してください:
PATH="/usr/lib/ccache/bin:${PATH}"
CCACHE_DIR="/var/cache/ccache"
DISTCC_DIR="/var/tmp/portage/.distcc"
ブートストラップに使う
TODO: Todo:
- この節に古い情報がないか確認してください。特に、"USE='-*'" と "--nodeps" はもはや推奨されないでしょう。詳しくは、議論ページを参照してください。
distcc をブートストラップに使う(たとえば、システムの残りをインストールする前にワーキングツールチェーンをビルドする)には、いくつか手間をかける必要があります。
Step 1: Portage の設定
Gentoo Linux LiveCDで新しくマシンを立ち上げて インストール手順 に従ってください。さらに、ブートストラップについての情報も Gentoo FAQ にありますので参考にしましょう。その次に dsitcc を使用してPortageを初期設定してください:
/etc/portage/make.conf
distccを使用するためのPortageの設定
FEATURES="distcc"
MAKEOPTS="-jN"
インストールセッションでの PATH 変数を次のように更新します:
root
#
export PATH="/usr/lib/ccache/bin:/usr/lib/distcc/bin:${PATH}"
Step 2: distcc をゲット
sys-devel/distcc をインストール:
root
#
USE='-*' emerge --nodeps sys-devel/distcc
Step 3: distcc のセッティング
distcc-config
を実行してdistccをセットアップしましょう。例中の
host#
には参加するノードの実際のIPアドレスやホスト名を入れてください。
root
#
/usr/bin/distcc-config --set-hosts "localhost host1 host2 host3 ..."
これでdistccはブートストラップ用に新しく設定されました。以降はインストールの手順に従ってください。 emerge @system の後に emerge distcc を実行するのを お忘れなく 。これは、すべての必要な依存関係のあるパッケージがインストールされているのかを確認するために行います。
ブートストラップと emerge @system の間、 distcc が使われていないことを見つけてしまうかもしれません。これはdistccとうまくいかないようなebuildがあり、そのようなebuildはわざとdistccを使用しないようにしているためで、予期される動作です。
付属するツール群
distcc アプリケーションには、 distcc 環境での作業をサポートするための機能やアプリケーションがあります。
監視ユーティリティ
Distccには2つの監視ユーティリティが付属しています。テキストベースの監視ユーティリティは
distccmon-text
で、必ずビルドされます。最初に実行するときは少々混乱するかもしれませんが、実際とても簡単に使うことができます。パラメータなしで実行したときは、プログラムは1回だけ実行されますが、引数に
N
を渡すと、
N
秒ごとに更新が行われます。
user
$
distccmon-text 10
もうひとつの監視ユーティリティは
gtk
USE フラグがセットされた時のみ有効になります。これはGTKベースで、X環境で動作し、なかなか良い外見をしています。
Gentooでは、このGUIモニタは混乱を避けるため
distccmon-gui
にリネームされています(もともとの名前は
distccmon-gnome
です)。
user
$
distccmon-gui
Portageでの distcc の使用をモニタするには:
root
#
DISTCC_DIR="/var/tmp/portage/.distcc/" distccmon-text 10
root
#
DISTCC_DIR="/var/tmp/portage/.distcc/" distccmon-gui
もしdistccディレクトリが別の場所にあるなら、それに合わせて DISTCC_DIR 変数を変えてください。
DISTCC_DIR を環境変数にセットするための良い方法:
root
#
echo 'DISTCC_DIR="/var/tmp/portage/.distcc/"' >> /etc/env.d/03distcc_custom
DISTCC_DIR は、 /etc/env.d/02distcc 以外の場所で設定しなければならないことに注意してください。 /etc/env.d/02distcc は、 distcc-config を使用するたびに上書きされます! distcc-config --set-env DISTCC_DIR <some_path> は動作しません。
ここで、環境を更新します:
root
#
env-update
root
#
source /etc/profile
最後に、GUIアプリケーションを起動しましょう。
root
#
distccmon-gui
SSH 通信
SSH経由のdistccをセットアップする場合、いくつかの落とし穴があります。まず、SSHの鍵ペアをパスワードをセットアップせずに生成してください。portageはプログラムをPortageユーザー(または、
FEATURES="userpriv"
がセットされていない場合にはroot)としてコンパイルすることに注意してください。Portageユーザーのホームフォルダーは
/var/tmp/portage/
であり、これは鍵を
/var/tmp/portage/.ssh/
に保存しておく必要があることを意味します。
Portage ユーザーのホームフォルダは、最近のバージョンで /var/lib/portage/home に変更されましたが、このフォルダはコンパイル中にアクセス可能なパスに含まれていないため、SSH を経由する distcc で使用することはできません。以下のように変更しましょう:
root
#
usermod -d /var/tmp/portage portage
root
#
ssh-keygen -b 2048 -t rsa -f /var/tmp/portage/.ssh/id_rsa
次に、SSH設定ファイルに各ホスト用のセクションを作成します:
/var/tmp/portage/.ssh/config
hostごとにセクションを追加する
Host test1
HostName 123.456.789.1
Port 1234
User UserName
Host test2
HostName 123.456.789.2
Port 1234
User UserName
公開鍵を各コンパイルノードに送信します:
root
#
ssh-copy-id -i /var/tmp/portage/.ssh/id_rsa.pub UserName@CompilationNode
また、各ホストが known_hosts ファイルに含まれていることを確認します:
root
#
ssh-keyscan -t rsa <compilation-node-1> <compilation-node-2> [...] > /var/tmp/portage/.ssh/known_hosts
ファイルの所有者を以下のように修正します:
root
#
chown -R portage:portage /var/tmp/portage/.ssh/
test1
と
test2
というホストをセットアップするには、以下を実行します:
root
#
/usr/bin/distcc-config --set-hosts "@test1 @test2"
distccにsshホストを指定する、
@
(@ マーク)に注意してください。
最後に、distccにどのSSHバイナリを使うか指示します:
/etc/portage/make.conf
DISTCC_SSH="ssh"
distcc がSSH経由で通信する場合、ホスト側で distccd のinitスクリプトを実行しておく必要はありません。
リバース SSH
distcc に組み込まれている SSH 機能に代えて、クライアントの distcc TCP ポートをコンパイルサーバーにリダイレクトし、コンパイルサーバーを SSH 経由でクライアントに接続させることができます。クライアント側でパスワードなしの SSH 鍵を用意する必要はありません:
user
$
ssh -R3632:127.0.0.1:3632 root@distcc-client
distcc は localhost を特別な用途のためのリテラルキーワードとして使用するため、代わりに 127.0.0.1 を使用しなければならないことに留意してください。 複数のコンパイルサーバーがある場合、それぞれクライアントの別のポートをリダイレクトする必要があります (例えば 127.0.0.1:4000、127.0.0.1:4001 など)。IP アドレスとポートがクライアントの /etc/distcc/hosts に列挙されていることを確認してください。
テスト
distcc をテストするには、簡単な Hello distcc プログラムを書いて distcc をverboseモードで実行し、正しく通信できているか確認します。
main.c
#include <stdio.h>
int main() {
printf("Hello distcc!\n");
return 0;
}
次に、verboseモードを有効にしてからdistccを使ってプログラムをコンパイルし、生成されたオブジェクトファイルをリンクして実行可能ファイルにします。
user
$
export DISTCC_VERBOSE=1
user
$
distcc gcc -c main.c -o main.o # または 'pump distcc <...>'
user
$
gcc main.o -o main
pumpモードを使用するには、 distcc コマンドを pump distcc に置き換えてください。
distccの設定の探索、接続するホストの選択、接続の開始、そして最後に main.c のコンパイルについて、一連の出力があるはずです。出力の中で使いたい distcc ホストがリストされない場合、設定を確認してください。
最後に、コンパイルされたプログラムが正しく動作するか確認してください。ホストそれぞれについてテストするには、hostsファイルで各コンパイルホストを列挙してください。
user
$
./main
Hello distcc!
トラブルシューティング
distcc をご使用中に問題が発生したときには、このセクションをお読みになれば問題解決の糸口となるかもしれません。
ERROR: failed to open /var/log/distccd.log
2015年1月22日以降、emergeすると /var/log/ に適切な distccd.log ファイルを作るのに失敗します。これは、 distcc ver.3.1-r8 のみに起こることが明らかにされています。このバグは現在修正中ですが(参照: bug #477630 )、手作業でそのログファイルを作成し、適切な所有者を設定し、distccデーモンを再起動することで何とかうまく動くようにできます。
root
#
mkdir -p /var/log/distcc
root
#
touch /var/log/distcc/distccd.log
root
#
chown distcc:daemon /var/log/distcc/distccd.log
次に、 /etc/conf.d/distccd にある distccd コンフィグレーションファイルの /var/log の値を先ほど作成した distcc ディレクトリに更新してください:
/etc/conf.d/distccd
Updating log path
DISTCCD_OPTS="--port 3632 --log-level notice --log-file /var/log/distcc/distccd.log -N 15
最後に distccd サービスを再起動します。
root
#
/etc/init.d/distccd restart
distccをつかえないパッケージもあります
様々なパッケージをインストールしていく中で、分散されない(並列にビルドできない)パッケージがあることに気づくでしょう。これは、そのパッケージの Makefile が並列オペレーションをサポートしていない、あるいはそのebuildのメインテナーが既知の問題があるために並列オペレーションを禁止しているからだと思われます。
時として、 distcc はパッケージのコンパイルに失敗することもあります。このようなことが起こりましたら、お手数ですが 報告 してください。
Rust パッケージは過剰な IO 利用を生じさせることが知られており、--local-load は無視されますし、--jobs は通常、ローカルビルドのためのリソースにとっては多すぎることになります。この振舞いを回避するためには、distcc を使用しない場合の MAKEOPTS の値を設定した package.env を準備する必要があります。
/etc/portage/env/nodistcc.conf
MAKEOPTS="-jN"
FEATURES="-distcc"
/etc/portage/package.env/nodistcc
dev-lang/rust nodistcc.conf
mail-client/thunderbird nodistcc.conf
sys-libs/libcxx nodistcc.conf
www-client/firefox nodistcc.conf
GCC のバージョンが混在する場合
もしdistcc環境のホスト間でGCCのバージョンが違っていたら、奇怪な問題が起こるかもしれません。解決法は、すべてのホストが同じバージョンのGCCであることをしっかり確認することです。
最近のPortageのアップデートでは、
gcc
のかわりに
${CHOST}-gcc
(minus gcc)を使うようになっています。しかしながらこのことは、もしi686マシーンがほかのタイプのマシーン(i386,i586)と混在していた場合には、ビルドが失敗に終わってしまうことになります。この問題に対しては、次の対処をするとよいかもしれません:
root
#
export CC='gcc' CXX='c++'
/etc/portage/make.conf の CC と CXX 変数を上記のようにセットしてもよいでしょう。
これを行うことでPortageの振る舞いを明らかに変えてしまい、将来において奇妙な結果を引き起こすことがあるかもしれません。ですので、混在するCHOSTがどうしても避けられないときにのみ行ってください。
サーバー側で正しいバージョンのgccをスロットとしてインストールしているだけでは不十分です。Portageは distcc を CHOST 変数(たとえば
x86_64-pc-linux-gnu
)で参照されるコンパイラーの代わりに使用し、
distccd
はそれをまったく同じ名前で実行します。正しいバージョンのgccは、すべての関係するコンパイルホストにおいてシステムのデフォルトコンパイラーである必要があります。
-march=native
GCC 4.3.0よりコンパイラは
-march=native
オプションをサポートするようになりました。これは、CPU自動判別と最適化の機能を有効にするものでで、GCCが実行されているプロセッサに対しては有効にしておく価値のあるものです。しかしながら、そのオプションで
distcc
を使用した場合には、一つ問題が引き起こされます。理由はそれぞれのプロセッサでの最適化されたコードが混在してしまうからです。例を挙げますと、
-march=native
とともに
distcc
を実行するとき、あるシステムでは AMD Athlon プロセッサで、別のシステムでは Intel Pentiumプロセッサの場合、両方のプロセッサのコンパイルしたコードが混在してしまうのです。
次の注意を心に留めておきましょう:
distcc でコンパイルするときには、 make.conf の CFLAGS 変数または CXXFLAGS 変数で
-march=native
や
-mtune=native
を
使用しないでください
。
詳細については、
CFLAGS と CXXFLAGS 節
や
Inlining
-march=native
for distcc
を参照してください。
ネットワークに到達できない
SSH 接続を使用している場合、このようなエラーが発生することがあります: ssh: Could not resolve hostname: Temporary failure in name resolution 。
network-sandbox
という機能で導入されたネットワークの制約によって、この問題に遭遇することがあります。
distcc
はこのセキュリティ機能とは相反するため、機能を無効化する必要があります:
/etc/portage/make.conf
network-sandbox 機能を無効化する
FEATURES="${FEATURES} -network-sandbox"
emerge のログからより多くの出力を得る
verboseモードを有効にすることで、より多くのログを取得することができます。これは DISTCC_VERBOSE を /etc/portage/bashrc に追加することによって実現できます。
/etc/portage/bashrc
詳細なログを有功にする
export DISTCC_VERBOSE=1
これで、詳細なログが /var/tmp/portage/$CATEGORY/$PF/temp/build.log で見られるようになります。
build.log で見られる最初の distcc の実行は、必ずしもビルドプロセス中の最初の distcc の実行であるとは限らないことを覚えておいてください。たとえば、ビルドサーバーは、コンパイラーを使ったチェックがいくつか実行された場合にconfigurationの段階で1分間のバックオフ期間に入る可能性があります( distcc はリモートサーバーでのコンパイルが失敗すると、それがローカルマシンでも失敗したかどうかに関わらずバックオフ期間を設定します)。
こうした状況を調査するには、 /var/tmp/portage/$CATEGORY/$PF/work/ ディレクトリに入ってください。他のログを探すか、あるいは作業ディレクトリの中から明示的に make を呼び出します。
もう一つの使うと興味深い変数は DISTCC_SAVE_TEMPS です。設定されている場合、リモートのコンパイラーからの標準出力/エラー出力を保存します。Portageビルドでは、結果は /var/tmp/portage/$CATEGORY/$PF/temp/ ディレクトリにあるファイルに保存されます。
/etc/portage/bashrc
一時的な出力の保存
export DISTCC_SAVE_TEMPS=1
ディレクトリ /dev/null/.cache/ccache/tmp を作成できません: ディレクトリではありません
このエラーは、 DISTCC_SAVE_TEMPS が設定されていない場合にサーバーの標準エラー出力ファイルに見られることがあります。これは、 distccd を ccache とともに使用している場合にのみ発生します。
これは、おそらく、 CCACHE_DIR が適切に設定されていないか、 distccd に正しく渡されていないためです。そのような場合、 ccache はキャッシュフォルダにデフォルトの $HOME/.cache/ccache を使用しようとします。しかしながら、 ccache は、 distccd によって、非ログインアカウントである distcc ユーザーで実行されます。 CCACHE_DIR の設定については systemd 節 や ccache で使用する 節 を参照してください。
Portage でのビルドが distcc に全く接続できないといったエラーを出して失敗する
ビルドが distcc に接続できていないかのようなエラーを出して失敗するが、FEATURES="-distcc" とすると動作する場合、DISTCC_VERBOSE=1 が原因となってビルドが失敗していることがあるという報告があります。
関連項目
- Distcc/Cross-Compiling — 異なるプロセッサアーキテクチャ間でクロスコンパイルするために distcc をセットアップする方法を示します。
外部の情報
This page is based on a document formerly found on our main website
gentoo.org
.
The following people contributed to the original document:
Lisa Seelye,
Mike Gilbert (floppym)
, Erwin,
Sven Vermeulen (SwifT)
, Lars Weiler, Tiemo Kieft, and
They are listed here because wiki history does not allow for any external attribution. If you edit the wiki article, please do
not
add yourself here; your contributions are recorded on each article's associated history page.