Safaci
Safaci

Reputation: 139

Makefile: nothing to be done

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

Answers (2)

Tom Tanner
Tom Tanner

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

Vikas R
Vikas R

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

Related Questions