2009年2月21日土曜日

(Solaris10,pkgsrc) lddしたら、libz.so.1 (SUNW_1.1) => (version not found) とか libgcc_s.so.1 (GCC_3.4) => (version not found) とか出た

いきなり無駄話から。



10数年前くらい前は、ソフトウェアをインストールするときは、自分でMakefileを書き換えたり、config.hとかいうファイルを書き換えたりして、makeして、エラーがでたらソースを直したり、インストールするには、手でファイルをコピーしたり・・・そんな感じ。



だんだんとautoconfが使われるようになってくると、「configure; make ; make install」の3つのコマンドだけで、インストールできるようになりました。これはすごい便利だ!と感動ものでした。



ただ、make installはあっても、make uninstallのようなものはなくって、アンインストールしたい、とか、バージョンアップしたい、とかいうときは、それはそれで面倒なことになります。



ちょうどそのころPC UnixとかLinuxが台頭してきましたが、「ソースからコンパイルするなんてめんどくさい。バイナリファイルをコピーするだけですむ、バイナリパッケージでいいんじゃね」的なスタイルも増えていきました。まだまだCPUパワーが低かったので、「make world」を実行すると、本当に1週間かけて「天地創造」しちゃう・・・という理由もあったかと思います。



FreeBSDでもバイナリパッケージはありますが、そのバイナリパッケージを作る仕組みとして「ports」があります。これは、ソフトウェアをインストールするための手順を記述したMakefileと、インストールすべきファイルの一覧リスト、必要に応じていくつかのpatchファイルなどから構成されています。makeと実行するだけで、自動的にソースコードをダウンロードして、自動的にソースコードからコンパイルしてくれます。しかも、コンパイルするときに、いろんなカスタマイズができるので、おまかせのバイナリ・パッケージでは不可能な、自由度の高さ、これが私のお気に入りなのです。



パッケージ管理の仕組みに頼らずに、自分でコンパイルしてインストールする、いわゆる「野良ビルド」がよくないのは、アンインストールやバージョンアップが簡単にはできない、っていう理由もありますし、インストールした人じゃないと、どういう設定でインストールしたのかがわからないので(メモが残してあったとしても、本当にそのメモが正しいとは限らなかったり)、管理者が変わると、もうわけわかんねぇ無秩序な状況に陥ってしまうことだと思います。
たった一人で使っているマシンなら、その人が責任をとればいいだけですけどね。
でも、FreeBSDのportsは異様に充実してて、私の場合、インストールしようと思うソフトは、ほぼすべてportsに入ってます。だから野良ビルドは、ほとんど無いです(fvwmとxemacsだけかな)。
「googleで見つからないウェブページは、存在しないのと同じ」と言われることがありましたが、それと同様に、「portsに入ってないソフトウェアは、存在しないのと同じ」と言ってもいいかもしれない、と思ってます。



FreeBSDのportsとよく似た仕組みが、NetBSDではpkgsrc(ぱっけーじ・そーす、って言うのかな?)という名前で用意されています。てゆーか移植版?
pkgsrcのすごいところは、NetBSD専用というわけではなくて、Solaris、Linux、FreeBSDなど、さまざまなプラットフォームに対応しているところ。残念ながら、私の周りには、NetBSDは無いのですが・・・。



Solaris、Linux、FreeBSDさまざまなマシンが混在する環境で、まったく同じソフトウェアをインストールすることができるので、プラットフォームの違いを極力感じさせない、使い勝手のよい計算機環境を提供できます。
あと、pkgsrcって、管理者権限がなくても、一般ユーザーで利用することができます。デフォルトでは、/varとか/usrとか、一般ユーザーでは書けないディレクトリにファイルを置いてしまいますが、最初のインストール時に、どのディレクトリにファイルを置くか指定できるようになってます。



というわけで、pkgsrcもお気に入りなんですが、マルチ・プラットフォーム対応!と大風呂敷を広げているせいか、やっぱり細かいところで漏れはあるみたいで、たとえばSolarisで使っていると、たびたびよくわかんないエラーがでることもあったり。



あ、そうそう、FreeBSDで、portsとpkgsrcの両方を使うことも、不可能ではないのですが、たまにトラブルが起きます。同じディレクトリ名を使っていたり、同じコマンド名があったり、似たような名前の共有ライブラリがありますので。mk.confや環境変数を工夫することで、だいたいなんとかなるんですが。
これまで困ったのは、portsとpkgsrcの両方でphpをインストールしてあるとき、portsでphpをビルドしようとすると、configureスクリプトが、pkgsrcで/usr/pkg以下にインストールしてあるファイルを先に見つけてしまう、ってことがありました。「mv /usr/pkg /usr/pkg-」とかやって、毎回、お茶を濁しています。





