Go to Cygwin

ネイティブビルドは死んでも終わらなさそうだったので、仕方なく、Cygwinを狙ってみることに。
そのまま始めてみると、lib9のビルドからずっこける。こ、こいつめ……
とりあえず、lib9で問題となる点と修正は

  • Linuxと同じくstat::st_genがないので、_p9dir.cのst_gen存在確認を修正する
  • Cygwinのsigsetjmp系が特殊なので、p9setjmpマクロをjmp.cで関数化、jmp.cのvoid*キャストを、一時変数はさんでsigjmp_bufに変換するように修正する

これで、lib9とlibbioが通る。
問題はlibmachで、こいつがuname=darwin, linux以外におことわりしてくる。どうやら、`uname`.cをコンパイルするように仕組まれいて、Cygwin向けに新しくコードを書き起こす必要があるようだ。
Cygwinならいけるかと思ったが、ここまでおもしろ可笑しい作りだとは思いもしなかった……

Go to Plan9

最近話題になっているGo。チュートリアルを読んで使ってみたつもりになっていたけど、やはり実際に動くモノを見てみたい。インストールの項目を見てみると、どう見ても*NIXオンリーです、本当にありがとうございました。
しかしWindowsでも使ってみたいわけで、ソースコードをHgリポジトリからcloneして、さらっと眺めてみた。
……はい、なにこのPlan9。lib9, libbio, その他でPlan9APIPOSIX APIでシミュレートして、その上で動く形に見える。
GoはPlan9勢の逆襲だと、とあるお方が仰っていたけど、こういう意味だったのか……違うかも知れないけど。
さて、POSIX APIでシミュレートされているとなると、まずWindowsに勝ち目などない。Cygwinや、SFUと言ったWindows向けPOSIX環境でビルドすれば行けるのかも知れないけど、それだとすごく負けた気がする。やっぱり完璧なネイティブ環境じゃないとね。
しかし、このライブラリ群のビルドをネイティブのビルド環境で通すとなると、大半を一から作り直すハメになりそうだなぁ。
これはどうしようか……

gem版Ruby/SDLインストール

B-LOGは移動しました[www.kitcc.org]にて、SDLRubyバインディングの存在を知った。SDLと言えばゲーム開発を想起させるが、RubySDLなゲーム……ってなかなか面白そうだ。
リンク先ではrubysdl-win32-binでインストールしているが、マシンのruby環境が独自ビルドものなので、rubysdl-gemをダウンロードして、インストール。gem install hogeraする前に、vsvarsall.batでコンパイラ環境を設定する必要があるのが独自ビルドの面倒なところである。だがそれが良い、と言うか、ライブラリをソースからビルド出来るから、この道を選んだわけなので、面倒も減ったくれもない。
どうもbinとgemではバイナリのインストールプロセスが違うようで、インストールスクリプトがzlibにやんちゃする出来事もなく、穏やかにインストールが終わった。
時間が余ったら、少し触ってみることにしようか。

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

おそらく最初のX509_EXTENSIONSトラブルで、singleがあろうがなかろうがエラー落ちして、singleなんてなかったという間違いを犯していたと考えられる。そのトラブルを修正してもextconf.hは変わらないので、有りもしないsetメンバーを参照して死んでいたわけだ。
とりあえず、ビルドは無事完了、WEBrick死亡もなかったことになってくれた。

>ruby --version
ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-mswin32_90]

>ruby webrick_teset.rb
[2009-11-06 03:07:40] INFO  WEBrick 1.3.1
[2009-11-06 03:07:40] INFO  ruby 1.9.1 (2009-07-16) [i386-mswin32_90]
[2009-11-06 03:07:40] INFO  WEBrick::HTTPServer#start: pid=2264 port=81
[2009-11-06 03:07:52] INFO  going to shutdown ...
[2009-11-06 03:07:52] INFO  WEBrick::HTTPServer#start done.

>

これにて一件落着。

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

ruby 1.9.1-p243 @ Visual C++ 2008 -落とし穴 GL/LTCG Edition は本当に落とし穴で泣かされたが、そのままGL/LTCG無しで通すのも癪だし、再チャレンジ枠を設けることにした。
まず始めに、GL/LTCGなしで configure + nmake。msvcr90-ruby-191.libが出来た辺りでCtrl+Cで強制終了する。こうすることで、清く正しいsh……じゃない、清く正しいdef/libを回収する。
次に、-GL/LTCG + configure + nmakeで、encのビルドで死ぬまで流す。

(snip)
   ライブラリ enc/encdb.lib とオブジェクト enc/encdb.exp を作成中
encdb.obj : error LNK2001: 外部シンボル "_rb_encdb_dummy" は未解決です。
encdb.obj : error LNK2001: 外部シンボル "_rb_encdb_replicate" は未解決です。
encdb.obj : error LNK2001: 外部シンボル "_rb_encdb_alias" は未解決です。
encdb.obj : error LNK2001: 外部シンボル "_rb_encdb_declare" は未解決です。
.ext/i386-mswin32_90/enc/encdb.so : fatal error LNK1120: 外部参照 4 が未解決です。
NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\cl.EXE"' : リターン コード '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\nmake.EXE"' : リターン コード '0x2'
Stop.

そして、回収したdef, libを適用してnmake。タイムスタンプを更新しておかないと死ぬハメになる。

