今日、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関係では、これまで何度かトラブルがありました。
- (FreeBSD) portsでビルド中に、undefined reference to `__mulxc3@GCC_4.0.0' というエラー
- (FreeBSD) USE_FORTRAN=yesの罠 ~ gcc42をうっかりアンインストールしてはいけない
gfortranを使うportsは、portsでインストールしたgccへ、依存関係をぶらさげてくれればいいのに。
てゆーか、こういう問題って、symbol versioningとかいう機能で解決されたりしないんでしたっけ? ←よく知らない。
この不具合については存じ上げておりました。
返信削除USE_FORTRAN=yesがgcc42に依存ししたがって、RUN_DEPENDSにもかくべきだというのは、当たり前のことでしたが、忘れていたため一年も放置してしまいました。PR 110952
おっと、すみません。
返信削除こんなブログでぶつぶつ言わず、send-prすべきでした。
[E:coldsweats01]
PR110952はすでにreminderのために書いてたので、send-pr
返信削除したところで、duplicatedでしょう。
ports freezeを狙って僕をpingするのがよかったのでしょうね。
フィードバックが少ないので、進みが悪く、また、
僕も含め多くの人に負担がかかりますので
問題を見つけたらメンテナーなりにメールかいてください。
ご協力お願い致します。