bmpをビルドしようとして、またリンクの際に「undefined reference」のエラーが起きた。他の時にもよく起きるんだけれども、解決法がいまいちわからない。以下はbmpのビルド中に出てきたエラーログ。
gcc -g -O2 -Wall -Wpointer-arith -finline-functions -ffast-math -funroll-all-loops -o .libs/beep beep-skin.o beep-util.o beep-output.o beep-fft.o beep-input.o beep-effect.o beep-general.o beep-visualization.o beep-fullscreen.o beep-pluginenum.o beep-playlist.o beep-controlsocket.o beep-dock.o beep-widget.o beep-sbutton.o beep-pbutton.o beep-tbutton.o beep-textbox.o beep-menurow.o beep-hslider.o beep-monostereo.o beep-vis.o beep-svis.o beep-number.o beep-playback.o beep-playstatus.o beep-playlist_list.o beep-playlist_slider.o beep-playlist_popup.o beep-eq_graph.o beep-eq_slider.o beep-main.o beep-logger.o beep-xml_document.o beep-mainwin.o beep-skinwin.o beep-prefswin.o beep-playlistwin.o beep-equalizer.o beep-glade.o beep-hints.o beep-about.o beep-softvolume.o beep-getopt.o beep-getopt1.o beep-urldecode.o beep-mkdtemp.o beep-iir.o -Wl,--export-dynamic -pthread -Wl,--export-dynamic -Wl,--export-dynamic -L/usr/X11R6/lib64 -lSM -lICE -L/usr/local/lib64 -L/usr/lib64 -L/opt/gnome/lib64 /opt/gnome/lib64/libglade-2.0.so /opt/gnome/lib64/libgtk-x11-2.0.so /opt/gnome/lib64/libgdk-x11-2.0.so /opt/gnome/lib64/libatk-1.0.so /opt/gnome/lib64/libgdk_pixbuf-2.0.so /opt/gnome/lib64/libpangoxft-1.0.so /opt/gnome/lib64/libpangox-1.0.so /opt/gnome/lib64/libpango-1.0.so /opt/gnome/lib64/libgobject-2.0.so /opt/gnome/lib64/libgmodule-2.0.so /opt/gnome/lib64/libglib-2.0.so /usr/lib64/libxml2.so -lz ../libbeep/.libs/libbeep.so /usr/local/lib64/libgtk-x11-2.0.so /usr/local/lib64/libgdk-x11-2.0.so -lXrandr -lXi -lXinerama -lXext /usr/local/lib64/libatk-1.0.so /usr/local/lib64/libgdk_pixbuf-2.0.so -lm /usr/local/lib64/libpangoxft-1.0.so /usr/local/lib64/libpangoft2-1.0.so -lXft -lXrender /usr/lib64/libfontconfig.so /usr/lib64/libexpat.so /usr/lib64/libfreetype.so /usr/local/lib64/libpangox-1.0.so -lX11 /usr/local/lib64/libgthread-2.0.so -lpthread /usr/local/lib64/libpango-1.0.so /usr/local/lib64/libgobject-2.0.so /usr/local/lib64/libgmodule-2.0.so -ldl /usr/local/lib64/libglib-2.0.so ../intl/libintl.a -Wl,--rpath -Wl,/opt/gnome/lib64 -Wl,--rpath -Wl,/usr/local/lib64 beep-skin.o(.text+0x2e6f): In function `skin_load_nolock': /home/wataru/tmp/bmp-0.9.7rc2/beep/skin.c:699: undefined reference to `gdk_cursor_new_from_pixbuf' beep-skin.o(.text+0x2ea0):/home/wataru/tmp/bmp-0.9.7rc2/beep/skin.c:699: undefined reference to `gdk_cursor_new_from_pixbuf' beep-util.o(.text+0x276): In function `make_filebrowser': /home/wataru/tmp/bmp-0.9.7rc2/beep/util.c:1346: undefined reference to `gtk_file_chooser_dialog_new ...(中略)... /home/wataru/tmp/bmp-0.9.7rc2/beep/equalizer.c:1229: undefined reference to `gtk_file_chooser_get_filename' beep-glade.o(.text+0x347): In function `glade_xml_new_or_die': /home/wataru/tmp/bmp-0.9.7rc2/beep/glade.c:31: undefined reference to `gtk_message_dialog_new_with_markup' /usr/local/lib64/libpangoft2-1.0.so: undefined reference to `g_type_instance_get_private' /usr/local/lib64/libpangoft2-1.0.so: undefined reference to `g_type_class_add_private' /usr/local/lib64/libgthread-2.0.so: undefined reference to `g_thread_init_glib' collect2: ld returned 1 exit status
ライブラリの依存関係を調べるときに使うコマンドは「ldd」、ライブラリのファイルを調べると以下のような形で依存関係がわかる。各ファイルにどんな名前の関数があるか調べる場合に使うコマンドは「nm」、詳しくはman nmで見れば問題無し。
で、既存のライブラリに対してundefined referenceて言われるってことは、ライブラリの依存関係が解消されていない場合だと思います。調べ方はたぶん、nmで任意の関数がどのファイルにあるかを調べる。例えば以下はg_type_instance_get_privateがどのファイルにあるかを調べる。コマンド行の下は家の環境でのその出力です。
%nm -o /usr/local/lib64/*.so | grep g_type_instance_get_private libgobject-2.0.so:0000000000021720 T g_type_instance_get_private libgtk-x11-2.0.so: U g_type_instance_get_private libpangoft2-1.0.so: U g_type_instance_get_private
"U"の場合、そこでは定義されていないから、lddを使って依存関係を掘り下げながら定義されているを見付ける。もし見付けられなければ「undefined reference」ということになる。
んが、今回それはなかった。というわけで、多分、/opt/gnome/lib64に入っているgtk+2.2関係のライブラリと/usr/local/lib64に入っているgtk+2.4関係のライブラリが両方とも指定されているせいじゃないかと思う。っていうかgtk周りでばっかりコレが起きてるんだから、それしかなかろう...。
でも全てのgtkアプリで起きている訳じゃない、たまたまライブラリの関数を使っていなかったからなのか、そもそもライブラリのビルド過程に問題があったのか、ていうか問題の起きた関数を使って自分でプログラム組んでみりゃええがな。後はMakefileいじってみるか。そうすりゃ他になんかわかるやろう。
じゃなんでnmやらlddの話を書いたかっていうと、単に備忘録のためだったり...。大体、lddはともかくnmなんてコマンド覚えてられないよ。下のトピックは今回参考にしたリンク。nmが思い出せなくてえらい時間がかかった。
nmやらlddやら共有オブジェクトについて調べてる時に見付けたのでリンク。-fPICオプションについて正直よく知らなかった(ぇー。