そして

OpenSSLモジュールのコンパイルではまった。
問題はOpenSSL 使用トラブル - BiBoLoGらしいので、さくっと修正してやったが、Ruby1.9 上のopensslライブラリがビルドできない。 - サイログ。MiyakoとかRubyとかなんとか+Miyako ACCESS MAPまで派生してくれた、なんてことだ……。
少々調べてみると、事は簡単で、

/* +++ ossl_x509attr.c (164- +++ */
#if defined(HAVE_ST_X509_ATTRIBUTE_SINGLE) || defined(HAVE_ST_SINGLE)  // x509_attributes_st.singleがあるかどうかで切り替えていて
#  define OSSL_X509ATTR_IS_SINGLE(attr)  ((attr)->single)
#  define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->single = 1)
#else
#  define OSSL_X509ATTR_IS_SINGLE(attr)  (!(attr)->set)
#  define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->set = 0)
#endif

で、

/* +++ x509.h (213- +++ */

/* a sequence of these are used */
typedef struct x509_attributes_st
	{
	ASN1_OBJECT *object;
	int single; /* 0 for a set, 1 for a single item (which is wrong) */  // ← x509_attributes_st.singleがあるのに
	union	{
		char		*ptr;
/* 0 */		STACK_OF(ASN1_TYPE) *set;   
/* 1 */		ASN1_TYPE	*single;
		} value;
	} X509_ATTRIBUTE;
/* extconf.h */

#ifndef EXTCONF_H
#define EXTCONF_H
#define HAVE_ASSERT_H 1
#define HAVE_OPENSSL_SSL_H 1
#define HAVE_OPENSSL_CONF_API_H 1
#define HAVE_RB_STR_SET_LEN 1
#define HAVE_RB_BLOCK_CALL 1
#define HAVE_ERR_PEEK_LAST_ERROR 1
#define HAVE_BN_MOD_ADD 1
#define HAVE_BN_MOD_SQR 1
#define HAVE_BN_MOD_SUB 1
#define HAVE_BN_PSEUDO_RAND_RANGE 1
#define HAVE_BN_RAND_RANGE 1
#define HAVE_CONF_GET1_DEFAULT_CONFIG_FILE 1
#define HAVE_EVP_CIPHER_CTX_SET_PADDING 1
#define HAVE_EVP_CIPHERFINAL_EX 1
#define HAVE_EVP_CIPHERINIT_EX 1
#define HAVE_EVP_DIGESTFINAL_EX 1
#define HAVE_EVP_DIGESTINIT_EX 1
#define HAVE_EVP_MD_CTX_CLEANUP 1
#define HAVE_EVP_MD_CTX_CREATE 1
#define HAVE_EVP_MD_CTX_DESTROY 1
#define HAVE_EVP_MD_CTX_INIT 1
#define HAVE_HMAC_CTX_CLEANUP 1
#define HAVE_HMAC_CTX_INIT 1
#define HAVE_PEM_DEF_CALLBACK 1
#define HAVE_PKCS5_PBKDF2_HMAC_SHA1 1
#define HAVE_X509V3_SET_NCONF 1
#define HAVE_X509V3_EXT_NCONF_NID 1
#define HAVE_X509_CRL_ADD0_REVOKED 1
#define HAVE_X509_CRL_SET_ISSUER_NAME 1
#define HAVE_X509_CRL_SET_VERSION 1
#define HAVE_X509_CRL_SORT 1
#define HAVE_OBJ_NAME_DO_ALL_SORTED 1
#define HAVE_SSL_SESSION_GET_ID 1
#define HAVE_OPENSSL_CLEANSE 1
#define HAVE_VA_ARGS_MACRO 1
#define HAVE_OPENSSL_ENGINE_H 1
#define HAVE_ENGINE_ADD 1
#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1
#define HAVE_ENGINE_GET_DIGEST 1
#define HAVE_ENGINE_GET_CIPHER 1
#define HAVE_ENGINE_CLEANUP 1
#define HAVE_OPENSSL_OCSP_H 1
#endif
// HAVE_ST_X509_ATTRIBUTE_SINGLE がない!

と言う理由だった。まったく……

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%占有で応答無しとは……

array_filterで配列要素のインデックスが歯抜けになる

急遽、rubyで言うArray#selectをphpで実現する必要が出てきた。
さらさらっと調べてみると、PHP Manualにarray_filterなる、そのものズバリな関数を見つけることが出来た。
しかし、サンプルを観てみると、どうも評価値に違和感が。

$array2 = array(6, 7, 8, 9, 10, 11, 12);

に対して、偶数フィルタを通した評価値が、

Array
(
    [0] => 6
    [2] => 8
    [4] => 10
    [6] => 12
)

となっている。インデックスを見てみると、除外された部分が歯抜けになって返ってきている。print_rの表示からして、まさかphpの配列は全て連想配列なのか……?
要求上、こんな歯抜け配列は許されないので、何としても詰めた配列が欲しい。
とりあえず、マニュアルについたコメントを読み進めていくと、

You can easily reassign indexes like this:

http://www.php.net/manual/ja/function.array-filter.php#80219

そうそう、求めていたのはこれだよ、これ!
と言うか、マニュアルにそういう頻出しそうなノウハウは反映させようよ。ググっても、日本語資料では出てくる様子がないし……