2009年1月21日水曜日

(FreeBSD) ports/math/Rをportupgrade中に、/usr/local/lib/libblas.so.2: undefined reference to `_gfortran_runtime_error_at'

ports関連のトラブルで、もうひとつ。



portsの、math/Rを、portupgradeでR-2.8.1にアップグレードしてる最中に出たエラーです。



cc -std=gnu99 -export-dynamic -L/usr/local/lib -o R.bin Rmain.o -L../../lib -lR
/usr/local/lib/libblas.so.2: undefined reference to `_gfortran_runtime_error_at'
*** Error code 1



Stop in /WORK/FreeBSD/ports/math/R/work/R-2.8.1/src/main.
*** Error code 1



どこからlibblasが呼ばれるんだ?という感じがしますが、-lRで指定されている、libRがlibblasに依存しているのでした。



でも、なんかよくわかんない・・・3分後、やっと気がつきました。



「-L../../lib -lR」なので、「../../lib/libR.so」がリンクされるんだろうと思ってたら、実は、その手前にある「-L/usr/local/lib」のせいで、「/usr/local/lib/libR.so」が使われてしまうのでした。そっちは、既存のRによってインストールされたもので、ということは旧バージョンなので使っちゃダメです。



% ls -l /usr/local/lib/R/lib/libR.so*
-rwxr-xr-x  1 root  wheel  2368863 12 15 13:34 /usr/local/lib/R/lib/libR.so*
lrwxr-xr-x  1 root  wheel       24 12 15 13:35 /usr/local/lib/libR.so@ -> /usr/local/lib/libR.so.0
-rwxr-xr-x  1 root  wheel  2368863 12 15 13:34 /usr/local/lib/libR.so.0*



う~ん、-Lオプションって、そういう挙動をするものでしたっけ?そうだったような気もします。



こういうのは、とてもわかりにくいので、自分でもミスしそうです。



ccの引数を「../../lib/libR.so」にすればいいのかな?とも思ったのですが、Makefileのどこが該当するのか探すのがめんどくさかったので、「今だけ通して!」ってことで



mv /usr/local/lib/libR.so /usr/local/lib/libR.so-



しちゃいました。可能なら、既存のRをアンインストールしちゃってもいいのかもしれません。





それとは別に、もうひとつ、嫌なものを見てしまいました。



% ldd ../../lib/libR.so
../../lib/libR.so:
        libblas.so.2 => /usr/local/lib/libblas.so.2 (0x483a4000)
        libgfortran.so.3 => /usr/local/lib/compat/pkg/libgfortran.so.3 (0x483f0000)
        libm.so.4 => /lib/libm.so.4 (0x48495000)
        libintl.so.8 => /usr/local/lib/libintl.so.8 (0x484ab000)
        libiconv.so.3 => /usr/local/lib/libiconv.so.3 (0x484b4000)
        libreadline.so.6 => /lib/libreadline.so.6 (0x485aa000)
        libpcre.so.0 => /usr/local/lib/libpcre.so.0 (0x485da000)
        libbz2.so.2 => /usr/lib/libbz2.so.2 (0x48609000)
        libz.so.3 => /lib/libz.so.3 (0x4861a000)
        libgcc_s.so.1 => /usr/local/lib/gcc-4.2.5/libgcc_s.so.1 (0x4862b000)
        libncurses.so.6 => /lib/libncurses.so.6 (0x48635000)
        libc.so.6 => /lib/libc.so.6 (0x48086000)



ちょっとまってよ。どうして
/usr/local/lib/compat/pkg/libgfortran.so.3
と、compatの下の方を見に行っちゃってるのですか? ・・・と。



こっちは?



