新APIGentoo山盛り

はじめに

一部で人気を博しているというこの記事から二年もたったのでいい加減いろいろと新しくしていこうと思うんですね。新時代Gentooの福音的な感じでね。

やっぱり想定的にはインストールしたけど、これからどうすんべ? とか、なんとなーくわかってきたけどもう少し楽な方法はなかとかね?ってあたり。

ちなみに環境は testingなので紹介する機能の中にはまだstableでは使えないものもあるかもしれないですね。そのへんはご容赦を。

/etc/make.conf

やっぱり基本となるのはこのファイル。だけど /etc/make.confは/etc/portage/make.confに移動されています。知ってましたか? 新規インストールだけなんでとりあえずそんなに気にすることもないでしょう

*FLAGS
CFLAGS="-O2 -pipe -fomit-frame-pointer -march=corei7-avx -mcx16 -msahf -mno-movbe -maes -mpclmul -mpopcnt -mno-abm -mno-lwp -mno-fma -mno-fma4 -mno-xop -mno-bmi -mno-bmi2 -mno-tbm -mavx -mavx2 -msse4.2 -msse4.1 -mno-lz-cnt -mrdrnd -mf16c -mfsgsbase --param l1-cache-size=32 --param l1-cache-line-size=64 --param l2-cache-size=3072 -mtune=generic -frecord-gcc-switches"
CXXFLAGS="${CFLAGS}"
FFLAGS=${CFLAGS}
FCFLAGS=${CFLAGS}

昔と大きく変わってはいませんね。あいかわらず、 "-march=native -O2 -pipe -fomit-frame-pointer"を展開したものです。それと最後に "-frecord-gcc-switches"をつけています。これがあると、gccがどんなオプションでビルドされたかを記録してくれるので、portageがそれを見て、ユーザの設定したCFLAGSが反映されていないよ?といったチェックができるようになります。まあ、これは開発者用ですね

USE
USE="mmx sse sse2 X emacs ssse3 -ldap xft fbcon xinerama wifi midi cjk xcomposite -bluetooth policykit cdda m17n-lib hddtemp python perl v4l v4l2 threads nsplugin sse3 llvm vaapi vdpau dga win32codecs bash-completion pulseaudio avahi xattr zsh-completion gtk3 -cups alsa infinality"

昔よりだいぶコンパクトになりました。最近はUSEフラグは手動でいじるのではなく、"flaggie"というツールを使うことにしています。

たとえば、 media-libs/freetypeでUSE='infinality'したいなーと思ったら

# flaggie media-libs/freetype +infinality

と、することで、いちいち/etc/portage/package.useを開かなくてもコマンド一つで編集できます。もし typoしちゃっても

# flaggie media-libs/freetype +infinity
At argv[2]='+infinity': infinity seems to be an incorrect flag for media-libs/freetype

と聞いてくれるので安心です。パッケージごとではなく、グローバルに変えたい時には

# flaggie +cjk
# flaggie -cjk

のようにすればOKです。

FEATURES
FEATURES='-stricter parallel-install parallel-fetch preserve-libs'

portageのさまざまな機能をON/OFFするFEATUESです。開発者用のプロファイルでデフォルトになってる "stricter"を切ってます。これがあるといろんなものがemerge通らなくなるのでね orz

FEATURES='parallel-install'を使うことで、より細かいロックを使うことで、インストールをいままでよりも並列度を上げて実行しています。

そして、 FEATURES='preserved-libs' これはなかなか大事な機能。

まずはこの機能が動いてない時の話をします。

libBを使っているpkgAをemergeします。すると

pkgA-0.1 -> libB-0.1

こんなふうに、AからBへの実行時リンクが"libB-0.1"という名前で行なわれます。ここで、libBがアップデートされます。 emergeはlibB-0.2をインストールし、libB-0.1が削除されます。

pkgA-0.1 -> (libB-0.1)
             libB-0.2

すると、pkgAは実行時リンクするべき"libB-0.1"が見つからないので、実行できなくなります。解決するには、再度pkgAをemergeして、pkgAのリンクをlibB-0.2へと張りかえなければいけません。

こういった、「リンクが壊れたパッケージ」を捜し出してリビルドするツールが "revdep-rebuild"でした。しかし、このプログラムは確かに便利で確実ではあるものの、システムの全バイナリをスキャンするために遅いという問題点がありました。

