Arantium Maestum

プログラミング、囲碁、読書の話題

TaPLの公式実装をduneでビルドする時にハマったこと

非常に限定された一部界隈では非常に有名なことで有名なTypes and Programming Languagesの公式サイトから、本に出てくる型システムの実装がダウンロードできる:

www.cis.upenn.edu

以前も気になった部分を落として実装を覗いてみたりはしたのだが、コンパイルして走らせてみたりはしなかった。

最近個人的な型システム熱が強まってきたので、自分でも実装してみようと思ってまずは公式実装をコンパイルして使ってみることにした。

公式はocamlcを使ったMakefileを提供しているが、私は自分のコードはいつもduneでコンパイルしているのでとりあえずそっちを使ってみることにした。

見たところocamllex/menhir以外では依存するライブラリもないようだし・・・というわけでこんなduneファイルを用意:

(menhir
  (modules parser))

(ocamllex lexer)

(executable
  (name main))

dune build ./main.exeとやってみたところ、コンパイルエラー。

「昔のコードだろうからね、最近のocamlcでコンパイルできなくても仕方ないね」と思いつつmakeを走らせてみると普通にコンパイルできてしまった。

Makefileの中身を覗いてみるとOCaml 4.02以降はコンパイラフラグとして-unsafe-stringを渡しているようだ。これで「StringじゃなくてByteだよ」といったエラーは消えるのだが、それでもduneのほうは大量にエラーが出る。主に使われていない変数、openされたモジュール、非再帰的なlet rec関数定義などについてのようだ。

Makefileではこれらに対して特にフラグを渡しているようでもないのだが、仕方なく手動で黙らせていく:

(menhir
  (modules parser))

(ocamllex lexer)

(env
  (dev
    (flags (:standard -w -3 -w -27 -w -32 -w -33 -w -34 -w -39 -unsafe-string))))

(executable
  (name main))

ちなみにこれは-w -3-27-32-33-34-39のように書けるようだ。

しかし

と不思議に思っていたところ:

と教えていただいた。

dune makes all warnings fatal by default. This can be a challenge when porting a codebase to dune.

というところだ。

dune build --profile release ./main.exeとするとwarningでコンパイルが止まらないらしいが、実際にはdev目的のビルドなのにreleaseフラグを使うのもなんだし、ということで

(menhir
  (modules parser))

(ocamllex lexer)

(env
  (dev
    (flags (:standard -unsafe-string  -warn-error -A))))

(executable
  (name main))

こういうduneファイルでwarningがエラーにならないように設定する。

これで(山のようにwarningは出るが)ちゃんとコンパイルできる。

arith$ ./_build/default/main.exe test.f 
true
false
0
1
false

実行もちゃんとできた。めでたしめでたし。@dico_lequeさんありがとうございます!