Scoping of implicit rules + Scoping of .SCANNER rules

OMake のお話。

% ワイルドカードの付いているルールは .SCANNER ルールも含め、global scope では無い! つまり、関数内で % を使ったルールを書いた場合、それは関数内でしか有効にならない! これを知らなかったので、% ワイルドカードのついた .SCANNER ルールを関数内で書いても効いて欲しい場所で効いていなかった!! export を使って外に出してやる必要がある! しかし名前が無いので引数無しの export だから他の名前も露出しちゃう。あららら。

詳しくは、 http://omake.metaprl.org/manual/omake-doc.html#section:implicit-scoping

例:

BYTE_ENABLED=true

InstallRules() =
    .SCANNER: scan-ocaml-%: I_know_the_scanner

I_know_the_scanner:
   println(I know the scanner)
   echo x > $@

.DEFAULT: test

InstallRules()

test: test.cmo
    ocamlc -o $@ $<

.PHONY: clean

clean:
    rm -f $(filter-proper-targets $(ls R, .))

この例は OCaml の依存解析をする前に、 I_know_the_scanner というファイルが必要である、と宣言している*つもり*。実際には I_know_the_scanner ではなくて、例えば CamlP4 のモジュールであるとか、ocamlfind であるとか、コンパイルに必要なツールの名前が来る。 さて、ここでは、% を使っているので、ルールはビルド時には有効ではない。omake test とすると普通に test.ml (空ファイルでもなんでもいい) をコンパイルして終わり。 I_know_the_scanner は作られない。

...

InstallRules() =
    .SCANNER: scan-ocaml-%: I_know_the_scanner
    export

...

InstallRules()

...

.SCANNER のルールの後に export を書くと、ルールが外にも有効になり、 I_know_the_scanner が作成される。もし、 InstallRules() が他の関数内で使われる場合は、さらに呼び出したところで export が必要になる:

...

public.InstallRules() =
    .SCANNER: scan-ocaml-%: I_know_the_scanner
    export

F() =
    InstallRules()
    export

F()

...