ttt

getttyent

(FreeBSD ports/lang/gcc42) /usr/bin/ld: .libs/jv-c

2007-01-11 21:53:57 | デジタル・インターネット

Problem summary

ports/lang/gcc42 cannot build with following error messages.

/home2/ports.work/usr/ports/lang/gcc42/work/build/gcc/gcj -B/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava/ -B/home2/ports.work/usr/ports/lang/gcc42/work/build/gcc/ -ffloat-store -fomit-frame-pointer -g -O2 -o .libs/jv-convert --main=gnu.gcj.convert.Convert -shared-libgcc -pthread  -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava/.libs ./.libs/libgcj.so -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libstdc++-v3/src -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libstdc++-v3/src/.libs -lz -L/home2/ports.work/usr/ports/lang/gcc42/work/build/./gcc -lgcc_s -lgcc_s -Wl,--rpath -Wl,/usr/local/lib/gcc-4.2.0
/usr/bin/ld: .libs/jv-convert: hidden symbol `__eprintf' in /home2/ports.work/usr/ports/lang/gcc42/work/build/./gcc/libgcc.a(_eprintf.o) is referenced by DSO
collect2: ld returned 1 exit status
gmake[3]: *** [jv-convert]  1
gmake[3]:  `/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava'
gmake[2]: *** [all-recursive]  1
gmake[2]:  `/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava'
gmake[1]: *** [all-target-libjava]  2
gmake[1]:  `/home2/ports.work/usr/ports/lang/gcc42/work/build'

OS version

FreeBSD 5.5-STABLE.

Some FreeBSD 6.2-PRERELEASE could build ports/lang/gcc42 and others did not.

How to fix

# pkg_delete gcc-2.95.3_2

Problem details

unresolved __eprintf symbol was included in libgcj.a

# nm .libs/libgcj.a | grep eprintf
         U __eprintf
         U __eprintf

this came from ltdl.o and mprec.o

ltdl.o:
000000a3 r .LC9
         U _CurrentRuneLocale
         U _GLOBAL_OFFSET_TABLE_
         U ___runetype
         U __eprintf

mprec.o:
00000157 T _Jv_ulp
         U __eprintf

# find . -name ltdl.o -print
./libltdl/.libs/ltdl.o
./libltdl/ltdl.o

libltdl/ltdl.o:
         U _CurrentRuneLocale
         U ___runetype
         U __eprintf
         U __isthreaded
         U access

ltdl.o was build like this

# /bin/sh ./libtool --debug --tag=CC --mode=compile /home2/ports.work/usr/ports/lang/gcc42/work/build/./gcc/xgcc -B/home2/ports.work/usr/ports/lang/gcc42/work/build/./gcc/ -B/usr/local/i386-portbld-freebsd5.5/bin/ -B/usr/local/i386-portbld-freebsd5.5/lib/ -isystem /usr/local/i386-portbld-freebsd5.5/include -isystem /usr/local/i386-portbld-freebsd5.5/sys-include -DHAVE_CONFIG_H -I. -I../../.././..//gcc-4.2-20070102/libjava/libltdl -I. -O2 -O -pipe -march=pentiumpro -c -o ltdl.lo ../../.././..//gcc-4.2-20070102/libjava/libltdl/ltdl.c

Looking into /usr/local/i386-portbld-freebsd5.5/include, __eprintf symbol can be found.

