Makefile 自动调用 `yacc`

Makefile automatically call `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 $<
endif

# Run ===========================================================================================
$(proj).out:$(GCC_DEP)
ifneq (,$(GCC_TRG))
    gcc $(CFLAGS) $(GCC_TRG) -o $@
endif

run:$(proj).out
    ./$<

run_lex:$(proj).out
    @echo "Please type in file names: "; \
    read file; \
    ./$< $$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 结果。以下是 shell 输出:

[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 发生变化时才会发生这种情况。

那么我应该如何解决这个问题并让 makefile 运行 指令假设在我的 makefile 中。

您被 make 的内置规则之一所困扰:

%.c: %.y
#  recipe to execute (built-in):
         $(YACC.y) $<
         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