ruby 1.9.1-p243 @ Visual C++ 2008 -落とし穴 GL/LTCG Edition

何時までもp0を使うのも何だかやな感じなので、久方ぶりにrubyをビルドすることにした。
折角VC9を使うんだから、SSE2最適化や、リンク時のコード生成を付けても罰は当たらないだろうと、Makefile.subのOPTFLAGSに-GL -arch:SSE2、LDFLAGS、ARFLAGSに-LTCGのおまけを付けて、configure + nmake。
minirubyの生成まで順調に来たので、そのまま何事もなく終わるかと思ったんだけど、そうは問屋が卸さなかった。ext/encライブラリの生成に失敗してしまう。どうも、またmkexports.rbが変なlibを生成しているのか、シンボルの参照解決で死んでいるようだった。
仕方ないので手動でdumpbinしたところ、何故かシンボルが出てこない。objに対してdumpbinしてみると、File Type: ANONYMOUS OBJECTの文字が。通りでシンボルが抽出出来ないわけだ。
しかし、GL/LTCGオプションでリンク時コード生成静的ライブラリを生成すると、dumpbinでシンボルを抽出することは出来ません、とはどこにも書いて……

/GL コンパイラ オプションで生成したファイルで使用できるのは、/HEADERS DUMPBIN オプションだけです。

DUMPBIN リファレンス

……あるし!
どうやら、/linkermemberオプションが辛うじて通るようなので、此奴の出力を加工してdefを作ることにした。
まずは、(汗と涙の結晶(?)で出来上がった)次のコマンドで、重要そうなシンボルを抽出。

dumpbin /linkermember msvcr90-ruby191-static.lib | findstr /R /C:"\s_[^?]*$" > ruby191-sym.lst

次に、出来たファイルを開いて、先頭からシンボル先頭の_までを正規表現置換等で消去。FOR構文マジックでも問題なさそうかも知れない。
最後に、mkexports.rbが以下のように、シンボルリストにおまけ付けてるので、これらを模倣する。

    syms["NtInitialize"] ||= "ruby_sysinit" if syms["ruby_sysinit"]
    syms["rb_w32_vsnprintf"] ||= "vsnprintf"
    syms["rb_w32_snprintf"] ||= "snprintf"
    yield "strcasecmp", "msvcrt.stricmp"
    yield "strncasecmp", "msvcrt.strnicmp"

ただ、これだと意図しないシンボルまでlibに含まれてしまうのがやな感じだなぁ。
とりあえず、これでビルドは通……らない?

   ライブラリ dummy.lib とオブジェクト dummy.exp を作成中
dummy.exp : error LNK2001: 外部シンボル "DllMain@12" は未解決です。
dummy.exp : error LNK2001: 外部シンボル "rb_w32_Sleep@4" は未解決です。
dummy.exp : error LNK2001: 外部シンボル "rb_w32_accept@12" は未解決です。
dummy.exp : error LNK2001: 外部シンボル "rb_w32_bind@12" は未解決です。
dummy.exp : error LNK2001: 外部シンボル "rb_w32_connect@12" は未解決です。
dummy.exp : error LNK2001: 外部シンボル "rb_w32_gethostbyaddr@12" は未解決です。
(snip)

どうも、stdcall組のシンボルが、しっぽ_を削ったばかりに未解決になっているようだ。実体をこんな感じに_付きで示してやると上手く納まった。

DllMain@12 = _DllMain@12
rb_w32_Sleep@4 = _rb_w32_Sleep@4
(snip)
>ruby --version
ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-mswin32_90]

>

その後……

WEBRickがまともに動かなかった。CPU100%占有で応答無しとは……