# grep -R eprintf /usr/local/i386-portbld-freebsd5.5/include
/usr/local/i386-portbld-freebsd5.5/include/assert.h:extern void __eprintf (const char *, const char *, unsigned, const char *)
/usr/local/i386-portbld-freebsd5.5/include/assert.h:extern void __eprintf (const char *, const char *, unsigned, const char *)
/usr/local/i386-portbld-freebsd5.5/include/assert.h:  (__eprintf ("%s:%u: failed assertion `%s'\n",             \
/usr/local/i386-portbld-freebsd5.5/include/assert.h:extern void __eprintf () __attribute__ ((noreturn)); /* Defined in libgcc.a */
/usr/local/i386-portbld-freebsd5.5/include/assert.h:  (__eprintf ("%s:%u: failed assertion `%s'\n",             \

Hummmm...

# ls -l /usr/local/i386-portbld-freebsd5.5/include/assert.h
-rw-r--r--  1 root  wheel  1486 11  9 14:41 /usr/local/i386-portbld-freebsd5.5/include/assert.h
# pkg_which  /usr/local/i386-portbld-freebsd5.5/include/assert.h
gcc-2.95.3_2

There is one more problem about ports/lang/gcc42

Problem summary

ports/lang/gcc42 cannot build binary package.

===>  Building package for gcc-4.2.0_20070102
Creating package /usr/ports/packages-5-stable/All/gcc-4.2.0_20070102.tbz
Registering depends: mpfr-2.2.1 libiconv-1.9.2_2 libgmp-4.2.1_1.
Creating bzip'd tar ball in '/usr/ports/packages-5-stable/All/gcc-4.2.0_20070102.tbz'
tar: bin/jar42: Could not stat: No such file or directory
pkg_create: make_dist: tar command failed with code 256
*** Error code 1

Stop in /usr/ports/lang/gcc42.

How to fix

a very simple workaround is ...

# touch /usr/local/bin/jar42

# make package
===>  Building package for gcc-4.2.0_20070102
Creating package /usr/ports/packages-5-stable/All/gcc-4.2.0_20070102.tbz
Registering depends: mpfr-2.2.1 libiconv-1.9.2_2 libgmp-4.2.1_1.
Creating bzip'd tar ball in '/usr/ports/packages-5-stable/All/gcc-4.2.0_20070102.tbz'

---------------------------------------------------

というわけで、FreeBSDのportsで、lang/gcc42をビルドしようとしたら(別にgcc-4.2が使いたいわけじゃなくて、portupgradeしたときに、依存関係によって、gcc42がビルドされただけなんですが)、エラーがでて失敗しました。

/usr/bin/ld: .libs/jv-convert: hidden symbol `__eprintf' で検索すると

http://lists.freebsd.org/pipermail/freebsd-questions/2007-January/138706.html

lang/gcc41 woes

というのが見つかりますが

hidden symbol `__eprintf' で検索すると、もっとたくさんでてくるようです。

で、いろいろ見てみましたが、解決方法は見つかりませんでした。

仕方ないので、自分で調べてみたよ、ってかんじ。

調べてみた結果、ports/lang/gcc295でインストールされるassert.hに含まれるシンボル__eprintfが悪さをしているのが原因でした。gcc42とgcc295がconflictしてる、っていってもいいかもしれませんが、gcc295のassert.hのインストール先がおかしいんじゃない?っていう気もします。

問題の解決方法をどうやって見つけたか?

かなり泥臭い方法ですが・・・

エラーを出したコマンドが

/home2/ports.work/usr/ports/lang/gcc42/work/build/gcc/gcj -B/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava/ -B/home2/ports.work/usr/ports/lang/gcc42/work/build/gcc/ -ffloat-store -fomit-frame-pointer -g -O2 -o .libs/jv-convert --main=gnu.gcj.convert.Convert -shared-libgcc -pthread  -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libjava/.libs ./.libs/libgcj.so -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libstdc++-v3/src -L/home2/ports.work/usr/ports/lang/gcc42/work/build/i386-portbld-freebsd5.5/libstdc++-v3/src/.libs -lz -L/home2/ports.work/usr/ports/lang/gcc42/work/build/./gcc -lgcc_s -lgcc_s -Wl,--rpath -Wl,/usr/local/lib/gcc-4.2.0

だったので、これの頭に、「ktrace」をつけて実行しました。ようするに、どのファイルを参照しているのか、を知りたかったのです。しかし、残念ながら、途中でexecしてしまうようで、ktraceで追いかけられません(私が子プロセスのトレース方法を知らないだけ?)。

ただ、何をexecしたかはktraceでわかるので、execしているプログラムを、ktraceで実行するようにwrapper scriptを作成します。さらにexecしてれば、同じことの繰り返し。

そうやってわかったのですが

/home2/ports.work/usr/ports/lang/gcc42/work/build/gcc/collect2 が呼ばれていて、

さらに

/home2/ports.work/usr/ports/lang/gcc42/work/build/gcc/collect-ld

が呼ばれてました。で、collect-ldの中身はというと

# cat /home2/ports.work/usr/ports/lang/gcc42/work/build/gcc/collect-ld
#!/bin/sh
exec /usr/bin/ld "$@"

なんてものだったので、ここ「ld --verbose」と書き換えてしまいます。

exec /usr/bin/ld --verbose "$@"

さらにexecの行の前に、

echo /usr/bin/ld "$@"

とか付けたすのもいいかもしれません。

これで、実際にどのファイル(ライブラリ)をリンクするかが表示されるようになるので、あとは、アクセスしたファイルすべてについて、「grep __eprintf」をしまくります。

そうやってみつけたのが、libgcj.aでした。

ktraceしたのは、grepでの探索範囲を狭めるという目的があったからでして、grep -Rで手当たりしだいに探すのでも、いいかもしれません(時間がかかるかもしれませんが)。

libgcj.aに取り込まれたltdl.oに、__eprintfというunresolved symbolがあることが、nmコマンドですぐにわかりますから、あとは、ltdl.oがどうやってコンパイルされたかを、調べればいいってこと。コンパイル中のログをみてもいいし、ログを残していなければ、ファイルを削除してから、gmakeコマンドを実行しちゃえばいいです。

/home2/ports.work/usr/ports/lang/gcc42/work/build/./gcc/xgcc -B/home2/ports.work/usr/ports/lang/gcc42/work/build/./gcc/ -B/usr/local/i386-portbld-freebsd5.5/bin/ -B/usr/local/i386-portbld-freebsd5.5/lib/ -isystem /usr/local/i386-portbld-freebsd5.5/include -isystem /usr/local/i386-portbld-freebsd5.5/sys-include -DHAVE_CONFIG_H -I. -I../../.././..//gcc-4.2-20070102/libjava/libltdl -I. -O2 -O -pipe -march=pentiumpro -c ../../.././..//gcc-4.2-20070102/libjava/libltdl/ltdl.c -o ltdl.o

というコマンドでコンパイルされているので、じゃあ、includeファイルのどこかに__eprintfがあるに違いない、となるので、include pathにあるディレクトリについて、grep -Rしまくったところ

% grep -R eprintf /usr/local/i386-portbld-freebsd5.5/include
/usr/local/i386-portbld-freebsd5.5/include/assert.h:extern void __eprintf (const char *, const char *, unsigned, const char *)

というかんじで見つかりました。

このヘッダファイルはどこからやってきたのか、どのパッケージでインストールされたのかは、pkg_whichでわかります。

# pkg_which  /usr/local/i386-portbld-freebsd5.5/include/assert.h
gcc-2.95.3_2

なーんだ、じゃあ、gcc-2.95.3_2をpkg_deleteしちゃえばいいんじゃない?

というかんじです。