#c #makefile #bison #flex-lexer #yacc
Вопрос:
Привет, у меня есть файл makefile, такой как этот:
# Variables ===================================================================================== PHONY = proj = ALL_FILES := $(filter $(proj).%,$(shell ls | grep "^$(proj).[a-z]*$")) LEX_FILE := $(filter %.l, $(ALL_FILES)) BISON_FILE := $(filter %.y, $(ALL_FILES)) C_FILE := $(filter %.c, $(ALL_FILES)) H_FILE := $(filter %.h, $(ALL_FILES)) BISON_OUT_H := $(subst .y,.tab.h,$(BISON_FILE)) BISON_OUT_C := $(subst .y,.tab.c,$(BISON_FILE)) BISON_OUT := $(BISON_OUT_C) $(BISON_OUT_H) LEX_OUT := $(subst .l,.yy.c,$(LEX_FILE)) LEX_TRG := $(LEX_FILE) LEX_DEP := $(LEX_FILE) $(BISON_OUT_H) GCC_TRG := $(BISON_OUT_C) $(LEX_OUT) $(C_FILE) GCC_DEP := $(GCC_TRG) $(H_FILE) $(BISON_OUT_H) CFLAGS = -g test: @echo $(proj) @echo $(ALL_FILES) @echo $(LEX_FILE) @echo $(BISON_FILE) @echo $(C_FILE) @echo $(BISON_OUT_C) @echo $(LEX_OUT) @echo $(GCC_TRG) @echo $(GCC_DEP) # Flex ========================================================================================== $(LEX_OUT):$(LEX_DEP) ifneq (,$(LEX_TRG)) flex --outfile=$@ $(LEX_TRG) endif # Bison ========================================================================================= $(BISON_OUT):$(BISON_FILE) ifneq (,$(BISON_FILE)) bison -d
lt;
endif# Run ===========================================================================================
$(proj).out:$(GCC_DEP)
ifneq (,$(GCC_TRG))
gcc $(CFLAGS) $(GCC_TRG) -o $@
endifrun:$(proj).out
./lt;
run_lex:$(proj).out
@echo "Please type in file names: ";
read file;
./lt; $file
PHONY = run run_wc run_lex
# Clean =========================================================================================
clean:
-rm *.out *.lex *.yy.c *.tab.h *.tab.c *.s
cleansp:
-rm $(proj).out $(proj).lex $(BISON_OUT) $(LEX_OUT)PHONY = clean cleansp
# GitHub ========================================================================================
commit: clean
git add -A
@echo "Please type in commit comment: ";
read comment;
git commit -m"$comment"
sync: commit
git push -u origin masterPHONY = commit sync
# PHONY =========================================================================================
.PHONY: $(PHONY)
В текущей папке у меня есть[shore@shore-82b6 flex-bison]$ ls calc2.c calc2.h calc2.l calc2.tab.c calc2.tab.h calc2.y calc2.yy.c calc.l calc.y ccr.l lc.l makefile Note.md samples st.l wc.l
Дело в том , что меня смущает то, что когда я запускаюсь
make run proj=calc2
, если что-то изменитсяcalc.y
, то файл make будет запускать дополнительные инструкции и выводитьcalc.c
в результате. Ниже приведен вывод оболочки:[shore@shore-82b6 flex-bison]$ make run proj=calc2 bison -d calc2.y flex --outfile=calc2.yy.c calc2.l yacc calc2.y mv -f y.tab.c calc2.c calc2.yy.c calc2.tab.c calc2.c
Обратите внимание, что это произойдет только в том случае, если
calc.y
будет изменено.Итак, как я должен это исправить и позволить файлу создания выполнять инструкции, которые, как предполагается, находятся в моем файле создания.
Ответ №1:
Вас укусило одно из встроенных правил make:
%.c: %.y # recipe to execute (built-in): $(YACC.y)
lt;
mv -f y.tab.c $@
Здесь говорится: «Если у меня есть файлfoo.y
, и я хочу создать файлfoo.c
, вот как это сделать». Это обычное соглашение об именах для создания файлов yacc.В вашей ситуации у вас есть файл
calc2.y
, который является файлом yacc, и другой файлcalc2.c
, который является обычным исходным файлом, но make не знает, что это обычный исходный файл.Если вы хотите , чтобы ваше
calc2.y
не было связано с вашимcalc2.c
, а вместоcalc2.y
этого было связано только сcalc2.tab.c
вами, вам придется отменить встроенное правило, объявив его без какого-либо рецепта, подобного этому:%.c: %.y