以前、SPARCなSolaris10で、pkgsrcを使っていろいろソフトをインストールしてあったんですが、インストールしたまんま放置してたので、先日、ひさびさにアップデートしておこう、という気分になりました。



そしたら、あちこちで、共有ライブラリが見つからなくてビルドに失敗。



lddで見ると(一部のみ抜粋)、

libgcc_s.so.1 =>         /usr/pkg/gcc3/lib/libgcc_s.so.1
libgcc_s.so.1 (GCC_3.4) =>       (version not found)
libz.so.1 =>     /usr/pkg/lib/libz.so.1
libz.so.1 (SUNW_1.1) =>  (version not found)

という感じの、おかしな状況が発生してました。





まずはzlibの問題について。



これ、どうやら、もともとOSの一部として存在していた/usr/lib/libz.soと、pkgsrcでインストールした/usr/pkg/lib/libz.soの、両方が混在して使われてしまっているらしいです。



たぶん、pkgsrcでインストールするソフトは、常に/usr/pkg/lib/libz.soを使ってくれればいいはずなので、それってどうやるんだろう?と思い、デバッグオプションを指定してbmakeしたり、pkgsrc/mk/以下のファイルをgrepして眺めてみたりしていて、ようやく発見しました。



/etc/mk.confに

PREFER.zlib = pkgsrc

と書いておけばよいみたいです。



この設定をしてから、zlibを利用しているソフトを再ビルドして、とりあえず解決。



ところで、pkgsrcの仕組みって、とっても変わっています。ビルド中には、作業ディレクトリの下に、
work/graphics/freetype2/work/.buildlink/lib/
といったディレクトリが作られて、このディレクトリ内に、各種共有ライブラリへのシンボリックリンクが張られて、このディレクトリを指定してリンクしてます。
PREFER.zlib = pkgsrc を書くと、.buildlink以下に、libz.so*へのシンボリックリンクが作られるようになりました。
コンパイル中に実行する各種コマンドも、/usr/pkg/bin/や/usr/bin/以下のコマンドが実行されるのではなくて、ラッパースクリプトがwork以下に作られて、ラッパースクリプトを実行するようになっています。
こうやって、プラットフォームの違いを吸収してるんですね。感心しました。





つぎにlibgcc_s.so.1の問題。



こっちは難しかった。あれこれ再ビルドしても、どうしても

libgcc_s.so.1 (GCC_3.4) =>       (version not found)

が出るんです。gcc34の再ビルドまでして、試行錯誤していくうちに、lddの表示が変化しました。

libgcc_s.so.1 =>         /usr/pkg/lib/libgcc_s.so.1
libgcc_s.so.1 =>         /usr/pkg/gcc34/lib/libgcc_s.so.1

おぉっ! なんか、2つ混じってる。



/usr/pkg/lib/libgcc_s.so.1 の方は、タイムスタンプがけっこう古くて、昔インストールしたgccの残骸ファイルみたいでした。というわけで、こっちを削除。



あとは、いくつか再ビルドして、やっとこさ問題解決できました。





自分でももう忘れていたんですが、昔書き残しておいた



(Solaris10) gcc -std=c99のとき、Undefined symbol __builtin_isnan となってエラー



の中に、

pkgsrcで、lang/gcc34が、すんなりとはビルドできなかった

という記述があって、そのときもzlibでトラブルがおきてました。
「-lz」で指定すると、64bitバイナリのビルド中に、32bitバイナリなlibzをひっぱってきてしまう、というのがトラブルの原因です。



当時は気がつかなかったことに、今回、気がつきました。



ビルド中の作業ディレクトリの中を眺めていたら、その中に、gcc34が自前で用意しているらしいzlibがありました。ただ、名前が微妙に変更されています。こんな感じ。



lang/gcc34/work/obj/sparc-sun-solaris2.10/sparcv9/zlib/libzgcj_convenience.la



というわけで、「-lz」の代わりに、libzgcj_convenience.laを使ってやればいいんじゃね?ということ。



エラーが出るのは、libjavaを作ってる途中なんですが、



lang/gcc34/work/obj/sparc-sun-solaris2.10/sparcv9/libjava/Makefile



の中で

SYS_ZLIBS = -lz

となっているところを

SYS_ZLIBS = ../zlib/libzgcj_convenience.la

に変更すれば、うまいことビルドできました。



いや、途中、attempted multiple inclusion of fileというwarningが、何度も出てましたが、見なかったことにしておきます。



それと、Makefileを書き換えても、32bit版のほうが再ビルドされなかったので、手でファイルを削除して、強制的に作り直させました。





そんなに苦労するんだったら、素直にバイナリパッケージを使えばいいのに、って思う人もいるんだろうなぁ・・・



0 件のコメント:

コメントを投稿