Сделайте файл автоматически вызываемым » yacc`

#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 $@
endif

run:$(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 master

PHONY = 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