OCaml MinGW でがんばる時メモ

Wodi に依存する場合は死ぬまで依存。上手く行かなくなっても泣かない。

Wodi に依存しない場合

  • OCamlWindows ビルドは三種類あり、それぞれ特性が違う。これは Native MinGW での話である。他人の Windows での OCaml の話を聞くときにはまずどの種類か確認してからにしなさい
  • http://d.hatena.ne.jp/camlspotter/20140502/1399024687 トラぶったらこれくらいはできる胆力が無ければ引き返してください
  • Flexdll は OCaml に依存しているんだ!だからまず Flexdll はバイナリで落としてこよう。自分でビルドは一段落してから。
  • 困ったら wodi のレポからパッチを盗む https://github.com/fdopen/godi-repo.git 。そもそも元のソフトのライセンスを考えればパクリは問題ない。ただし、Wodi というか Godi の内部構造とか知っても全く得しないのでパッチもらうだけにしよう
  • OPAM は動かないが、パッケージ情報は上手に利用できる https://opam.ocaml.org/packages/ 。こっからソースと依存情報はすぐ取れるのでかなり楽
  • ほとんどの場合は Oasis の setup.ml を使えばインストールは問題ないはず、だが、 PREFIX だけは cygpath -m を通したものを使ったほうがよいようだ: ocaml setup.ml -configure --prefix `cygpath -m $PREFIX` 。ビルド時の Cygwin側からも実行時の Windows 側からも解釈できる形だから。
  • ML のみのパッケージならこの時点で9割はビルドはできる。パス周りの動作はもちろん知らない。
  • EXE=.exe して Makefile などを手直しする必要がままある
  • oasis で setup.ml を作り直すとそれはそれでハマルような気がするので、できるだけ付属の setup.ml を改竄する感じで
  • ocaml setup.ml -configure や -build などで shell script を呼び出している場合、うまくいかないので Some ("foobar.sh", args) みたいなのを Some ("c:/cygwin/bin/sh.exe", "foobar.sh" :: args) に変更しなければいけない場合がままある (ビルドは Cygwin 側でも ocaml setup.ml から先は Windows 側になるため)
  • \ が潰れている場合は深く考えず、さっさと / に書き換える

OCaml + Mingw bigarray.cma issue

Summary: OCaml+Mingw or Flexlink need to be upgraded for newer cygwin mingw gcc(I dunno which one exactly) so that -static-libgcc can be given to the link of dllXXX.dll.

So far, a tentative fix in OCaml side is to change config/Makefile:

FLEXLINK=flexlink -chain mingw -stack 16777216 -link -static-libgcc



Today I tried to compile OCaml 4.01.0 under Mingw and had a trouble.

I followed the instruction in README.win32 and everyhing was compiled w/o problem. But:

$ ocaml bigarray.cma
Cannot load required shared library dllbigarray.
Reason: C:/ocamlmgw/lib/stublibs\dllbigarray.dll: The specified module could not be found.

even though the dll file exists there.

Windows LoadLibraryEx returns error code 126, module not found, even though the file exists. It happens when its dependent library is not found.

Using DependencyWalker, I found the dll has a strange dependency over libgcc_s_sjlj-1.dll. This dependency is not in dllbigarray.dll in the binary districution of OCaml mingw. So I guess new mingw gcc works a bit differently. By Googling I found that -static-libgcc option should link this file to dll, so the dependency should be gone with the option.

The creation of dll is by flexlink. This can be found as follows:

$ cd otherlibs/bigarray
$ make -f Makefile.nt clean
$ make -f Makefile.nt
i686-w64-mingw32-gcc -O -mms-bitfields -Wall -Wno-unused -I../../byterun  -I../win32unix -DIN_OCAML_BIGARRAY -DCAML_NAME_SPACE -c bigarray_stubs.c
i686-w64-mingw32-gcc -O -mms-bitfields -Wall -Wno-unused -I../../byterun  -I../win32unix -DIN_OCAML_BIGARRAY -DCAML_NAME_SPACE -c mmap_win32.c
../../boot/ocamlrun ../../tools/ocamlmklib -oc bigarray bigarray_stubs.o mmap_win32.o 
../../boot/ocamlrun ../../ocamlc -nostdlib -I ../../stdlib -w s -c -w +33..39 -warn-error A -g -I ../win32unix bigarray.mli
../../boot/ocamlrun ../../ocamlc -nostdlib -I ../../stdlib -w s -c -w +33..39 -warn-error A -g -I ../win32unix bigarray.ml
../../boot/ocamlrun ../../tools/ocamlmklib -o bigarray -oc bigarray -ocamlc '../../boot/ocamlrun ../../ocamlc -nostdlib -I ../../stdlib -w s' -linkall \
         bigarray.cmo 

