<targets>: <pattern>: <dependencies>
<commands>
-例えば、以下のルールではファイル `` a.o`` と ``b.o`` のみにルールを適用しています。 ::
+例えば、以下のルールではファイル ``a.o`` と ``b.o`` のみにルールを適用しています。 ::
a.o b.o: %.o: %.c
$(CC) $(CFLAGS) -DSPECIAL -c $*.c
8.3 セクション
----------------------------------
+ルールの内容に書かれているコマンドはシェルによって頻繁に評価されます。omakeはまた、omake自身も評価の対象に加えることもできます。
+
+これらの「ファイルを作るためのルール」を表現するためには ``section`` 表現を使います。以下のルールではターゲットの ``hello.c`` を生成するためにomakeのIO関数を用いています。 ::
+
+ hello.c:
+ section
+ FP = fopen(hello.c, w)
+ fprintln($(FP), $""#include <stdio.h> int main() { printf("Hello world\n"); }"")
+ close($(FP))
+
+この例では出力するテキストをクオートするために、クオーテーション ``$""...""`` を用いています(詳細はB.1.6のセクションを参照してください)。これらのクオートは出力されたファイルには含まれていません。 ``fopen`` , ``fprintln`` , ``close`` 関数はIOセクションで評価するようにファイルのIOを実行します。
+
+加えて、関数の呼び出しや他の特殊なコマンドはその場で正しく評価されます。また、 ``fprintln`` 関数はファイルを直接出力することもできるので、上のルールは下のような形に省略できます。 ::
+
+ hello.c:
+ fprintln($@, $""#include <stdio.h> int main() { printf("Hello world\n"); }"")
.. _label8.4:
8.4 セクションルール
----------------------------------
+また、ターゲットの依存関係がルールの内容で記述されるような場合、 ``section rule`` を使うことで計算することができます。以下のルールでは、ファイル ``a.c`` が存在していた場合は内容を ``hello.c`` にコピーし、そうでなければ ``hello.c`` は ``default.c`` から生成されます。 ::
+
+ hello.c:
+ section rule
+ if $(target-exists a.c)
+ hello.c: a.c
+ cat a.c > hello.c
+ else
+ hello.c: default.c
+ cp default.c hello.c
.. _label8.5:
8.5.1 :exists:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+時々、依存しているファイルの内容ではなく、ファイルが存在しているのかどうかが重要となる場合もあるでしょう。 ``:exists:`` 修飾子はこのような依存関係を指定したい場合に用いられます。 ::
+
+ foo.c: a.c :exists: .flag
+ if $(test -e .flag)
+ $(CP) a.c $@
.. _label8.5.2:
8.5.2 :effects:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+コマンドの中にはおまけとして別のファイルを生み出すものもあるでしょう。例えば、 ``latex(1)`` コマンドは ``.dvi`` ファイルを生成する際、おまけとして ``.aux`` ファイルを生成します。このような場合、 ``:effects:`` 修飾子はこのようなおまけファイルを明示的に指定したい場合に用いられます。omakeはこのおまけファイルを上書きしないように、平行してプログラムを走らせないようにします。 ::
+
+ paper.dvi: paper.tex :effects: paper.aux
+ latex paper
.. _label8.5.3:
8.5.3 :value:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+``:value:`` 依存関係は、ルールの実行がある式の値に依存していることを指定するために用いられます。例えば、以下のルールを見てください。 ::
+
+ a: b c :value: $(X)
+ ...
+
+上のルールでは、"a"が ``$(X)`` の値が変わった場合に再コンパイルされる必要があることを指定しています(Xがファイル名である必要はありません)。これはファイルや変数の依存関係をより精密にコントロールすることを意図しています。
+
+加えて、これは他の依存関係の代わりに用いることができます。例えば、以下のルールは、その次のルールと等価です。 ::
+
+ a: b :exists: c
+ commands
+
+::
+
+ a: b :value: $(target-exists c)
+ commands
+
+.. note::
+ * 任意の値をとることができます(指定する変数に制限はありません)。
+ * 値はルールが展開されるときに評価されます。なので式には ``$@`` や ``#^`` のような変数も含めることができます。
.. _label8.6:
8.6 .SCANNER ルール
----------------------------------
+スキャナルールでは、自動的に依存関係の解析を行う方法について定義します。 ``.SCANNER`` ルールは以下のような形となります。 ::
+
+ .SCANNER: target: dependencies
+ commands
+
+ルールは、指定されたターゲットのソースファイルに定義されている、追加の依存関係を計算するのに用いられます。``.SCANNER`` コマンドの実行結果は、OMakeのフォーマットで依存関係のシーケンスが標準の出力先に出力される必要があります。例えばGNUシステムでは、 ``gcc -MM foo.c`` はファイル ``foo.c`` の依存関係を生成するコマンドです(これは ``#include`` の情報を元にしています)。
+
+私たちはこれを用いて、 ``.c`` ファイルから ``.o`` ファイルを生成するため、スキャンされた依存関係を既存の依存関係に追加することができます。以下のスキャナではファイルの依存関係を指定しており、仮に ``foo.o`` が指定されたとすると、 ``gcc -MM foo.c`` を走らせることによって依存関係の解析が行われます。さらには、 ``foo.c`` は依存されているので、 ``foo.c`` が変更された場合はいつでもスキャナは再計算されます。 ::
+
+ .SCANNER: %.o: %.c
+ gcc -MM $<
+
+コマンド ``gcc -MM foo.c`` は以下の行を出力するものとします。 ::
+
+ foo.o: foo.h /usr/include/stdio.h
+
+以上から、ファイル ``foo.h`` と ``/usr/include/stdio.h`` は ``foo.o`` に依存しているものと考えられます。これは、もしこれらのファイルのどれか一つが変更された場合、 ``foo.o`` はリビルドされるべきであることを示しています。
+
+これはある程度ですがうまく動きます。この機能の利点の一つとしては、 ``foo.c`` が変更された場合、いつでもスキャナが再解析を行ってくれるというのが挙げられます。しかしながらこれには問題があります。Cの依存関係は *再帰的* なのです。すなわち、もしファイル ``foo.h`` が修正されたとしたら、そのファイルは他のファイルを含んでいることで、さらなる依存関係が生じているのかもしれません。必要なのは ``foo.h`` の変更に応じて、再びスキャナを走らせることです。
+
+私たちはこの問題を「依存関係を示す値(value dependency)」を用いて解決しました。変数 ``$&`` は任意の前回のスキャンから、依存関係の結果を返す変数として定義されています。私たちはこれらの依存関係を、ファイルのMD5による要約を計算して返す ``digest`` 関数を用いて追加しました。 ::
+
+ .SCANNER: %.o: %.c :value: $(digest $&)
+ gcc -MM $<
+
+これで、ファイル ``foo.h`` が変更されたときには要約も変更されているのでスキャナは再計算されます。これは依存関係を示す値( ``$&`` には ``foo.h`` がインクルードされています)によるものです。
+
+ですが、これはまだ完全に正しいというわけではありません。Cコンパイラはインクルードファイルのために *検索パス(search-path)* を使用しているのです。ファイル ``foo.h`` には何通りものバージョンが存在しており、そのうちの選んでいる一つがインクルードパスに依存しているのかもしれません。必要なのは検索パスの依存関係も含めることです。
+
+``$(digest-in-path-optional ...)`` 関数は検索パスを元にした要約を計算し、この問題に解決案を提示します。 ::
+
+ .SCANNER: %.o: %.c :value: $(digest-in-path-optional $(INCLUDES), $&)
+ gcc -MM $(addprefix -I, $(INCLUDES)) $<
+
+スキャナルールの標準出力はOMakeによって捉えられるので、OMakeが依存関係を解析できない内容を含むことは許されません。まだ関連付けられていない依存関係について出力することは許されますが、このような依存関係は無視されます。スキャナルールでは標準エラーの出力先に任意の内容を出力することが許されています。このような出力は通常のルールの出力と同様に扱われます。(言い換えれば、これは --output-… オプションを有効にすることで、ユーザーに見せることのできる出力です。)
+
+``.SCANNER`` ルールについての追加例は ":ref:`label3.4.3`" で見つけることができます。
.. _label8.6.1:
8.6.1 スキャナの命名と :scanner: 依存関係
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+スキャナがルール中で使われていることを明示的に指定するほうが有用である場合があります。例えば、私たちは ``.c`` ファイルを異なったオプションでコンパイルしたり、あるいは(天よ我らを助けて) ``gcc`` と Microsoft Visual C++ コンパイラ ``cl`` の両方を使いたいとしましょう。通常、 ``.SCANNER`` のターゲットは特定のターゲットに結びついてないのですが、私たちはこれを好きなように命名することができます。 ::
+
+ .SCANNER: scan-gcc-%.c: %.c :value: $(digest-in-path-optional $(INCLUDES), $&)
+ gcc -MM $(addprefix -I, $(INCLUDES)) $<
+
+ .SCANNER: scan-cl-%.c: %.c :value: $(digest-in-path-optional $(INCLUDES), $&)
+ cl --scan-dependencies-or-something $(addprefix /I, $(INCLUDES)) $<
+
+次のステップはスキャナの依存関係を明示的に定義することです。 ``:scanner:`` 依存関係はこのために用いられます。この場合、スキャナの依存関係は明示的に指定されます。 ::
+
+ $(GCC_FILES): %.o: %.c :scanner: scan-gcc-%c
+ gcc ...
+
+ $(CL_FILES): %.obj: %.c :scanner: scan-cl-%c
+ cl ...
+
+明示的な ``:scanner:`` スキャナの指定は、単体の ``.SCANNER`` ルールを複数のターゲットに向けて依存関係を生成することにも用いられます。例えば以下の例を見てみましょう。 ::
+
+ .SCANNER: scan-all-c: $(GCC_FILES) :value: $(digest-in-path-optional $(INCLUDES), $&)
+ gcc -MM $(addprefix -I, $(INCLUDES)) $(GCC_FILES)
+
+ $(GCC_FILES): %.o: %.c :scanner: scan-all-c
+ ...
+
+上の例はgccが一回だけ呼び出されるという利点と、一つのソースファイルが変更された場合、すべてのファイルが再スキャンされてしますという欠点の両方を持ち合わせています。
.. _label8.6.2:
8.6.2 ノート
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+多くの場合において、あなたは自分の手でスキャナを定義する必要はありません。OMakeにはC, OCaml, LaTeXファイルのためのスキャナ(しかも暗黙的、明示的に命名されたスキャナの両方)が標準で用意されています。
+
+``SCANNER_MODE`` 変数は、暗黙のスキャナの依存関係の使用についてコントロールする変数です。
+
+明示的に ``:scanner:`` 依存関係を指定することは、スキャナが間違って指定してしまう危険を減らします。巨大で複雑なプロジェクトでは ``SCANNER_MODE`` を ``error`` に設定することで、名前がある ``.SCANNER`` ルールと明示的な ``:scanner:`` 指定を使うようにしましょう。
.. _label8.7: