2009年9月19日土曜日

(FreeBSD) /usr/ports/math/octaveで、/libexec/ld-elf.so.1: /usr/lib/libstdc++.so.6: version GLIBCXX_3.4.11 required by ./gendoc not found

FreeBSDのportsで、math/octaveをportupgrade中に、こんなエラーがでて終了・・・



making gendoc.cc
g++44 -O2 -fno-strict-aliasing -pipe -I/usr/local/include -I/usr/local/include -o gendoc gendoc.cc -L/usr/local/lib -pthread
making DOCSTRINGS
/libexec/ld-elf.so.1: /usr/lib/libstdc++.so.6: version GLIBCXX_3.4.11 required by ./gendoc not found
gmake[2]: *** [DOCSTRINGS] エラー 1
gmake[2]: ディレクトリ `/WORK/usr/ports/math/octave/work/octave-3.2.2/src' から出ます
gmake[1]: *** [src] エラー 2
gmake[1]: ディレクトリ `/WORK/usr/ports/math/octave/work/octave-3.2.2' から出ます
gmake: *** [all] エラー 2
*** Error code 1



Stop in /usr/ports/math/octave.



ちなみに、octaveは、USE_FORTRAN=yes になっているので、portsのバージョンが上がったみたい。


ちょっと調べてみました。



# ./gendoc
/libexec/ld-elf.so.1: /usr/lib/libstdc++.so.6: version GLIBCXX_3.4.11 required by ./gendoc not found



なるほど、実行できませんね。



% nm -C gendoc | grep GLIBCXX_3.4.11
         U _ZNKSt5ctypeIcE13_M_widen_initEv@@GLIBCXX_3.4.11



GLIBCXX_3.4.11って、これのことですか。なるほど、symbol versioningってやつのことみたいですね。



えーと・・・



# ldd gendoc
gendoc:
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x480f9000)
        libm.so.5 => /lib/libm.so.5 (0x481ee000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x48203000)
        libthr.so.3 => /lib/libthr.so.3 (0x4820e000)
        libc.so.7 => /lib/libc.so.7 (0x48223000)



なるほど、たぶん、違うバージョンのGCCの共有ライブラリが使われている、というわけで。



というか、g++44、「/usr/local/bin/g++44」でコンパイルしているのに、/usr/lib/libstdc++.so.6 が使われている時点で、そりゃおかしくないか? ですね。


ふときがつけば、「libstdc++.so.6」って、同じ名前のファイルが、いくつもあるんですけど・・・



# ls -l /usr/local/lib/gcc*/libstdc++.so.6 /usr/lib/libstdc++.so.6
-r--r--r--  1 root  wheel   981660  8 26 17:51 /usr/lib/libstdc++.so.6
-rwxr-xr-x  1 root  wheel  4419577  9 17 09:57 /usr/local/lib/gcc43/libstdc++.so.6
-rwxr-xr-x  1 root  wheel  4560445  9 14 11:21 /usr/local/lib/gcc44/libstdc++.so.6



ついでに、libgcc_s.so.1も複数あるし。



# ls -1 /lib/libgcc_s.so.1 /usr/local/lib/gcc*/libgcc_s.so.1
/lib/libgcc_s.so.1
/usr/local/lib/gcc43/libgcc_s.so.1
/usr/local/lib/gcc44/libgcc_s.so.1



/usr/libのほうは・・・GLIBCXX_3.4.11というのが入ってない。



% strings /usr/lib/libstdc++.so.6|grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_FORCE_NEW



一方、GCC 4.4のほうは・・・あります。



% strings /usr/local/lib/gcc44/libstdc++.so.6 | grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_FORCE_NEW
GLIBCXX_DEBUG_MESSAGE_LENGTH



おまけ。GCC 4.3だけど、まあ、これはどうでもいいけど。



% strings /usr/local/lib/gcc43/libstdc++.so.6 | grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_FORCE_NEW
GLIBCXX_DEBUG_MESSAGE_LENGTH


というわけで、/usr/local/lib/gcc44 にある共有ライブラリが使われるようにすればOKなはずなので、たとえばLD_LIBRARY_PATHを使ってやれば



# env LD_LIBRARY_PATH=/usr/local/lib/gcc44 ldd gendoc
gendoc:
        libstdc++.so.6 => /usr/local/lib/gcc44/libstdc++.so.6 (0x480f9000)
        libm.so.5 => /lib/libm.so.5 (0x481e3000)
        libgcc_s.so.1 => /usr/local/lib/gcc44/libgcc_s.so.1 (0x481f8000)
        libthr.so.3 => /lib/libthr.so.3 (0x48204000)
        libc.so.7 => /lib/libc.so.7 (0x48219000)



これで、実行できるようになります。



ですが、LD_LIBRARY_PATHを指定しないといけない、ってのは正常とは思えません。



ldconfigがおかしいのかな?と思ったのですが