Ok, ocamlmklib creates the dll. Let's see what it does:

$ ../../boot/ocamlrun ../../tools/ocamlmklib -v -oc bigarray bigarray_stubs.o mmap_win32.o
+ flexlink -chain mingw -stack 16777216 -o .\dllbigarray.dll bigarray_stubs.o mmap_win32.o    
+ rm -f .\libbigarray.a && i686-w64-mingw32-ar rcs  .\libbigarray.a bigarray_stubs.o mmap_win32.o

Aha! Flexlink here. Let's dig more (Note that .\dllbigarray.dll must be escaped):

$ flexlink -v -chain mingw -stack 16777216 -o ".\dllbigarray.dll" bigarray_stubs.o mmap_win32.o    
+ i686-w64-mingw32-gcc -mconsole -shared -Wl,-e_FlexDLLiniter@12  -L.   -o ".\dllbigarray.dll" "C:\cygwin\tmp\dyndll5f2f0b.o" "C:\flexdll\flexdll_initer_mingw.o" "C:\cygwin\tmp\dyndll5853c8.o" "C:\cygwin\tmp\dyndlle17070.o" "C:\cygwin\tmp\flexlink952408.def"

Ok, then what happens if I add -static-libgcc to the linker?

$ flexlink -v -link -static-libgcc -chain mingw -stack 16777216 -o ".\dllbigarray.dll" bigarray_stubs.o mmap_win32.o    
+ i686-w64-mingw32-gcc -mconsole -shared -Wl,-e_FlexDLLiniter@12  -L.   -o ".\dllbigarray.dll" "C:\cygwin\tmp\dyndll5f2f0b.o" "C:\flexdll\flexdll_initer_mingw.o" "C:\cygwin\tmp\dyndll5853c8.o" "C:\cygwin\tmp\dyndlle17070.o" "C:\cygwin\tmp\flexlink952408.def" "-static-libgcc"

Yey! The new dllbigarray.dll has no dependency over libgcc_s_sjlj-1.dll!!

ソウルフル小話: 型付き関数型言語と C++ は同時に使ってはいけない

いやまじで使っちゃいけないです。

三年前こういうことがあったんです。 HaskellC++ を使っているコードなんですが、

  • 突然ビルドができなくなる。さっきまで上手く行っていたのに、意味不明な C++ のエラーがゴボゴボ出てくる。 git status や hg status してもそんなとこ何も触ってない。そもそも C++ なんか触ってねえし、俺触ってたの Haskell だし!
  • 変更を全部元に戻してビルド ⇒ やはり意味不明な C++ のエラー。エラー行数が多すぎて読む気も起きない。俺は C++ 専従じゃねえからこんなもん読めるか

ビルドできたはずのコードに戻して make clean してもビルドエラーが出るわけ。まさに「何もいじってないのに壊れましたぁ」状態。ほら、さすがにプロだから、この台詞は絶対言いたくないんだけど、この台詞でしか説明できない。そのビルドディレクトリをあきらめて別のディレクトリに git clone / hg clone しなおすと…ビルドできる。わけわかんない

で、昨日ね、まさにそういう同僚がいて私に助けを求めましたですよ。「ちょっとわかんねーなー、これは三年位前俺もひっかかって…あきらめた」とか話しながら見ていたんですが、ビルドルートディレクトリで ls すると、なんか変なファイルがあるわけ

$ ls
[String] .... Map Maybe ... String

あれーこれは Haskell の型の名前ですやん。なんでこんなものが…

そこであなたも経験ある型付きの関数型言語プログラマなら必ずやったことがあるはずだと思いますが、型名をコピペしますよな?んで間違って shell にペーストして実行しちゃったことありますよな?

$ Int -> [String]
bash: Int: command not found

したら [String] とかいう空ファイルができてしまいますやん。あーそういうファイルだなやーと思ったし、当然中身空だし、消したの。