% ldd /usr/local/lib/libR.so.0
/usr/local/lib/libR.so.0:
        libblas.so.2 => /usr/local/lib/libblas.so.2 (0x483a5000)
        libgfortran.so.2 => /usr/local/lib/gcc-4.2.5/libgfortran.so.2 (0x483f1000)
        libm.so.4 => /lib/libm.so.4 (0x48482000)
        libintl.so.8 => /usr/local/lib/libintl.so.8 (0x48498000)
        libiconv.so.3 => /usr/local/lib/libiconv.so.3 (0x484a1000)
        libreadline.so.6 => /lib/libreadline.so.6 (0x48597000)
        libpcre.so.0 => /usr/local/lib/libpcre.so.0 (0x485c7000)
        libbz2.so.2 => /usr/lib/libbz2.so.2 (0x485f6000)
        libz.so.3 => /lib/libz.so.3 (0x48607000)
        libgcc_s.so.1 => /usr/local/lib/gcc-4.2.5/libgcc_s.so.1 (0x48618000)
        libncurses.so.6 => /lib/libncurses.so.6 (0x48622000)
        libc.so.6 => /lib/libc.so.6 (0x48086000)



わけわからん・・・えーと、こっちはgcc42が使われてたころの名残りですね。



で、新たにgcc43でビルドしたほうは、lib/compat/pkg/libgfortran.so.3を見てて、って、なんで、/usr/local/lib/gcc-4.3.3/の下の方を見てくれないの???



えーと、2つ、同じ名前のライブラリがありますね・・・やばい雰囲気。



% ls -l /usr/local/lib/gcc-4.3.3/libgfortran.so.3 /usr/local/lib/compat/pkg/libgfortran.so.3
-rwxr-xr-x  1 root  wheel  2297336  1  8 10:56 /usr/local/lib/compat/pkg/libgfortran.so.3*
-rwxr-xr-x  1 root  wheel  2297336  1 13 11:13 /usr/local/lib/gcc-4.3.3/libgfortran.so.3*


どっちを先に見るのかな?



% ldconfig -r | head
/var/run/ld-elf.so.hints:
        search directories: /lib:/usr/lib:/usr/lib/compat:/usr/local/lib:/usr/local/lib/compat:/usr/local/lib/compat/pkg:/usr/local/lib/evolution/2.22:/usr/local/lib/gcc-4.2.5:/usr/local/lib/gegl-0.0:/usr/local/lib/graphviz:/usr/local/lib/kde3:/usr/local/lib/mysql:/usr/local/lib/nss:/usr/local/lib/pth:/usr/local/lib/qt4:/usr/local/lib/wine:/usr/local/lib/zsh:/usr/local/libexec/openldap:/usr/local/sge/lib/fbsd-i386:/usr/local/lib/evolution/2.24
        0:-lkvm.3 => /lib/libkvm.so.3
        1:-lm.4 => /lib/libm.so.4
        2:-lmd.3 => /lib/libmd.so.3
        3:-lncurses.6 => /lib/libncurses.so.6
        4:-lncursesw.6 => /lib/libncursesw.so.6
        5:-lsbuf.3 => /lib/libsbuf.so.3
        6:-lutil.5 => /lib/libutil.so.5
        7:-lalias.5 => /lib/libalias.so.5



/usr/local/lib/compat/pkgの方が先ですね。だめじゃん。



どうして、libgfortran.so.3が2つあるのかな。



compat/pkg/の下のは、たぶん消しちゃってもいいんでしょう。



結局、こういう感じになりました。



% ldd /usr/local/lib/libR.so.0
/usr/local/lib/libR.so.0:
        libblas.so.2 => /usr/local/lib/libblas.so.2 (0x483a4000)
        libgfortran.so.3 => /usr/local/lib/gcc-4.3.3/libgfortran.so.3 (0x483f0000)
        libm.so.4 => /lib/libm.so.4 (0x48495000)
        libintl.so.8 => /usr/local/lib/libintl.so.8 (0x484ab000)
        libiconv.so.3 => /usr/local/lib/libiconv.so.3 (0x484b4000)
        libreadline.so.6 => /lib/libreadline.so.6 (0x485aa000)
        libpcre.so.0 => /usr/local/lib/libpcre.so.0 (0x485da000)
        libbz2.so.2 => /usr/lib/libbz2.so.2 (0x48609000)
        libz.so.3 => /lib/libz.so.3 (0x4861a000)
        libgcc_s.so.1 => /usr/local/lib/gcc-4.2.5/libgcc_s.so.1 (0x4862b000)
        libncurses.so.6 => /lib/libncurses.so.6 (0x48635000)
        libc.so.6 => /lib/libc.so.6 (0x48086000)





