Next: C Scanners with Bison Parsers, Previous: Appendices, Up: Appendices [Contents][Index]
In this appendix, we provide tips for writing Makefiles to build your scanners.
In a traditional build environment, we say that the .c files are the
sources, and the .o files are the intermediate files. When using
flex
, however, the .l files are the sources, and the generated
.c files (along with the .o files) are the intermediate files.
This requires you to carefully plan your Makefile.
Modern make
programs understand that foo.l is intended to
generate lex.yy.c or foo.c, and will behave
accordingly45. The
following Makefile does not explicitly instruct make
how to build
foo.c from foo.l. Instead, it relies on the implicit rules of the
make
program to build the intermediate file, scan.c:
# Basic Makefile -- relies on implicit rules # Creates "myprogram" from "scan.l" and "myprogram.c" # LEX=flex myprogram: scan.o myprogram.o scan.o: scan.l
For simple cases, the above may be sufficient. For other cases,
you may have to explicitly instruct make
how to build your scanner.
The following is an example of a Makefile containing explicit rules:
# Basic Makefile -- provides explicit rules # Creates "myprogram" from "scan.l" and "myprogram.c" # LEX=flex myprogram: scan.o myprogram.o $(CC) -o $@ $(LDFLAGS) $^ myprogram.o: myprogram.c $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $^ scan.o: scan.c $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $^ scan.c: scan.l $(LEX) $(LFLAGS) -o $@ $^ clean: $(RM) *.o scan.c
Notice in the above example that scan.c is in the clean
target.
This is because we consider the file scan.c to be an intermediate file.
Finally, we provide a realistic example of a flex
scanner used with a
bison
parser6.
There is a tricky problem we have to deal with. Since a flex
scanner
will typically include a header file (e.g., y.tab.h) generated by the
parser, we need to be sure that the header file is generated BEFORE the scanner
is compiled. We handle this case in the following example:
# Makefile example -- scanner and parser. # Creates "myprogram" from "scan.l", "parse.y", and "myprogram.c" # LEX = flex YACC = bison -y YFLAGS = -d objects = scan.o parse.o myprogram.o myprogram: $(objects) scan.o: scan.l parse.c parse.o: parse.y myprogram.o: myprogram.c
In the above example, notice the line,
scan.o: scan.l parse.c
, which lists the file parse.c (the generated parser) as a dependency of
scan.o. We want to ensure that the parser is created before the scanner
is compiled, and the above line seems to do the trick. Feel free to experiment
with your specific implementation of make
.
For more details on writing Makefiles, see The GNU Make Manual.
GNU make
and GNU automake
are two such
programs that provide implicit rules for flex-generated scanners.
GNU automake
may generate code to execute flex in lex-compatible mode, or to stdout. If this is not what you want,
then you should provide an explicit rule in your Makefile.am
This example also applies to yacc parsers.
Next: C Scanners with Bison Parsers, Previous: Appendices, Up: Appendices [Contents][Index]