したらビルドの問題が綺麗さっぱりなくなった。なんでーーー!

C++STL のヘッダファイルって拡張子なくって string とか list とかなんですねーひどいね!ビルドルートディレクトリを基点に C++ コードをコンパイルしようとすると、どっかで STL の include があって、

#include <string>
#include <list>

とか書いてある。書いてあったらどうなる?ビルドルートに string とか list とかのファイルがあったら読みに行っちゃうんだね!そんなこたぁ起こらない?いや上で見たとおり型付き関数型言語使ってると起こす人いるんだねぇ。んでそれって空のファイルだから、そこではエラーでない訳よ。(変なごみの入ったファイルだったらビルド時のエラーメッセージですぐわかるんだけどね。)後のほーで、多分 STL まわりの意味不明なエラーがゴンゴン出る。え? String だから #include は読み込まないはず?おめぇ、大文字小文字の違い無視する OS で働いたことねえのな。

結論:型付きの関数型言語C++ を組み合わせて開発をしてはいけない。

ってか STL 作った人って頭悪い。おわり。

ちょっと考えた

ビルドルートがなんでインクルードパスに入ってんねんと思ったが、 ROOT/A/B/B.h とかが山ほどあるので、 #include とかのために入ってないと困る。必須。

やっぱり拡張子無しのヘッダファイルなんか作るやつが悪いってことで終わり。

stone 穴堀り

人からこんなテクニックを聞いた。私には必要ないが。

Stone http://www.gcd.org/sengoku/stone/Welcome.ja.html

設定

  • 火壁つきプロキシがある。 proxy:8080 とする。これが何でもかんでもブロックしてつらい、が、アマゾンで買い物できるように https は通すようだ
  • 火壁の外にあなたのマシン hogehoge がある。無難なドメイン名になっている。

あなたのマシン側

stone proxy 443/ssl

https のデフォルトポートに http プロキシを建てる。やってきた入力は ssl decode する。ポートが 443 なのは火壁が妙なポートへの https を認めないからである

あなたのマシンに無難なドメイン名をつけておく。IP アドレスそのままだと火壁が認めないからである。

Port 22 に sshd を走らせておく。(22 である必要は無い。 22 だとアタックされやすいかもしれないから…)

火壁の中

stone localhost:8000/http 10022 "CONNECT hogehoge:22 HTTP/1.0" \
   -- localhost:10443/ssl 8000 \
   -- proxy:8080/http 10443 "CONNECT hogehoge:443 HTTP/1.0"
  • port 8000 は http プロキシになる。通信は ssl encode されるので proxy には中身はわからない。
  • ssh -p 10022 localhost すると hogehoge への sshd に繋がる。これは port 8000 のプロキシを使っているので中身も ssl encode される。もちろん ssh なので通信自体は元から暗号化されているが、 sshプロトコルssl encode されているので proxy には ssh だということさえわからない。

単一化で人間の気持ちが失われるんだ!というサビシイ話

OCaml 演習とかやってひぃひぃ言っている人対象ですぅ。わからない人にはわかるように書いていませんから、「さっぱりわからない」とか呟く前にスルー推奨です

type t = int list list list

let x : t = [[[1]]]
let y = x @ x

コンパイルすると、 x は t だが y の型は int list list list とレポートされる。これが残念だって話。だって明らかに t でしょ?
これはもちろん単一化アルゴリズムの気持ちになれば明らかに、明らかではないのだが…

それに、じゃあ x @ x の型が t としてレポートされるべきかというと、そうではないわな。

type kg = float
type m = float (* メーテル *)
let bmi (w : kg) (h : m) = w /. (h *. h)

としたときに bmi の戻り値が kg (もしくは m) になっていて欲しいですかあなたは?

あなたが単一化アルゴリズムの気持ちになれているかどうかは、

let z = [x] @ [x]

の型が int list list list list ではなく t list としてレポートできるのは何故か、で、なぜそれは bmi の例とちがっておかしさがないか、考えるといいですぅ。

どーしてもこれが嫌なら、

type t = Foo of int list list list

として別の型にせにゃならん、がもちろん (@) はそのままでは使えなくなる。

はっ!今気づいた。ようするに、あれだ。 (@) : 'a list -> 'a list -> 'a list は 'a は全部同じことを保証しているが、三つの 'a list が同じであることを保証していない。(いや、同じ型だよ、でも bmi の例と同じく、人間の気持ち的には同じ意味じゃないかもしれないよね?) だから、人間の気持ちを導入してやればよろしい:

