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.
make programs understand that foo.l is intended to
generate lex.yy.c or foo.c, and will behave
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
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
There is a tricky problem we have to deal with. Since a
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
For more details on writing Makefiles, see The GNU Make Manual.
make and GNU
automake are two such
programs that provide implicit rules for flex-generated scanners.
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.