Reputation: 875
I've got a problem with a Makefile, it just compiles many time the same file.
Here are my files:
$ ls *
carnet.data carnet.l carnet.y Makefile
struct:
carnet.c carnet.h ihm.c ihm.h struct.c struct.h
Here is my Makefile:
CC = gcc
LEX = lex
YACC = yacc
FLAGS = -Wall -Wextra -Werror -O3 -g
ELIB = -lfl # Flex library
TARGET = carnet
SRC = $(shell find struct/ -name "*.c")
OBJ = $(SRC:.c=.o)
SRCL = $(shell find -name "*.l")
OBJL = lex.yy.o
SRCY = $(shell find -name "*.y")
OBJY = y.tab.o
all : $(TARGET)
$(TARGET) : $(OBJ) $(OBJY) $(OBJL)
@echo "Linking"
@echo $(SRC)
@echo $(OBJ)
@$(CC) $^ -o $@ $(FLAGS) $(ELIB)
$(OBJY) : $(SRCY)
@echo $<
@$(YACC) -d $<
@$(CC) -c y.tab.c -o $@
$(OBJL) : $(SRCL)
@echo $<
@$(LEX) $<
@$(CC) -c lex.yy.c -o $@
$(OBJ) : $(SRC)
@echo $<
$(CC) -c $< -o $@ $(FLAGS)
clean :
rm y.tab.c $(OBJY) y.tab.h lex.yy.c $(OBJL)
rm $(OBJ)
destroy :
rm $(TARGET)
rebuilt : destroy mrpropper
mrpropper : all clean
And here is the output when I do a 'make':
struct/struct.c
gcc -c struct/struct.c -o struct/struct.o -Wall -Wextra -Werror -O3 -g
struct/struct.c
gcc -c struct/struct.c -o struct/carnet.o -Wall -Wextra -Werror -O3 -g
struct/struct.c
gcc -c struct/struct.c -o struct/ihm.o -Wall -Wextra -Werror -O3 -g
carnet.y
carnet.l
Linking
struct/struct.c struct/carnet.c struct/ihm.c
struct/struct.o struct/carnet.o struct/ihm.o
As we can see, when I do a 'echo $(SRC)' he finds all three files, but he only compiles the 'struct.c' file, and I don't understand why !
Thanks for your help, Phantom
Upvotes: 1
Views: 70
Reputation:
SRC = $(shell find struct/ -name "*.c")
You create a list here, $(SRC)
will be struct/struct.c struct/carnet.c struct/ihm.c
. Or any other order find
may return, but according to your result, this seems to be the order.
OBJ = $(SRC:.c=.o)
This creates the modified list struct/struct.o struct/carnet.o struct/ihm.o
$(OBJ) : $(SRC)
@echo $<
$(CC) -c $< -o $@ $(FLAGS)
Here we go, (partial, for clarity) expansion leads to
struct/struct.o struct/carnet.o struct/ihm.o : struct/struct.c struct/carnet.c struct/ihm.c
@echo $<
$(CC) -c $< -o $@ $(FLAGS)
So you have a rule applied for building 3 targets, fine. Now, $<
expands to the first prerequisite, which is struct/struct.c
here.
One possible (and common) solution if you use a make
capable of it, e.g. GNU make, is to use pattern rules instead of this find
-hack:
struct/%.o : struct/%.c
@echo $<
$(CC) -c $< -o $@ $(FLAGS)
Note that normally, you just maintain ONE list of the modules of your taget in your Makefile
, usually the object files, manually, like here:
OBJS:= struct/struct.o struct/carnet.o struct/ihm.o
Upvotes: 2