Hi I have a makefile like this:
# 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)
In the current folder I have
[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
The thing vary confused me is that when I run make run proj=calc2
, if calc.y
is changed then the make file will run extra instructions and output to calc.c
as a result. The following is the shell output:
[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
Notice this will only happen if calc.y
is changed.
So how should I fix this and letting the makefile run the instructions suppose to be in my makefile.
You are being bitten by one of make's built-in rules:
%.c: %.y
# recipe to execute (built-in):
$(YACC.y) $<
mv -f y.tab.c $@
This says, "if I have a file foo.y
and I want to build a file foo.c
, here's how to do it". This is the normal naming convention for building yacc files.
In your situation you have a file calc2.y
which is the yacc file and another file calc2.c
which is a normal source file, but make doesn't know that it's a normal source file.
If you want to have your calc2.y
not be related to your calc2.c
, and instead have calc2.y
be related only to calc2.tab.c
, you'll have to cancel the built-in rule by declaring it without any recipe like this:
%.c: %.y