/ / Makefile: нічого не потрібно робити - c ++, c, makefile, bison, flex-lexer

Makefile: нічого робити - c + +, c, makefile, bison, flex-lexer

Я будую парсер, використовуючи Bison і Flex. Щоб скомпілювати все, я використовую простий файл makefile. Файл makefile працює, за винятком декількох речей:

Зміна вихідного коду у файлі file.cpp не виявляється за допомогою makefile. Нічого не можна зробити. А. make clean вирішує проблему, але це, звичайно, не обов'язково. Я знайшов багато підручників makefile, але не будь-який обговорює такі проблеми.

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 "$@"

%.o: %.cpp
$(CC) $(CFLAGS) -c "$<" -o "$@"

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

Відповіді:

2 для відповіді № 1

Покласти file.cpp як залежність для збирання файлів cpp. Це зробить файл make для компіляції цих двох файлів при зміні u 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)

2 для відповіді № 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 будуватиме обидва з них і двічі запускати ту ж команду (це буде цікаво, якщо ви намагаєтеся побудувати паралельно).

Якщо ви можете дозволити собі змінити систему збирання, ви можете подивитися на Сплани що робить це трохи більш інтуїтивно.

Я також хотів би трохи розбити вашу марку, щоб кожен .o був побудований незалежно, так що ви маєте щось подібне:

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

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

тому що це означає, що він менш схильний до відновлення речейви не хочете і більше ймовірно, щоб відновити речі, які ви хочете - ви дійсно не хочете, щоб відновити.