2009年1月14日水曜日

(FreeBSD) /usr/local/lib/liblapack.so: undefined reference to `_gfortran_pow_r8_i4'

今日、FreeBSDでportsを使ってとあるソフトをビルド中、以下のようなエラーがでました。



/usr/local/lib/liblapack.so: undefined reference to `_gfortran_pow_r8_i4'
/usr/local/lib/liblapack.so: undefined reference to `_gfortran_pow_r4_i4'
collect2: ld returned 1 exit status
*** Error code 1



エラーの意味としては、ライブラリliblapack.soをリンクしたところ、解決できないシンボルがあったよ、ということですね。



名前からして、libgfortranで定義されていそうな雰囲気がプンプンしてますので、nmで調べてみると



% nm /usr/local/lib/gcc-4.3.3/libgfortran.so | grep pow_
0007ba94 T _gfortran_pow_c10_i4
0007c0ec T _gfortran_pow_c10_i8
0007b8c4 T _gfortran_pow_c4_i4
0007be94 T _gfortran_pow_c4_i8
0007b97c T _gfortran_pow_c8_i4
0007bfa4 T _gfortran_pow_c8_i8
0007b750 T _gfortran_pow_i4_i4
0007bbd0 T _gfortran_pow_i4_i8
0007b7bc T _gfortran_pow_i8_i4
0007bc58 T _gfortran_pow_i8_i8
0007be30 T _gfortran_pow_r10_i8
0007bd7c T _gfortran_pow_r4_i8
0007bdd0 T _gfortran_pow_r8_i8



定義されてますね。ということは、libgfortranがリンクされていないのかな?おかしいな?と思い、あれこれ調べはじめて10分経過。う~ん、わかんねぇ。



・・・で、やっと気がつきました。



エラーが出たのは、以下のシンボル。

_gfortran_pow_r8_i4
_gfortran_pow_r4_i4

これらは、上のnmの出力には含まれていません。微妙に違うんです。紛らわしい。見間違いをしてました。



というわけで、今度は、liblapack.soに問題があるんじゃないかな、という気がしてくるわけです。



どのportsでインストールされたのか、確認。



# pkg_which /usr/local/lib/liblapack.so
lapack-3.1.1_1



# pkg_which /usr/local/lib/gcc-4.3.3/libgfortran.so
gcc-4.3.3_20090108



タイムスタンプを確認。



% ls -l /usr/local/lib/gcc-4.3.3/libgfortran.so*
lrwxrwxr-x  1 root  wheel       16  1 13 11:44 /usr/local/lib/gcc-4.3.3/libgfortran.so@ -> libgfortran.so.3
-rwxr-xr-x  1 root  wheel  2280928  1 13 11:44 /usr/local/lib/gcc-4.3.3/libgfortran.so.3*



% ls -l /usr/local/lib/liblapack.so
lrwxr-xr-x  1 root  wheel  14  6 24  2008 /usr/local/lib/liblapack.so@ -> liblapack.so.4



おおおぉぉぉ、libgfortran.soよりも、liblapack.soの方が古い。



というか、libgfortran.soの方が新しい。



つまり、liblapack.soが依存してたlibgfortran.soと、今存在するlibgfortran.soは別ものであるというわけですね。



というわけで、解決方法は、

# portupgrade -fp lapack-3.1.1_1



で、lapackをビルドしなおせば、きっとOKになる。

たしかに、一応は、これで解決できました。

portsのgccが更新されたときは、gfortranを使うportsも再ビルドが必要になる・・・かもしれない

ってことなんですね。
しかし、portsでは、lapackはgccに依存してる、といような情報はどこにも記録されていないので、気がつくのは非常に困難です。





gfortran関係では、これまで何度かトラブルがありました。





gfortranを使うportsは、portsでインストールしたgccへ、依存関係をぶらさげてくれればいいのに。



てゆーか、こういう問題って、symbol versioningとかいう機能で解決されたりしないんでしたっけ? ←よく知らない。



3 件のコメント:

  1. この不具合については存じ上げておりました。
    USE_FORTRAN=yesがgcc42に依存ししたがって、RUN_DEPENDSにもかくべきだというのは、当たり前のことでしたが、忘れていたため一年も放置してしまいました。PR 110952

    返信削除
  2. おっと、すみません。
    こんなブログでぶつぶつ言わず、send-prすべきでした。
    [E:coldsweats01]

    返信削除
  3. PR110952はすでにreminderのために書いてたので、send-pr
    したところで、duplicatedでしょう。
    ports freezeを狙って僕をpingするのがよかったのでしょうね。
    フィードバックが少ないので、進みが悪く、また、
    僕も含め多くの人に負担がかかりますので
    問題を見つけたらメンテナーなりにメールかいてください。
    ご協力お願い致します。

    返信削除