また、ebuildではpreserve_old_libを呼び出して、残しておくべきライブラリを指定すると、昔のライブラリをコピーして残しておいてくれました。昔のライブラリが残っていれば、コマンドはいままで通りに動きます。あとは適宜revdep-ebuildではりかえるだけです。しかし、残ったライブラリは、リンクをはりかえた後にユーザが手動で削除する必要があり、忘れさられることがありました。

さて、そこでこんな仕事はportageに自動的にやらせればいい、ということになります。 FEATURES='preserved-libs' しておくことで

  • 過去のライブラリを残しておく
  • 新しいライブラリにはりかえるべきパッケージを認識する
  • それらをemerge @preserved-rebuildでリビルドする
  • リビルドが完了した時点で、過去のライブラリを削除する

といったことができるようになります。

この preserved-libsの機能はだいぶ前から portage-2.2系列には入っていたものの、portage-2.1系列には入っていませんでした。しかし、EAPI=5の変更の影響もあって、portage-2.1にもコードが入ることとなりました。とはいえ、デフォルトでは無効になっていますから、 FEATURES='preserved-libs' が必要になる、というわけです。

Rubyのこと
RUBY_TARGETS="ruby19"

rubyのパッケージでターゲットにしたい、rubyのvariantを列挙します。 いまのところ

  • ruby18
  • ruby19
  • ree18
  • jruby
  • rbx

が使えるみたいですね。

ちなみにいまでは ruby-1.9がデフォルトになっています。 Project:Ruby/Ruby 1.9 migration - Gentoo Wiki

起動あたりのこと
DRACUT_MODULES="btrfs syslog ssh"
GRUB_PLATFORMS="efi-64

もうすっかりGRUB2とinitrdを使っています。initrdは/usrが/と別パーティションであれば、必須です。udevが/usrがmountされてないと動かなくなっちゃったんですよねえ。

で、initrd作りには distro-neutralなinitrdを作ってくれるツールのdracutを使っています。上の DRACUT_MODULES はdracutのUSEフラグですね。

そして、下の方はGRUB2のUSEフラグ。 efi bootしています。

dracutの使い方は簡単で

# dracut /boot/initrd-<kernel version> <kernel version> --force

こんな感じ。 dracutは上書きをしてくれないので、--forceをつけていますが、そこはお好みで。

そして、grub2は

# grub2-mkconfig -o /boot/grub2/grub.cfg

とかしていると、インストールされているカーネルを見つけだしてgrub.cfgを勝手に作ってくれますね。便利なもんです。

このへんをカーネルをインストールするごとにやれば、いいわけですがまあめんどいですしうっかり忘れそうですよね。そこで、/root/bin/installkernel というファイルを使います。ここにスクリプトをおいておけば、カーネルでの make instalがこいつを実行してくれます。うちでは

#!/bin/bash

make modules_install # モジュールインストールする

/sbin/installkernel "$@" # カーネルインストールする

# initramfsの作成
[ -f /boot/initramfs-$1.img ] && mv /boot/initramfs-$1.img /boot/initramfs-$1.old.img
dracut /boot/initramfs-$1.img $1
ln -sf initramfs-$1.img /boot/initramfs.img

# Grubのメニュー更新
grub2-mkconfig -o /boot/grub2/grub.cfg       

こんな感じで実行しています。これで、一通りのカーネル更新時の作業が全て実行されます。

EAPI=5

最初に書いた通りこの記事は「新時代Gentooの福音的」ってことで、新しく採択されたEAPI=5についても書いていきます。 EAPIはebuild全体の書式とかを統括してるAPIですね。新しくなるとなにがいいの? 新しい革新的な機能がふえます。

Sub-SLOT

Sub-SLOTがユーザから見ると一番大きな変更となります。これは上でも書いた revdep-rebuild, preserved-libs の進化系です。 preserved-libs は確かにライブラリに起因するリビルドを楽にしてくれます。しかし、

  • emerge @preserved-rebuild が必要である
  • ライブラリに起因する問題しか解決できない

この2つの問題があります。1つ目は解説しなくてもわかるでしょうが、2つ目はどういうことでしょうか。 たとえば、現状、GentooではPerlの本体が更新された時に perl-cleanerコマンドを使って全てのperlのパッケージを新しいバージョンのものへリビルドしています。emergeでperlが更新されてから、perl-cleanerを実行するまでの間はperlのプログラムがうまく動かなかったりしますし、さらにはいっぱい更新した時なんかはうっかりperl-cleanerの実行を忘れているかもしれません。

そこで、Sub-SLOTというものが導入されます。SLOTは「同一パッケージでSLOTが異なるものを共存させる」ための仕組みですが、Sub-SLOTは「同一SLOTでAPIの変更(など)を指定する」ための仕組みです。たとえばdev-lang/perl-5.16.1でこれを使うなら

