Reputation: 139
I'm building a parser using Bison and Flex. To compile everything I use a simple makefile. However, I'm not an expert in creating makefile. The makefile is working, except for a few things:
Changing source code in file.cpp isn't detected by the makefile.
Nothing to be done.
A make clean
fixes the problem, but this should not be necessary of course. I have found a lot of makefile tutorials, but not any discusses this kind of problems.
CC=g++
CFLAGS=-Wall -std=c++11 -ll
EXECUTABLE=parser
OBJS=parser.tab.cpp lex.yy.c
FILES= file.cpp
all: parser
parser.tab.cpp parser.tab.hpp: parser.ypp
bison -d parser.ypp
lex.yy.c: parser.l parser.tab.hpp
flex parser.l
parser: $(OBJS) $(FILES)
$(CC) $(CFLAGS) $(OBJS) $(FILES) -o $(EXECUTABLE)
clean:
rm -rf *o $(EXECUTABLE) $(OBJS)
Of course, I could use make -B all
, and then I have detected something strange:
bison -d parser.ypp
bison -d parser.ypp
flex parser.l
g++ -Wall -std=c++11 -ll parser.tab.cpp lex.yy.c file.cpp -o parser
Why is bison -d parser.ypp
done twice?
[SOLVED]
We use now the following makefile:
CC = g++
CFLAGS = --std=c++0x -O2
SOURCES = $(wildcard */*.cpp *.cpp) parser/parser.cpp
OBJECTS = $(SOURCES:.cpp=.o) scanner/scanner.o parser/parser.o
EXECUTABLE = calculator
all: parser/parser.cpp scanner/scanner.cpp $(EXECUTABLE)
parser/parser.cpp:
cd parser && bison -d -o parser.cpp grammar.ypp && cd ..
scanner/scanner.cpp: parser/parser.hpp
cd scanner && flex -o scanner.cpp lexer.l && cd ..
$(EXECUTABLE): $(OBJECTS)
$(CC) $^ -o "$@"
%.o: %.cpp
$(CC) $(CFLAGS) -c "$<" -o "$@"
clean:
rm -rf $(OBJECTS) $(EXECUTABLE) parser/parser.cpp parser/parser.hpp scanner/scanner.cpp
Upvotes: 2
Views: 2332
Reputation: 9354
One of your problems is that this
a b: c
do something
in a makefile
says that:
a
depends on c
; to build it, run do something
b
depends on c
; to build it, run do something
not, as you might hope, that a
and b
are both built as a result of do something
. As you have both parser.tab.cpp
and parser.tab.hpp
as explicit dependencies (for parser
and lex.yy.c
respectively), make
will build both of them, and run the same command twice (which is going to be fun if you try to build in parallel).
If you can afford to change your build system, you might want to look at Scons which does this a little more intuitively.
I would also be inclined to break up your make a bit so that each .o was built independently, so you have something like this:
file.o: file.cpp
lex.yy.o: lex.yy.c parser.tab.hpp
parser: lex.yy.o parser.tab.o file.o
as that means it's less likely to rebuild things you don't want and more likely to rebuild things you do want - you don't really want to rebuild lex.yy.c if you've changed the .hpp. But you do want to rebuild the .o file
Upvotes: 2
Reputation: 21
Put file.cpp
as dependency for the cpp files to build. This will make the makefile to compile those two files when u change file.cpp
:
CC=g++
CFLAGS=-Wall -std=c++11 -ll
EXECUTABLE=parser
OBJS=parser.tab.cpp lex.yy.c
FILES= file.cpp
all: parser
parser.tab.cpp : parser.ypp $(FILES)
bison -d parser.ypp
lex.yy.c: parser.l parser.tab.hpp $(FILES)
flex parser.l
parser: $(OBJS) $(FILES)
$(CC) $(CFLAGS) $(OBJS) $(FILES) -o $(EXECUTABLE)
clean:
rm -rf *o $(EXECUTABLE) $(OBJS)
Upvotes: 2