Gentooで異なるアーキテクチャ間でバイナリパッケージを作る
サーバ機のメンテナンスをしていて、デスクトップマシンとの性能差にうんざりしたので、どうにかしてもっと高速化できないものかと考えました。現在は distcc と crossdev で分散コンパイルとクロスコンパイルを行っているわけですが、サーバの I/O 性能の低さはいかんともしがたく。いくらコンパイル部分を高速化しても configure やソースの展開等で時間がかかってしまい、せっかくの高速化にも限界が。
それじゃぁと。いっそのことデスクトップマシン上でバイナリパッケージを作ってしまうことにしました。
その1 crossdev の機能を使う
先に結論から行くと、私はこの方法は使っていないのですが。
ココ とか ココ とかを見ていて気づいたのですが、環境変数で騙してやれば crossdev で作成したツールチェインを使って異なるアーキテクチャのバイナリを作成できるようです。emerge はシステムルートを環境変数 SYSROOT 変数で判断するようで、コレを / (リアルルート) 以外の場所にしてあげればいいと言うことのようですね。
デスクトップマシンは例によって amd64 環境で、サーバは x86 です。なのでデスクトップマシンで作成したツールチェインは x86 用の i686-pc-linux-gnu で、これは /usr/i686-pc-linux-gnu 以下に展開されています。この配下にサーバとそっくりの環境を整えてあげて SYSROOT="/usr/i686-pc-linux-gnu" を与えて emerge し、その際にバイナリパッケージもつくるようにしてしまえばいいことになります。
ということで作っていいきます。
サーバ上のファイル情報の取得
必要な情報 (ファイル) は以下のもの。
最初の2つは、 sftp なり NFS 共有なりで拾ってきます。最後のはサーバ上でこんな感じでいいかと。
$ ls /etc/make.profile -l lrwxrwxrwx 1 root root 47 2009-10-30 05:07 /etc/make.profile -> ..//usr/portage/profiles/default/linux/x86/10.0
デスクトップ上のファイルの環境構築
サーバ上の情報を元に、こんな感じで配置します。サーバから取得した /etc/make.conf やら /etc/portage/package.* やらは、 /home/nanasi/ に置いてあることにしておきます。
$ sudo su - # mkdir -p /usr/i686-pc-linux-gnu/etc/portage # cp /etc/make.global /usr/i686-pc-linux-gnu/etc/ # cp /home/nanasi/make.conf /usr/i686-pc-linux-gnu/etc/ # cp /home/nanasi/package.* /usr/i686-pc-linux-gnu/etc/portage/ # ln -sn /usr/portage/profiles/default/linux/x86/10.0 / /usr/i686-pc-linux-gnu/etc/make.profile # mkdir -p /usr/i686-pc-linux-gnu/var/lib/portage/ # cp /home/nanasi/world /usr/i686-pc-linux-gnu/var/lib/portage/
このとき、 /usr/i686-pc-linux-gnu/etc/make.conf の中身が i686 向けになっていることを一応確認しておきます。
あとは、ハンドブックに従い、こんな感じで emerge すると幸せになれるようです。 emerge コマンドに -b (または --buildpkg) オプションをつけると、バイナリパッケージが作成されます。デフォルトでは /usr/portage/packages/ 以下です。
# export SYSROOT="/usr/i686-pc-linux-gnu" # CBUILD="i686-pc-linux-gnu" ROOT="$SYSROOT" PORTAGE_CONFIGROOT="$SYSROOT" emerge -avb ntp
その他ラッパースクリプトのようなものも、ハンドブックには書いてあります。
その2 chrootで32bit環境を作ってしまう
chroot でサーバと全く同じ環境を作ってしまう方法です。私はとりあえずこっちを使ってみることにしました。 crossdev でやっていてときどきコンパイルエラーを吐いたり、なぜか 64bit コンパイラが動いているように見えて不安だったからです。
chroot 環境は ココ にある手順にしたがって導入すれば簡単に作成できますが、サーバと同じ環境を作りたいため若干手を加えます。
- /etc/make.conf はサーバにあるものとほぼ同じものを使う
- /etc/portage/package.* をサーバからとってきて同じものを使う
- /var/lib/portage/world をサーバにあるものと同じものにする
- ローカルオーバーレイを反映させる
手順
先程と同様、サーバの設定ファイルは /home/nanasi/ 以下にあることとします。
$ cd /home/nanasi/ $ wget http://ftp.jaist.ac.jp/pub/Linux/Gentoo/releases/x86/autobuilds/current-stage3/stage3-i686-20100601.tar.bz2 (stage3 ファイルは最寄のミラーから最新のものを)
$ sudo su - # cd /mnt # mkdir gentoo32 # cd gentoo32 # tar -xf /home/nanasi/stage3-i686-20100601.tar.bz2 # cp -L /etc/resolv.conf /mnt/gentoo32/etc/ # cp -L /etc/passwd /mnt/gentoo32/etc/
サーバから持ってきたファイルをコピーします。
# cp /home/nanasi/make.conf /mnt/gentoo32/etc/ # mkdir -p /mnt/gentoo32/etc/portage/ # cp /home/nanasi/package.* /mnt/gentoo32/etc/portage/ # mkdir -p /mnt/gentoo32/var/lib/portage # cp /home/nanasi/world /mnt/gentoo32/var/lib/portage/
ハンドブックのとおりにリンク (bind) を張っていきます。
# mount -o bind /dev /mnt/gentoo32/dev # mount -o bind /dev/pts /mnt/gentoo32/dev/pts # mount -o bind /dev/shm /mnt/gentoo32/dev/shm # mount -o bind /proc /mnt/gentoo32/proc # mount -o bind /proc/bus/usb /mnt/gentoo32/proc/bus/usb # mount -o bind /sys /mnt/gentoo32/sys
さらにハンドブックのとおりにリンクを張っていきます。自分の場合ローカルオーバーレイも使用しているので、これも忘れないように追加しておきます。今回のローカルオーバーレイは /usr/local/portage 以下です。
# mkdir -p /mnt/gentoo32/usr/portage/ # mount -o bind /usr/portage /mnt/gentoo32/usr/portage/ # mkdir -p /mnt/gentoo32/usr/local/portage # mount -o bind /usr/local/portage /mnt/gentoo32/usr/local/portage/ # mount -o bind /tmp /mnt/gentoo32/tmp
最後に、 chroot します。自分の環境では linux32 コマンドは既にインストール済でした。またドキュメントでは emerge linux32 でインストールするように書いてありますが、これは若干古いようです。現在は linux32 コマンドは sys-apps/util-linux に入っている模様。
# emerge util-linux # linux32 chroot /mnt/gentoo32 /bin/bash # uname -m i686
あとは、 emerge するだけです。 -b オプションをつけて emerge すればバイナリパッケージが作成されます。または make.conf 内で FEATURES="buildpkg" を指定してやると、常につくるようになります。繰り返しますが、作成先は /usr/portage/packages/ 以下です。 chroot 環境下のディレクトリに作成されます。
なお、作成先は PKGDIR 変数で指定されています。
# emerge --info | grep PKGDIR PKGDIR="/usr/portage/packages"
バイナリパッケージをつかう
パッケージが作成されたら、サーバ上で emerge に -k (または --usepkg) オプションをつけると、バイナリからインストールしようとしてくれます。もちろんサーバから見て /usr/portage/packages/ (PKGDIR変数で指定したディレクトリ) 以下にファイルがなくてはいけませんので、このディレクトリは NFS で共有してしまうといいですね。
# むしろ /usr/portage ごと複数の PC で共有してしまうのが幸せです!
$ emerge -pk ntp [binary R ] net-misc/ntp-4.2.4_p7-r1
表示が binary になっていることを確認して下さい。
なお、 -G や -g なんてオプションも使えますが、詳しくは man emerge で。(笑)
肝心の高速化ですが、コンパイル作業そのものは全て高速な PC 上で行うのでかなり速くなると思います。しかしながらインストールしてあるパッケージを全部コンパイルしなおすことになるので、その時間が…w まぁ、せっかく gcc のバージョンもあがったし、 emerge -e world したと思えばいいかな。
あとは、バイナリからのインストールにそれなりに時間はかかるでしょうけど、それでもコンパイルするよりは速いはず! たぶん。