SLOT="0/${PV}"

のように書きます。一方で、perlのパッケージは

RDEPEND="dev-lang/perl:="
DEPEND="${RDEPEND}"

のように、":="をつけておきます。これをつけると、emergeした時に、その時のdev-lang/perlのSub-SLOTへの依存が記録されます。すなわち、ここでは "dev-lang/perl:0/5.16.1=" というように記録されます。

さて、この後perl本体が更新され、"dev-lang/perl-5.16.2"がemergeされる、とします。この時、package managerはさきほどの "dev-lang/perl:0/5.16.1=" をチェックし、「dev-lang/perl-5.16.2をインストールすることで、この依存関係が壊れること」を認識します。すると、package managerは依存が壊れるものをリビルドする形で解決しようとします。これによって、いままで python-udater, perl-cleaner, haskell-updater, revdep-rebuildなどなど、壊れた依存を直すためのコマンドの役割が全てemergeに吸収され、emergeだけでなにもかもすむようになります。(実際のところは、haskell-updaterは結構使いますが…haskellの依存はいろいろ特殊…)

ということで、このSub-SLOTですがまだまだportageのメインツリーにはそこまで入ってきていません。gentoo-hasekllのツリーでは積極的にとりいれていて、新しいものはどんどんと":=" を使ったものに書きかわっているようです。

その他?

他にもebuildを書く側としては newhogeが標準入力を使えるようになったり、use.stable.maskというstableな時だけmaskされるUSEを指定したりと便利なものは入っているのだけれど、これは開発者むけだからね…。ユーザ向けには結局、Sub-SLOTだけかも。

ネットワークのこと

wicdがコマンドから使えるし、いいよねー?とか思ってたけど、最近はGentooサポートらしきものもnetworkmanagerに入ったようなので、NetworkManagerを(ノートPCでは)使っています。

そして、NetworkManagerのコマンドラインツール nmcliがあるのでこれでつないだりする。

# nmcli dev wifi connect <SSID> password <password>

依存衝突のこと

emergeするとこんなのが出てくる日もある

WARNING: One or more updates have been skipped due to a dependency conflict:

net-misc/curl:0

  (net-misc/curl-7.28.0-r1::gentoo, ebuild scheduled for merge) conflicts with
    <net-misc/curl-7.27.0 required by (dev-cpp/libcmis-0.1.0-r1::gentoo, installed)

これは

  • net-misc/curl-7.28.0-r1::gentoo を emergeしたい (ebuild scheduled for merge)
  • けど、 インストールしてある "dev-cpp/libcmis-0.1.0-r1::gentoo"が "

から、無理だよーってことを言ってる。

libcmisなんてこころあたりがないので、これがどのパッケージから呼ばれているのかを検索かけます。

# equery d libcmis
 * These packages depend on libcmis:
app-office/libreoffice-bin-3.5.5.3 (=dev-cpp/libcmis-0.1*)
                                   (<dev-cpp/libcmis-0.2)

というわけで、libreoffice-binのせいでした。 libreofficeにしたらいいのかもしれないけれども、めんどいのでこのconflictは放置、といったところですかね。

別のケース

dev-haskell/authenticate:0

  (dev-haskell/authenticate-1.3.1.2::gentoo-haskell, installed) pulled in by
    =dev-haskell/authenticate-1.3*:0/1.3.1.2= required by (dev-haskell/yesod-auth-1.1.1.4::gentoo-haskell, installed)

  (dev-haskell/authenticate-1.3.2::gentoo-haskell, ebuild scheduled for merge) pulled in by
    (no parents that aren't satisfied by other packages in this slot)
  • インストールされているyesod-authが "=dev-haskell/authenticate-1.3*:0/1.3.1.2="に依存
  • でも、dev-haskell/authenticate-1.3.2が更新でインストールされようとしている

これは上のSub-SLOTの例でpackage managerが自動的にyesod-authのrebuildをかけてくれるべきなんだけれど、推測に失敗している。

なので、手動で

emerge -1 authenticate yesod-auth

としてやると解決

依存のコンフリクトは結構迷うところなのでこれからも随時blogに書いていきたいところ。ただ、基本的なパターンは上の2つだと思う。

つまり

  • 心当たりがないなら、equeryを使ってどのパッケージがひっぱってきているかつきとめる
  • 仕方ないならあきらめる
  • とりあえずコンフリクトの登場人物を emerge -1 に渡してみる