Here is the relevant part of my Makefile.
...
LIBS = gc ft
vpath %.a $(LIBS:%=lib%)
all:
$(MAKE) $(NAME)
$(NAME): $(LIBS:%=lib%.a) $(OBJS) | libs
$(CC) $(CFLAGS) $(OBJS) -o $(NAME) $(LDFLAGS)
-include $(DEPENDENCIES)
$(OBJS_DIR)/%.o: %.c $(OBJS_DIR)/debug$(DEBUG) | $(OBJS_DIR)
$(CC) $(CFLAGS) $(INCLUDES_DIR:%=-I %) -c $< -o $@
$(OBJS_DIR):
$(MKDIR) $@
libs: $(LIBS:%=lib%.a)
$(foreach LIB, ${LIBS}, ${MAKE} -C lib${LIB} ;)
lib%.a:
$(MAKE) -C $(@:%.a=%)
...
My problem is that, whenever I touch a file in one of my libs, make recompile that lib, but I have to run make a second time to make it relink the object files.
What am I doing wrong ?
Thanks in advance.
---EDIT---
So now my Makefile looks like this.
...
all: $(NAME)
$(NAME): $(OBJS) libft/libft.a libgc/libgc.a
$(CC) $(CFLAGS) $(OBJS) -o $(NAME) $(LDFLAGS)
-include $(DEPENDENCIES)
$(OBJS_DIR)/%.o: %.c $(OBJS_DIR)/debug$(DEBUG) | $(OBJS_DIR)
$(CC) $(CFLAGS) $(INCLUDES_DIR:%=-I %) -c $< -o $@
$(OBJS_DIR):
$(MKDIR) $@
libft/libft.a:
$(MAKE) -C libft
libgc/libgc.a:
$(MAKE) -C libgc
...
It does not relink anymore but if change some file in the sources of my libs, it does not recompile either.
You cannot use vpath to find generated files. It can only be used to locate source files (that always exist). See http://make.mad-scientist.net/papers/how-not-to-use-vpath/ for details.
You need to use the real path of the libraries generated as prerequisites, so that when make checks their modification time it knows they've changed.
ETA
You are using a recursive make model for building. That means that this makefile doesn't know whether your libraries are out of date or not: here you don't list any prerequisites for them, so as far as make is concerned if they exist, they are up to date.
Instead, you've relegated the knowledge of whether the libraries are up to date into the subdirectory makefiles. That means that in order to know if they're up to date, you have to run that sub-make so it can check. That means you ALWAYS want to run the sub-make, which will only update the libraries if they're out of date. A simple way to do this is using a
FORCEtarget: