C/C++のコンパイル高速化ツール ccache のキャッシュを複数ユーザーで共有してビルドを高速化する方法を説明します。


ccacheとは

c/c++ のコンパイルを高速化するツールにccacheというものがあります。 コンパイル結果をキャッシングしておき次回以降のビルドを高速化するツールです。C/C++界隈ではメジャーなツールです。 Arduino のビルド高速化なんかにも使えたりします(下記の記事参照)

特定の機種をチームで開発するときは各人が同じコードをコンパイルしていることが多いと思います。 そこで今回は、ccacheがキャッシングした結果を複数ユーザーで共有することでみんなでccacheの恩恵にあずかろうという話です。 みんなでキャッシュを使うことでよりキャッシュヒットの効果がでやすくなるはずです。

また、ビルドといえばJenkinsを利用している方も多いと思いますが、 ユーザーと Jenkins とで ccacheの結果を共有するコツも合わせて記載します。 Jenkinsがキャッシュを共有することでつねにキャッシュが更新されるので他のユーザがより恩恵を預かりやすくなります。

注意点ですが、ここでは同一マシンを使うユーザーを想定しています。リモートのマシン間での共有は想定していません。 リモート間での共有に興味がある方は distcc で検索してみてください。

共用キャッシュディレクトリの作成

ccache はデフォルトの設定では各ユーザのホームディレクトリ配下の~/.ccache ディレクトリの下にキャッシュファイルを生成します。 しかしこれではユーザ間でキャッシュファイルを共有することができません。 そこでまず、みんながアクセスできるような場所にキャッシュを保存するディレクトリを作成します。

場所はどこでもいいのですが SSDなどの高速なストレージ上がいいと思います。HDDは避けたほうがいいでしょう。 ここでは例として /mnt/ssd/.ccache/を共有キャッシュディレクトリにすることにします。 下記のように普通にディレクトリを作成します。

1
2
cd /mnt/ssd/
mkdir .ccache/

共用キャッシュディレクトリのアクセス権設定

つぎに、他のユーザも共用キャッシュディレクトリにアクセスできるようにします。 といっても、だれでもかれでもアクセスできるようにするわけには行かないので、 ここではグループを作成することにします。

グループ名は何でもいいのですが、ここでは ccacheとしておきます。 そしてそのグループに ccache を使うユーザを追加します。 下記の例では username_1 username_2 というユーザを追加しています。

1
2
3
groupadd ccache
sudo adduser username_1 ccache
sudo adduser username_2 ccache

また、新規に作成されるディレクトリのために setgid もしておきます。

1
2
chgrp ccache /mnt/ssd/.ccache/
chmod g+s /mnt/ssd/.ccache/

コンパイル時の環境変数設定

あとは環境変数にてキャッシュディレクトリの場所の設定を行います。またあわせて umask の設定も必要です。 下記のようにすればOKです。

1
2
export CCACHE_DIR=/mnt/ssd/.ccache/
export CCACHE_UMASK=002

これで ccache を実行すれば /mnt/ssd/.ccache/ 以下にキャッシュファイルが出力され、かつ、 他のユーザもそれを利用することができるようになります。

Jenkins の場合の設定

せっかくなら常時ビルドを実行しているJenkinsともキャッシュを共用したいところです。 Jenkins ジョブはユーザー jenkins グループ jenkinsとして実行されるので、 ccache グループに jenkinsを追加すれば良さそうに思えます。 しかしそれでは下記のようなエラーが出てしまいます。

1
ccache: error: Failed to create temporary file for /mnt/ssd/.ccache/tmp/tmp.cpp_stderr: Permission denied

じつはJenkins ジョブのユーザーとグループは /etc/default/Jenkins ファイルにて設定されています。 なのでそのファイルを変更する必要があります。 まずは root 権限でエディタでファイルを開きます。

1
sudo emacs /etc/default/Jenkins

下記のような設定箇所がありますので、 JENKINS_GROUPccacheに変更します。

1
2
3
4
# user and group to be invoked as (default to jenkins)
JENKINS_USER=$NAME
#JENKINS_GROUP=$NAME
JENKINS_GROUP=ccache

あとは下記のように Jenkins をリスタートさせれば、Jenkinsも共用キャッシュを利用できるようになります。

1
sudo service jenkins restart

まとめ

今回は同一マシン上で ccache のキャッシュファイルを共有する方法を説明しました。 また、Jenkinsでもccache のキャッシュファイルを共有する方法も説明しました。 Jenkinsと組み合わせることで常にキャッシュが更新された状態にできますのでますますccacheを便利に使えると思います!