適当に翻訳する。
mkisofs の管理者様へ
84000 程度のディレクトリを持つ CD-ROM イメージを書き込もうとすると、2 の 16 乗のディレクトリ数上限にぶつかる。これは write.c 文書の以下に抜粋した部分に因る。
/*
* ここから経路表に書き込んでいく。ルート・ディレクトリから始める。
*/
if (next_path_index > 0xffff) {
#ifdef USE_LIBSCHILY
comerrno(EX_BAD,
"Unable to generate sane path tables - too many directories (%d)\n",
next_path_index);
「sane」という語に注意。無効という意味ではない。
疑問:この現象は ISO 9660 標準仕様に基づくものなのか、そうでない何かなのか。ISO 9660 形式のデータと大量のディレクトリを持つ DVD ではどうなのか。
「if (next_path_index > 0xffff)」という検査を単純に飛ばしたらどうなるか。
全ての教示と cdrtools 開発に捧げられた素晴らしい仕事とに、先に礼を述べておく。
「directory」構造体の「path_index」は unsigned short で定義されており、65536 が上限。(mkisofs.h を参照)
「path_index」は経路表(path table)で利用される。これは iso9660.h で定義されていて、親ディレクトリの ID を示すのに 2 バイトしか使えない。次のサイトの 9.4 節「経路表の単位の形式」も参照。
http://www.y-adagio.com/public/standards/iso_cdromr/sect_2.htm
James Pearson
訳註:「directory」構造体の「path_index」は現在(cdrtools-3.00)、 unsigned int で定義されている(mkisofs.h にて)。0xffff の判定は健在(write.c にて)で、ディレクトリは 65536 個までしか使えない。
「iso_path_table」構造体(iso9660.h にて)
struct iso_path_table {
unsigned char name_len[2]; /* 721 */
char extent[4]; /* 731 */
char parent[2]; /* 721 */
char name[1];
};
バイナリが使用しているシンボルに、直接結合されたライブラリによっては提供されないものが含まれている時、その状態を下潜結合という。例えば、libeb では zlib の「deflate」が使われている。しかし libeb の構築にあたっては -lz は付けられていない。このやり方は共有ライブラリでは認められている。
objdump -p /usr/lib/libeb.so | grep NEEDED
NEEDED libnsl.so.1
NEEDED libresolv.so.2
NEEDED libc.so.6
libeb を利用するプログラムには、明示的に libz を結合する必要がある。直接 libz を使っていなくても。
% echo 'main() { eb_log("foo"); }' > t.c
% gcc t.c -leb -lz
% gcc t.c -leb
/usr/lib/libeb.so: undefined reference to `inflateEnd'
/usr/lib/libeb.so: undefined reference to `deflate'
...
collect2: ld returned 1 exit status
上のプログラムは -Wl,--as-needed を用いて結合してはいけない。(過剰結合)
% gcc t.c -Wl,--as-needed -leb -lz
/usr/lib/libeb.so: undefined reference to `inflateEnd'
/usr/lib/libeb.so: undefined reference to `deflate'
...
collect2: ld returned 1 exit status
例えば、librsvg は libm の「tan」を使用しているが、構築時に「-lm」は付けられていない。
この librsvg と libm を基にした下潜結合は、先の単純な例とは異なり、librsvg を伴って構築されたプログラムに何の影響も及ぼさない。これは librsvg が多くの共有ライブラリと結合されており、その共有ライブラリの中に libm と結合されているものが存在することに因る。
新しい版の libfoo が公開され、今度の libfoo は zlib を使用している、しかし libfoo 構築時に zlib は結合していない、この場合どうなるか。libfoo を使用している全てのプログラムは「-lz」を付けて構築し直すことになる。
上で述べたように、下潜結合しているライブラリを付してプログラムを構築する時、--as-needed を使ってはいけない。
例:
% gcc -Wl,--as-needed conftest.c -lgtk -lgdk -lgmodule -lgthread -lglib -lpthread -ldl -lXi -lXext -lX11 -lm
/usr/lib/libgtk.so: undefined reference to `gdk_window_foreign_new'
/usr/lib/libgtk.so: undefined reference to `gdk_drag_find_window'
/usr/lib/libgtk.so: undefined reference to `gdk_colormap_get_visual'
...
「-lgdk」が挙げられているが、conftest.c はこれを使用していないので、--as-needed 指定によって捨てられる。
解決方法は /usr/lib/libgtk.so を適切に libgdk と結合すること。未定義の参照が libgtk.so に含まれないようにする。
配布に際しては、パッケージの間の依存関係を知る必要がある。下潜結合状態のライブラリがあると、再構築するべきか判断できなくなる。(BuildRequires を確認すれば話は別だが。) また、これによって過剰結合せざるを得なくなる。
例:
libeb を必要とするプログラム foo は libeb と libz を付けて構築される。もし ABI の異なる新しい libz が公開されたら:
ROSA Linux では「-Wl,--no-undefined」が標準で LDFLAGS に設定されている。これによって全ての共有ライブラリ(DSO)が下潜結合されないようになる。足りないライブラリがあると構築に失敗する。例:
% echo 'main() { deflate(); }' > libfoo.c
% gcc -shared libfoo.c
% gcc -shared libfoo.c -Wl,--no-undefined
ccEqBIQo.o: In function `main':
libfoo.c:(.text+0x12): undefined reference to `deflate'
collect2: ld returned 1 exit status
--no-undefined を標準で用いると問題が起きることもある。特に plugins/modules に。下記を見よ。
ここで説明されている警告を見ることがあるだろう。(spec-helper の strip_and_check_elf_files によって調べられる。)
しかしこの検査は ldd -r を使っており、検出できない場合もある。
「ldd -r」を使う。例:
% ldd -r /usr/lib/libeb.so.10.0.2 >/dev/null
undefined symbol: inflateEnd (/usr/lib/libeb.so.10.0.2)
undefined symbol: deflate (/usr/lib/libeb.so.10.0.2)
undefined symbol: deflateInit_ (/usr/lib/libeb.so.10.0.2)
undefined symbol: inflate (/usr/lib/libeb.so.10.0.2)
undefined symbol: deflateEnd (/usr/lib/libeb.so.10.0.2)
undefined symbol: inflateInit_ (/usr/lib/libeb.so.10.0.2)
「ldd -r」では十分でない。「表に現れない場合」を検出できない。構築時に --no-unneeded を使えばあらゆる場合に対応できる。
修正の例:
--- distcache-1.5.1/ssl/libnalssl/Makefile.am 2004-04-30 13:09:14.000000000 -0400
+++ distcache-1.5.1.oden/ssl/libnalssl/Makefile.am 2008-05-21 12:11:36.000000000 -0400
@@ -3,3 +3,4 @@
lib_LTLIBRARIES = libnalssl.la
libnalssl_la_SOURCES = bss_nal.c
libnalssl_la_LDFLAGS = -version-info 1:1:0
+libnalssl_la_LIBADD = ../../libnal/libnal.la
--- gtk+-1.2.10/gtk/Makefile.am.gtkgdkdep 2003-10-15 15:20:27.000000000 -0400
+++ gtk+-1.2.10/gtk/Makefile.am 2003-10-15 15:22:50.000000000 -0400
@@ -23,6 +23,10 @@
# libtool stuff: set version and export symbols for resolving
libgtkincludedir = $(includedir)/gtk-1.2/gtk
+
+libgtk_la_DEPENDENCIES = $(top_builddir)/gdk/libgdk.la
+libgtk_la_LIBADD = $(top_builddir)/gdk/libgdk.la
+
libgtk_la_LDFLAGS = @STRIP_BEGIN@ \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
-release $(LT_RELEASE) \
make libid3_la_LIBADD="-lstdc++ -lz" で修正できる。
二つの問題に気をつける。
mpg123 を例に採る。プラグインは呼出し元のプログラムで定義された関数を使用している。
% ldd -r /usr/lib/mpg123/output_sdl.so >/dev/null
undefined symbol: sfifo_close (/usr/lib/mpg123/output_sdl.so)
undefined symbol: sfifo_init (/usr/lib/mpg123/output_sdl.so)
undefined symbol: sfifo_flush (/usr/lib/mpg123/output_sdl.so)
undefined symbol: sfifo_read (/usr/lib/mpg123/output_sdl.so)
undefined symbol: sfifo_write (/usr/lib/mpg123/output_sdl.so)
% objdump -T /usr/bin/mpg123 | grep sfifo
0805ac30 g DF .text 00000013 Base sfifo_flush
0805ac80 g DF .text 0000007a Base sfifo_init
0805adc0 g DF .text 000000b8 Base sfifo_read
0805ad00 g DF .text 000000c0 Base sfifo_write
0805ac50 g DF .text 00000021 Base sfifo_close
ここに挙げられたシンボル(プラグインの中では解決されない)は、そのプラグインを呼び出したプログラムの一部である。(以下のプログラムのプラグインが例。gnome-settings-daemon、compiz*、emerald、libxslt、lxpanel など。)
これらの特別なプログラムで下潜結合を禁じるには、次の一文を仕様文書に加える。
%define _disable_ld_no_undefined 1
この文が必要ないことも多々ある。というのは、%configure で呼び出される drop-ld-no-undefined-for-shared-lib-modules-in-libtool によって ltmain.sh/libtool が修正され、共有ライブラリ構築時に --no-undefined が無視されるようになるから。
より良い修正方法は libtool が -module 指定付きで正しく呼ばれるようにすること。(時々 -export-dynamic しか使われないことがある。両方用いられるべきなのに。)
ROSA Linux は Perl 機能群に対して --no-undefined 指定をしていない。Perl 機能群は構築の際、LDFLAGS を利用しないから。
Perl 機能群は libperl と結合されないので、むしろ指定するべきでない。
Ruby 機能群は libruby に対して結合されるので --no-undefined は必要ない。ruby/GNOME2 が壊れてしまうので、機能群構築にあたって --no-undefined は元々使われていない。このパッケージは複数の機能群(glib、gtk、atk、poppler など)を構築するが、これらは結合されない。そのかわりに、ruby コードによって然るべき順序で読込まれる。この特別なパッケージを修正するのが筋だが、今のところ ruby パッケージの方に解決処理が入っている。
カレンダー
カテゴリー
最新コメント
最新記事
ブログ内検索
広告