試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

x86_64版Gentoo Linuxの32bitライブラリを自前で管理(概要と、ビルド方法について)

Gentoo Linuxでは、「emul-linux-x86-*」パッケージにより、x86_64環境においても、事情により64bit版として動作させられないプログラム*1を実行することができるのだが、最近このバージョンがJavaのランタイムを除き、あまり更新されていない。
(2007/11/16)最近新しいバージョンが入った。少しだけ変わった新しいインストールシステムになり、自前管理もしやすくなった。→「新しいemul-linux-x86-*パッケージと、これを利用した32bitライブラリの自前管理について


最近ビルドしたWineは、挙動が変なところがあり、32bitライブラリのバージョンを64bit側に合わせたところ、改善されたものがある。*2ビルド時に参照するヘッダファイルが64bit側のものなので、これと大きく離れたバージョンの32bitライブラリを使用するのは良くないということになる。
自分でパッケージをビルドしてインストールできれば、このような問題に対処できるだけでなく、ビルド時に最適化もできるし、インストールする項目を多少調整することも簡単にできる(例: 32bitでのGTK+のテーマエンジンを追加)。インストールするバージョンが細かく選択できるのも便利(例: ALSAのライブラリだけ最新版にして、他のサウンド関連のライブラリは安定版のまま)。
これ以外にも、freetypeライブラリのように、実行形式(バイナリ)として配布されているものに制約がある場合でも、ソースからビルドすることで、その制約を回避できるし、他には、binutils 2.18から使用できるhashstyleをいち早く導入できるというメリットもある。
デメリットは、手間と時間がかかることと、その割に得られるものが大きいのかが怪しいこと。ただ、Wineを使用しているのであれば、不具合が改善されることがあるため、やってみる価値はあると思う。

  1. 大まかな流れ
  2. 「CHOST=i686-pc-linux-gnu」「ABI=x86」の動作原理と注意点
    1. ライブラリパスの誤検出とlibtool
  3. emul-chrootの概要

大まかな流れ

これを行う方法は何通りか考えられるのだが、最も手っ取り早いのは

  1. 32bitビルドしたtbz2パッケージファイルを作成
  2. 既存の「emul-linux-x86-*」パッケージのebuildをベースにして、構成するパッケージ名とバージョンの部分を編集、そのカスタムebuildをローカルOverlayへ入れる
  3. tbz2ファイルをdistfilesのディレクトリへ入れて、カスタムパッケージをインストール

という流れ。
一番の問題は、32bit向けのtbz2パッケージを用意するところで、

  • として、emulパッケージビルド用のchrootを用意して、その中で普通にパッケージをビルドし、tbz2ファイルを作成
  • chrootを使用せず、「CHOST=i686-pc-linux-gnu」と「ABI=x86」を付けて、emerge -Bでパッケージ作成
  • 公式の「emul-linux-x86-*」パッケージの中に含まれるバージョンのtbz2ファイルをそのまま使用(自分が滅多に使いそうにないものに対しては効果的)

のいずれかで用意することになる。
chrootを使用する場合、amd64のstage2を使用して、プロファイルには/usr/portage/profiles/default-linux/amd64/dev/32bit-userland/を使用する。詳細は
http://www.gentoo.org/proj/en/base/amd64/emul/index.xml
を参照。
emul用chrootよりも、x86-chrootでビルドするほうが手間もかからず、より確実な気もするのだが、詳しいこと(emul用chroot上でビルドされたものととx86-chroot上でビルドされたものの違い)はよく分からない(更に言うと、「CHOST=i686-pc-linux-gnu」と「ABI=x86」だけでビルドが通ったものではダメなのかすら分からない)。
(2007/10/8)ライブラリのディレクトリ名が違うというのはある。x86-chrootでは、「32」の付かない/libのような名前になっているのに対し、emul用chrootは、x86_64環境と同様、/lib32のような「32」付きの名前となる。
(2007/11/13)上の追記にも書いたように、x86-chrootを使用すると「/lib」「/usr/lib」などに入る形でconfigureやビルドがされるため、問題がある。「CHOST=i686-pc-linux-gnu」と「ABI=x86」(QT4など、必要に応じてlinux32も必要)でパッケージを作る分には問題ないと思われるが、GLib 2、GTK+ 2、D-BUSなどを使用するパッケージにおいて、32bit版固有のヘッダファイル(/usr/lib32/以下に配置されるヘッダファイル)が使用されるようにしなくてはならず、64bit環境上でビルドする際にはその点に注意が必要。emul用chrootは、一度作ってしまえば、そのあたりのことや、ビルド時の色々な修正などを行ったりすることなく、普通にビルドしていけるので好ましい、ということになる。

[引用]ファイル名: /usr/portage/profiles/default-linux/amd64/dev/32bit-userland/make.defaults より