let (@!) : ('a list as 'b) -> 'b -> 'b = (@)
let y = x @! x

はいできました。 y の型は t になるよ。

ようするに、機械の体は人間の気持ちを推論してくれないのだ。メーテル、サビシイね、と鉄郎は思った。

EP (就労許可) カードを無くした時

シンガポールで仕事をしている人や、その家族がパスポートよりいつも肌身離さず持っている率の高いEPやDPカード。そこに記載されている個人識別番号は結構普通にいろんなところで(各種行政書類、電話、ガス、水道、電気の契約、はてはレストランの割引会員登録まで)便利に使ってしまうので、国民背番号とかマイナンバーでいろいろ騒いでいる日本とか見てるとどっちがどーなんだか判らなくなってきますが…

それを日本で無くしてしまいました。 ないとマジ不便だし多分違法なので再発行してもらわないといけません。日本で調べたところ、Google で EP Singapore lost と入れれば出てくる情報ですが、

http://www.mom.gov.sg/foreign-manpower/passes-visas/employment-pass/inform-mom/Pages/Card-Replacement.aspx

これが出てきました

簡単に言うと(もちろん、本文を当たってくださいね!)

  • 無くしてから一週間以内に再発行の手続きをすること
  • 盗まれた場合は警察に届け、その届けを提出
  • 帰国時には旅行者と同じく disembarkment card を機内で貰って記載し、パスポートで入国
  • 入国後、雇い主に無くしたことを告げ、人事辺りに再発行手続きをしてもらう

です。なので、とりあえず落ち着いてくださいね。

旅行中で帰国一週間前に無くした時どうすんねん、とか、盗難時の日本語のポリスレポート翻訳せなあかんのか、とか、そういうの気にする頭のある人は、どうすればいいか自ずから明らかですからそうしてください。

空港で、パスポートと disembarkment card を見せて、EP card なくしちゃった…と言ったら、別の窓口に回されましたが、そこのおっちゃんがめっちゃ親切で、あー別にそのまま入ったらいいのにーと言ってくれ、 disembarkment card には VOID (無効)と書かれた上で特別の出口から出してもらいました。でも多分ゲートではこの人が EP ホルダかどうか、情報出るからそこでカード出さない人って結局特別処理されそうな…、まあこういうの行政の建前と実際の運用の差というか、MOM と入管の縦割りとか、あるような気がします。ま、とにかく、終始ジェントルな対応であったことを記しておきます。

あと、指紋を採られている方は普通にパスポートと親指だけで通過できる改札を使えば問題なく入国できるはずですが…その場合は上のMOMの文書と矛盾した行動になるので、帰国後シンガポールでEPを無くしたことに気づいた!というストーリーにしないと駄目です。折角なんで、黙ってないで窓口で言ってみると横の出口から出られるョ!

なお再発行にはある程度お金がかかります。初回は100SGD、それ以降は300SGDで、まあ懲罰的な意味があるんでしょう。私の場合は今のところ人事から天引きするとは言われていないのですが…

ところで、私の場合、

  • 再発行の手続きを会社が(人事ヘルプ業者を通して) MOM に要請する
  • 再発行カードができる日付が決定される
  • 無くしたことを申し出る書類がやってくるのでそれに必要事項+サイン
  • 人事の判子をその書類に貰う
  • その紙を持って再発行の日に EP office に行く

という順序で進んでいます。無くしましたという申請書類の正式な提出前にもうカードが作られている、この並行感はいいですね!

後日

EP は問題なく再発行されました。受け取るときに次は 300SGD よー、などと言われた。

Note for mercurial-git / hg-git and https access to github

I needed the patch discussed in here: https://groups.google.com/forum/m/#!topic/hg-git/YVvcRH8R8NI

Then

Add ~/.hgrc:

[extensions]
hgext.bookmarks =
hgext.git =

[auth]
xxx.prefix = https://github.com
xxx.username = my_user_name
xxx.password = my_password

Some web documents are old. Ignore them.

xxx can be anything but I use `github'.

Then

$ hg clone git+https://github.com/my_user_name/blahblah.git

Note: Git branches are handled as Hg bookmarks.