lex および yacc は、C ソースファイルを出力します。lex および yacc のソースファイルは、接尾辞がそれぞれ .l、.y になります。lex および yacc のソースファイルを別々にコンパイルする場合のコンパイル処理は、C ソースだけからプログラムを生成する場合と同様です。
lex または yacc のソースを .c ファイルにコンパイルする暗黙の規則があります。.c ファイルは、C ソースからオブジェクトファイルをコンパイルする暗黙の規則を使用してさらに処理されます。ソースファイルに #include 文が含まれていない場合は、.c ファイルは中間ファイルとして使用されるため、保存しておく必要はありません。この場合は、.l.o の規則または .y.o の規則を使用してオブジェクトファイルを生成し、(派生した) .c ファイルを削除できます。
以下にメークファイルの例を示します。
CFLAGS= -O .KEEP_STATE: all: scanner parser scanner: scanner.o parser: parser.o
このメークファイルの結果は、以下のようになります。
$ make -n rm -f scanner.c lex -t scanner.l > scanner.c cc -O -c -o scanner.o scanner.c rm -f scanner.c yacc parser.y cc -O -c -o parser.o y.tab.c rm -f y.tab.c
lex と yacc を組み合わせて使用する場合は、より複雑になります。オブジェクトファイルが正しく機能するには、lex の C コードに yacc が生成したヘッダーが含まれている必要があります。yacc のソースファイルが変更されたときは、lex が生成した C ソースファイルを再コンパイルする必要があります。この場合は、yacc のソースが変更されるごとに lex を実行しなくてもよいように、lex が生成した中間 (.c) ファイルと、yacc が生成した .h ファイルを保存しておきます。
yacc は、y.tab.c と y.tab.h という名前の出力ファイルを生成します。出力ファイルのベース名をソースファイルと同じにしたい場合には、出力ファイルの名前を変更してください。
以下のメークファイルは、lex のソース、yacc のソース、C ソースファイルから構築したプログラムを管理します。
CFLAGS= -O .KEEP_STATE: a2z: c_functions.o scanner.o parser.o cc -o $@ c_functions.o scanner.o parser.o scanner.c: parser.c + parser.h: parser.y yacc -d parser.y mv y.tab.c parser.c mv y.tab.h parser.h
前述のように、複数の暗黙の規則の橋渡しをする規則は生成されないので、scanner.c のターゲットエントリを指定する必要があります。このエントリは、.l.c と .c.o の暗黙の規則の橋渡しをして scanner.o の依存関係リストから scanner.l を生成します。ターゲットエントリには規則がないため、暗黙の規則 .l.c を使用して scanner.c が構築されます。
次のターゲットエントリは、yacc の中間ファイルを生成する方法を指定しています。yacc -d を使用してヘッダーと C ソースファイルの両方を生成する暗黙の規則はないため、これを行う規則を指定するターゲットを記述する必要があります。