FEATURES="multilib-strict"
MULTILIB_STRICT_DIRS="/lib32 /lib /usr/lib32 /usr/lib /usr/kde/*/lib32 /usr/kde/*/lib /usr/qt/*/lib32 /usr/qt/*/lib /usr/X11R6/lib32 /usr/X11R6/lib"
MULTILIB_STRICT_DENY="64-bit.*shared object"

CHOSTやABI以外では、この辺りが重要なのかもしれないが、詳しい情報は見付けられない。
関連している可能性があるのは
http://archives.gentoo.org/gentoo-dev/msg_142909.xml
ぐらい。

「CHOST=i686-pc-linux-gnu」「ABI=x86」の動作原理と注意点

# FEATURES="noman noinfo" CHOST=i686-pc-linux-gnu ABI=x86 PKGDIR=[出力先] emerge -avB [パッケージ名]
$ sudo bash -c 'FEATURES="noman noinfo" CHOST=i686-pc-linux-gnu ABI=x86 PKGDIR=[出力先] emerge -avB [パッケージ名]'

の形では、64bit版GCCが使用され、-m32で実行したのと同様に処理され、リンク時には32bit版ライブラリが使用され、32bitバイナリとなる。ヘッダファイルに関しては、/usr/include/以下が使用される。Wineをビルドする際にも、これと同様の原理で32bitの実行ファイルとライブラリが生成される。

注意点として、「emul-linux-x86-*」パッケージに含まれないライブラリに依存するようなUSEフラグを有効にしないようにする。それが使用したい機能の場合は、依存するライブラリ側も別途32bitのライブラリとして用意する必要がある。USEフラグでも外せないものが出たらebuildに手を加えるしかない。

ライブラリパスの誤検出とlibtool
ビルドするパッケージ自体、他のパッケージに依存しないものであれば問題はないのだが、別のライブラリに依存するパッケージをビルドする際、リンク時のコマンドライン/usr/lib64/lib[名前].soというファイル名が突然現れることがあり、これに対してリンクを試みるため、形式が合わないとエラーになる。下は、openMotifの例。

/bin/sh ../../libtool --mode=link x86_64-pc-linux-gnu-gcc  [CFLAGS] -I/usr/include/gentoo-multilib/x86 -fno-strict-aliasing -Wall -Wno-unused -Wno-comment  -version-info 3:2:0 -o libXm.la -rpath /usr/lib32  XmStrDefs.lo (中略) ComboBox2.lo -L/usr/lib64 -lXmu -lXt -lSM -lICE -lXext -lXp -lX11  
x86_64-pc-linux-gnu-gcc -shared  .libs/XmStrDefs.o (中略) .libs/ComboBox2.o  -L/usr/lib64 /usr/lib64/libXmu.so /usr/lib64/libXt.so /usr/lib64/libSM.so /usr/lib64/libICE.so /usr/lib64/libXext.so /usr/lib64/libXp.so /usr/lib64/libX11.so [CFLAGS] -Wl,-soname -Wl,libXm.so.3 -o .libs/libXm.so.3.0.2
/usr/lib64/libXmu.so: could not read symbols: File in wrong format
collect2: ld returned 1 exit status
make[3]: *** [libXm.la] Error 1
make[3]: Leaving directory `/var/tmp/portage/x11-libs/openmotif-2.2.3-r9/work/openMotif-2.2.3/lib/Xm'

これは、configureスクリプトで(誤)検出された/usr/lib64などのディレクトリ名が、スクリプトの実行後に生成されるMakefileの中に含まれ、それを(上の例では)libtool

-L/usr/lib64 -lXmu -lXt -lSM -lICE -lXext -lXp -lX11

として渡された部分を

-L/usr/lib64 /usr/lib64/libXmu.so /usr/lib64/libXt.so /usr/lib64/libSM.so /usr/lib64/libICE.so /usr/lib64/libXext.so /usr/lib64/libXp.so /usr/lib64/libX11.so

としてリンカに渡してしまい、エラーを引き起こすような感じになっている。
対処法としては、configureスクリプトの実行後に全てのMakefileに対して

sed -i -e 's/lib64/lib32/g' Makefile

をすればよい(それだけではダメな場合もある)のだが、Makefile生成後、すぐにmakeが実行されてしまう*3ため、タイミングが難しく、ebuildファイルに直接手を加えてからdigestを取り直し、ビルドするのが楽?

emul-chrootの概要

amd64のstage2をベースにするのだが、設定後emerge -e worldが進むにつれて、64bit版のパッケージが32bit版のものに少しずつ置き換わっていく。しかし、実際にやってみると、なかなかうまくいかなかったりする。

*1:x86_64版としてビルドできないもの、32bit版でないと動作が安定しないもの、オープンソースでない32bitアプリなど

*2:emul-linux-x86-xlibsを64bitのバージョンへ合わせたところ、最近起動しなかったTMIDI Playerが動作するようになったなど

*3:更に、ebuild中で、両方とも「src_compile()」の中で続けて実行される形なので、分離するのは無理