ldconfigでどのディレクトリが参照されるのかは、以下のあたりを見ると、なるほどね、と気がつくと思います。



(1) /etc/rc.d/ldconfig



(2) /etc/defaults/rc.conf にある
ldconfig_local_dirs="/usr/local/libdata/ldconfig /usr/X11R6/libdata/ldconfig"



(3) そして
% cat /usr/local/libdata/ldconfig/gcc43
/usr/local/lib/gcc-4.3.3




同じ名前のライブラリが複数個あるのは、トラブルの元なので、望ましくない状況です。



たしかそういう状況をチェックできるコマンドがあったはずだ!



う~ん、思い出せない。



libchkは、ちょっと違うな。



3分経過。



そうだ、portsclean -L だ。



なんていう思い出しにくいコマンドだ・・・



portsclean -Lを実行すると、こんな感じで、同名の共有ライブラリを見つけ出して、片方を削除してくれます。



** /usr/local/lib/gcc-4.3.3/libmudflap.so.0 is shadowed by /usr/local/lib/gcc-4.2.5/libmudflap.so.0
        /usr/local/lib/gcc-4.2.5/libmudflap.so.0        <- gcc-4.2.5_20081126
        /usr/local/lib/gcc-4.3.3/libmudflap.so.0        <- gcc-4.3.3_20090108
--> Two packages install the same library in different directories!



** /usr/local/lib/gcc-4.3.3/libmudflapth.so.0 is shadowed by /usr/local/lib/gcc-4.2.5/libmudflapth.so.0
        /usr/local/lib/gcc-4.2.5/libmudflapth.so.0      <- gcc-4.2.5_20081126
        /usr/local/lib/gcc-4.3.3/libmudflapth.so.0      <- gcc-4.3.3_20090108
--> Two packages install the same library in different directories!



** /usr/local/lib/gcc-4.3.3/libffi.so.4 is shadowed by /usr/local/lib/gcc-4.2.5/libffi.so.4
        /usr/local/lib/gcc-4.2.5/libffi.so.4    <- gcc-4.2.5_20081126
        /usr/local/lib/gcc-4.3.3/libffi.so.4    <- gcc-4.3.3_20090108
--> Two packages install the same library in different directories!



「-L」オプションだけだと、いきなりファイルを削除してしまうので、「-n」オプションもつけたほうがいいかもしれません。
もっとも、消されてしまっても、案外、どうでもよかったりします。



それから、今日、FreeBSD6なマシンで思い出したんですが、たしか/etc/defaults/rc.confにある



ldconfig_paths="/usr/lib/compat /usr/local/lib /usr/local/lib/compat/pkg"



みたいなやつに、/usr/X11R6/libが入ってて、かつ、/usr/X11R6が、/usr/localへのシンボリックリンクになってると(歴史的な事情で、普通はそうなってると思う)、/usr/loca/libと、/usr/X11R6/libの両方がldconfigで見に行ってしまい、ところが両者は同一のものなので、同じものが2個ずつ見つかる、というフィーバー状態になってました(笑)。






portsclean -Lで大掃除した結果、1個、残りました・・・



% portsclean -L
** /usr/local/lib/gcc-4.3.3/libobjc.so.2 is shadowed by /usr/local/lib/compat/libobjc.so.2
        /usr/local/lib/compat/libobjc.so.2      <- compat6x-i386-6.4.604000.200810
        /usr/local/lib/gcc-4.3.3/libobjc.so.2   <- gcc-4.3.3_20090108
--> Two packages install the same library in different directories!


見なかったことにしよう。



0 件のコメント:

コメントを投稿