2013-06-18 3 views
2

Я строю парсер, используя Bison и Flex. Чтобы скомпилировать все, я использую простой make-файл. Однако я не специалист по созданию make-файла. Файл makefile работает, за исключением нескольких вещей:Makefile: ничего не нужно

Изменение исходного кода в файле file.cpp не обнаружено в make-файле. Нечего делать. A make clean устраняет проблему, но это, конечно, не обязательно. Я нашел много учебников по make-файлу, но не обсуждает такие проблемы.

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) 

Конечно, я мог бы использовать make -B all, а потом я обнаружил что-то странное:

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 

Почему bison -d parser.ypp делается в два раза?

[РЕШИТЬ]

настоящее время мы используем следующие 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 "[email protected]" 

%.o: %.cpp 
    $(CC) $(CFLAGS) -c "$<" -o "[email protected]" 

clean: 
    rm -rf $(OBJECTS) $(EXECUTABLE) parser/parser.cpp parser/parser.hpp scanner/scanner.cpp 

ответ

2

Помещенный file.cpp в зависимости для CPP файлов для построения. Это позволит сделать Makefile, чтобы собрать эти два файла, когда и изменить 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) 
+0

Почему именно вы хотите, чтобы lex.yy.c был перестроен в результате изменения файла file.cpp? –

2

Одна из ваших проблем является то, что это

a b: c 
    do something 

в makefile говорит, что:

  • a зависит на c; для его строительства, эксплуатация do something
  • b зависит от c; строить его, запустить do something

не так, как вы могли бы надеяться, что a и b оба построены в результате do something. Поскольку у вас есть как parser.tab.cpp, так и parser.tab.hpp в качестве явных зависимостей (для parser и lex.yy.c соответственно), make будет строить их оба и выполнить ту же команду дважды (что будет весело, если вы попытаетесь построить параллельно).

Если вы можете позволить себе изменить свою систему сборки, вы можете посмотреть на Scons, который делает это немного интуитивно.

Я хотел бы также быть наклонена, чтобы разбить ваш сделайте немного так, чтобы каждый .o был построен самостоятельно, поэтому у вас есть что-то вроде этого:

file.o: file.cpp 
lex.yy.o: lex.yy.c parser.tab.hpp 

parser: lex.yy.o parser.tab.o file.o 

, как это означает, что менее вероятно, чтобы восстановить вещи, которые вы дон Не хотите и, скорее всего, перестроить все, что вам нужно, - вы действительно не хотите перестраивать lex.yy.c, если вы изменили .hpp. Но вы хотите перестроить файл .o

+0

Спасибо за ваш ответ!Теперь ясно, как работает make-файл. Я «перестраиваю» мой makefile, чтобы каждый .o был построен независимо. И вы правы, зачем перестроить каждый .cpp-файл для lex.yy.c? Не нужно! – Safaci

+0

не стесняйтесь пересматривать любые полезные ответы –

Смежные вопросы