2010/04/16(Fri)
○[NetBSD] Only one ABI change in libc, in more than 15 years!(その3)
さて誰得な気もするけど、昨日のチラシの裏のつづきにして最後。
(これまでのうらすじ)
昔々 libfoo.so.12 のところに foo というシンボルがありました。
このシンボルを call すると、"hello, libfoo12."というどうでもいい文字列を表示します。
ある日のことどっかのloopyな王様が仕様変更を唱えまして、"hello, libcfoo13."と表示しなければならなくなりま。
困ったことにこの変更でバイナリ後方互換が壊れてしまった(ということにしといてくらはい)ので
*BSD 村一番の後方互換パラノイア、NetBSD は、奥義 __RENAME マクロを使って対処しました。
ですので古いバイナリは foo を呼びますが、新しいバイナリは ヘッダ中ですりかえられた
__foo60 を呼んでます、ですのでバイナリ後方互換は守られみな幸せに暮らしましたとさ(おわr
このすりかえは ヘッダをインクルードせずに extern foo した場合には
just won't work on youですが
まぁその場合は __warn_references マクロでリンク時警告出してますんで自己責任ということで。
そもそも __RENAME マクロは共有ライブラリのの soname を変更したくない為の怪しげな voodoo です。
ですので major を crunk するといちど決めてしまえば "hello, libfoo12." を表示する foo の方はもはや不要です。
そして "hello, libfoo13."を表示する __foo60 は元の正しい名前、foo としてコンパイルして欲しいわけです。
ですので libfoo12.tar.gzから libfoo13.tar.gzで以下の書き換えを行いました。
- libfoo13/foo/foo.c が __foo60 ではなく foo になるよう、libfoo13/include/foo.h から __RENAMEを削除する。
--- libfoo12/include/foo.h 2010-04-13 07:58:20.000000000 +0900 +++ libfoo13/include/foo.h 2010-04-13 08:41:42.000000000 +0900 @@ -4,7 +4,7 @@ #include <sys/cdefs.h> __BEGIN_DECLS -void foo(void) __RENAME(__foo60); +void foo(void); __END_DECLS #endif /*_FOO_H_*/
- libfoo13/compat/foo/compat_foo.c はもう不要になるので libfoo13/Makefile で
libfoo13/compat/Makefile.inc をインクルードするのをやめる。--- libfoo12/Makefile 2010-04-13 08:37:52.000000000 +0900 +++ libfoo13/Makefile 2010-04-13 08:43:04.000000000 +0900 @@ -1,8 +1,9 @@ LIB= foo CPPFLAGS+= -I${.CURDIR} -COMPATDIR= ${.CURDIR}/compat .include "${.CURDIR}/foo/Makefile.inc" -.include "${COMPATDIR}/Makefile.inc" + +SUBDIR= compat +.include <bsd.subdir.mk> .include <bsd.lib.mk>
- libfoo*/shlib_version に記述された major を 12 -> 13 に変更する。
--- libfoo12/shlib_version 2010-04-13 09:24:25.000000000 +0900 +++ libfoo13/shlib_version 2010-04-13 09:24:18.000000000 +0900 @@ -1,2 +1,2 @@ -major=12 +major=13 minor=0
- 使用されなくなった libfoo13/compat 以下を再利用し、後方互換のための libfoo.so.12 をここで作成するため
libfoo13/compat/Makefile
libfoo13/compat/shlib_versionLIB= foo CPPFLAGS+= -I${.CURDIR}/.. COMPATDIR= ${.CURDIR} .include "${.CURDIR}/Makefile.inc" .include "${.CURDIR}/foo/Makefile.inc" .include <bsd.lib.mk>
の2つのファイルを追加し、libfoo13/Makefile では compat を SUBDIR に指定するように変更。major=12 minor=0
- libfoo13/compat/foo/compat_foo.c だけだと foo しか作られないので libfoo13/compat/foo/Makefile.incで
無理矢理 libfoo13/foo を参照するように .PATH を設定した上で SRCSに libfoo13/foo/foo.c を追加する。--- libfoo12/compat/foo/Makefile.inc 2010-04-13 08:39:51.000000000 +0900 +++ libfoo13/compat/foo/Makefile.inc 2010-04-13 08:45:43.000000000 +0900 @@ -1,3 +1,4 @@ -.PATH: ${COMPATDIR}/foo -SRCS+= compat_foo.c +.PATH: ${COMPATDIR}/foo ${.CURDIR}/../foo +SRCS+= compat_foo.c foo.c CPPFLAGS.compat_foo.c+= -I${COMPATDIR}/include +CPPFLAGS.foo.c+= -I${.CURDIR}/../include
- このままだと libfoo13/foo/foo.c も libfoo13/compat/foo/compat_foo.c もどちらも foo で
ビルドされてしまうので、今度は libfoo13/compat/include/foo.h に __RENAME を追加する。
また libfoo13/foo/foo.c が __foo60 libfoo13/compat/foo/compat_foo.c が foo としてビルドされるよう--- libfoo12/compat/include/foo.h 2010-04-13 08:18:34.000000000 +0900 +++ libfoo13/compat/include/foo.h 2010-04-13 08:46:33.000000000 +0900 @@ -2,7 +2,7 @@ #define _COMPAT_FOO_H_ __BEGIN_DECLS -void foo(void); +void foo(void) __RENAME(__foo60); __END_DECLS #endif /*_FOO_H_*/
libfoo13/compat/foo/Makefile.inc で foo.h へのインクルードパスを libfoo12 とは反対に入れ替えてることに注意!
とまぁこんな感じでヘッダとMakefile関係をちょびっと書き直すだけで major crunk 前後にうまく対応してるわけです。
はい、ややこし過ぎてとても正気の沙汰とは思えませんです :D うまくない!
しかも弱点がこれあって、foo.c が1関数で完結してないと駄目だよねという、それともstatic な関数
とかはまだしも、libc内部でだけ使われるシンボルも全部 __RENAME しちゃうんですかね。
とーっても無駄すぎると思うのですが。
あと compat だと 1回の soname 変更にしか対応できないよね、次に libfoo14 とかが必要になる事態まで考えてないよね。
libfoo13/compat じゃなくて libfoo13/compat12 としといた方がいいんじゃないの、とかかなぁ。
とまぁこんな感じです。トリックが無駄にややこしいので私の貧弱な文章力では何人理解できるか大変不安、ごめんちゃい。