# ldconfig -r
/var/run/ld-elf.so.hints:
        search directories: /lib:/usr/lib:/usr/lib/compat:/usr/local/lib:/usr/local/lib/compat/pkg:/usr/local/kde4/lib:/usr/local/lib/compat:/usr/local/lib/evolution/2.26:/usr/local/lib/gcc/i386-portbld-freebsd7.2/3.4.6:/usr/local/lib/gcc43:/usr/local/lib/gegl-0.0:/usr/local/lib/graphviz:/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/virtualbox:/usr/local/lib/gcc44
        0:-lc.7 => /lib/libc.so.7
        1:-lcrypt.4 => /lib/libcrypt.so.4
(以下省略)



こういう順番でディレクトリを検索していくので、共有ライブラリが同じファイル名である以上、/usr/libが見つかってしまうのは、しかたなし。



LD_LIBRARY_PATHは使わずに、コンパイル時に、rpath(runpath, runtime shared library search path)を指定すれば、まあ、とりあえずOKかな、と。



% g++44 -O2 -fno-strict-aliasing -pipe -I/usr/local/include -I/usr/local/include -o gendoc gendoc.cc -L/usr/local/lib -pthread -Wl,--rpath,/usr/local/lib/gcc44



% ldd gendoc
gendoc:
        libstdc++.so.6 => /usr/local/lib/gcc44/libstdc++.so.6 (0x480f9000)
        libm.so.5 => /lib/libm.so.5 (0x481e3000)
        libgcc_s.so.1 => /usr/local/lib/gcc44/libgcc_s.so.1 (0x481f8000)
        libthr.so.3 => /lib/libthr.so.3 (0x48204000)
        libc.so.7 => /lib/libc.so.7 (0x48219000)



ただ、わざわざこんな「-Wl,--rpath,/usr/local/lib/gcc44」というオプションを追加しなくちゃいけない、ってのはなんか間違っている気がします。
portsのgcc44で、このへんを、ケアしてもらえないんでしょうかね。




GNU C++ (GCC) version 4.4.2 20090908 (prerelease) (i386-portbld-freebsd7.2)
        compiled by GNU C version 4.4.2 20090908 (prerelease), GMP version 4.3.1, MPFR version 2.4.1.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 5feec5ea47297b9f3ff6755b82d5a555
COMPILER_PATH=/usr/local/libexec/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/:/usr/local/libexec/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/:/usr/local/libexec/gcc44/gcc/i386-portbld-freebsd7.2/:/usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/:/usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/
LIBRARY_PATH=/usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/:/usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-O2' '-fno-strict-aliasing' '-pipe' '-I/usr/local/include' '-I/usr/local/include' '-o' 'gendoc' '-L/usr/local/lib' '-pthread' '-shared-libgcc' '-mtune=i386'
/usr/local/libexec/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/collect2 -V -dynamic-linker /libexec/ld-elf.so.1 -o gendoc /usr/lib/crt1.o /usr/lib/crti.o /usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/crtbegin.o -L/usr/local/lib -L/usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2 -L/usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/../../.. /tmp//ccM05ca2.o -lstdc++ -lm -lgcc_s -lgcc -lpthread -lc -lgcc_s -lgcc /usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/crtend.o /usr/lib/crtn.o
GNU ld version 2.15 [FreeBSD] 2004-05-23
  Supported emulations:
   elf_i386_fbsd




もしかして、g++44でコンパイルしたC++なプログラムって、ことごとく動かないんじゃ・・・



試してみよう。



#include <iostream>



int
main( int argc, char* argv[] )
{
  std::cout << "Hello world" << std::endl;



  return 0;
}



% g++44 hello.cc
% ldd a.out
a.out:
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x4807d000)
        libm.so.5 => /lib/libm.so.5 (0x48172000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x48187000)
        libc.so.7 => /lib/libc.so.7 (0x48192000)
% ./a.out
Hello world



あれ?本来とは違う共有ライブラリが使われているのに、動いちゃいますね。



% strings a.out|grep GLIBC
GLIBCXX_3.4



というわけで、新しいライブラリの必要としないみたい。



ただし、コンパイル時は、/usr/local/lib/gcc44/gcc/以下の共有ライブラリが参照されています。



% g++44 -Wl,--verbose hello.cc
GNU ld version 2.15 [FreeBSD] 2004-05-23
  Supported emulations:
   elf_i386_fbsd
using internal linker script:
==================================================
/* Script for -z combreloc: combine and sort reloc sections */
OUTPUT_FORMAT("elf32-i386-freebsd", "elf32-i386-freebsd",
              "elf32-i386-freebsd")
OUTPUT_ARCH(i386)
省略



attempt to open /usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/libstdc++.so failed
attempt to open /usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/libstdc++.a failed
attempt to open /usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/../../../libstdc++.so succeeded
-lstdc++ (/usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/../../../libstdc++.so)
省略



attempt to open /usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/libgcc_s.so failed
attempt to open /usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/libgcc_s.a failed
attempt to open /usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/../../../libgcc_s.so succeeded
-lgcc_s (/usr/local/lib/gcc44/gcc/i386-portbld-freebsd7.2/4.4.2/../../../libgcc_s.so)





portsでインストールしたGCCを使うときは、rpathが自動的に追加されるようにならないかなぁ~。



0 件のコメント:

コメントを投稿