'How to avoid my makefile to relink
My Makefile is relinking and I can't find why.
I'm not sure why malloc assume that $(NAME) have to be executed. Is the $(SRC:.c=.o) macro changing the timestamps of the .o files or something like that ?
CC = gcc
NAME = app
#
CFLAGS = -Wall -Werror -Wextra -pedantic -pedantic-errors
INCLUDES = -I ./includes
#
DIRSRC = srcs/
DIROBJ = objs/
SRC += main.c
SRC += malloc.c
OBJ = $(SRC:.c=.o)
DIROBJS = $(addprefix $(DIROBJ), $(OBJ))
#
LIBS_PATH = ./libs
LIBFT_PATH = $(LIBS_PATH)/libft
LIBFT_INCLUDES = -I $(LIBFT_PATH)
LIBFT = -L $(LIBFT_PATH) -lft
#
COMPILE = $(CC) $(CFLAGS) $(INCLUDES)
#
all: $(NAME)
$(NAME): configure libs $(DIROBJS)
$(COMPILE) $(LIBFT) $(DIROBJS) -o $(NAME)
$(DIROBJ)%.o: $(DIRSRC)%.c
@echo Compiling: $<
$(COMPILE) $(LIBS_INCLUDES) -c $< -o $@
clean:
@rm -rf $(DIROBJ)
fclean: clean
@rm -rf $(NAME)
re: fclean all
#
configure:
@mkdir -p $(DIROBJ)
#
libs:
@$(MAKE) -C $(LIBS)
.PHONY: all configure clean fclean re libs cleanlibs fcleanlibs relibs
Solution 1:[1]
It always relink because the configure rule will always run. So Make believes one of the dependencies changed, and it reevaluates the rule.
The way I would solve this would be to get rid of the configure rule and to move the @mkdir -p $(DIROBJS) in the rule that builds your object files:
$(DIROBJ)%.o: $(DIRSRC)%.c
@mkdir -p $(DIROBJS)
@echo Compiling: $<
$(COMPILE) $(LIBS_INCLUDES) -c $< -o $@
There might be more reasons (that could be related to the library you're also building), I don't know. Let us know if this solves it entirely.
Solution 2:[2]
@rtur's answer works, however I should mention another alternative. You could do:
$(DIROBJ):
mkdir $@
$(DIROBJ)/%.o: $(DIRSRC)/%.c | $(DIROBJ)
@echo Compiling: $<
$(COMPILE) $(LIBS_INCLUDES) -c $< -o $@
That way, it only makes the directory if it doesn't already exist. One thing to notice is the | symbol. This makes $(DIROBJ) an order-only prerequisite. This means if it's newer than the target, it will not cause the the target to rebuild. This is really important for directories, as the timestamp of a directory is the date the last item in it was added/deleted/modified, and your target would always be out of date without that symbol. This is considered cleaner, as you have less invocations of mkdir this way.
Also, as a style note, you usually, you don't include the trailing / at the end of directory names. $(OBJ_DIR)/%.o looks nicer than $(OBJ_DIR)%.o. Of course, that could just be my opinion :-)
Solution 3:[3]
I'm 42 network student. I had this problem quite often as well.
Moving the .o files into a folder usually causes the Makefile to relink since that directory is not a 'dependency'. Here's an example:
NAME = lib.a
INC = lib.h
FLAGS = -Wall -Wextra -Werror
LIB = function1.c function2.c function3.c function4.c
OBJ = $(SRC:%.c=%.o)
all: $(NAME) clear
$(NAME): $(OBJ)
@$(AR) rcs $@ $^
@ranlib $(NAME)
%.o: %.c
@$(CC) $(FLAGS) -I $(INC) -c $< -o $@
clear:
@mkdir -p obj
@mv $(OBJ) obj
clean:
@$(RM) $(OBJ)
fclean: clean
@$(RM) $(NAME)
re: fclean all
The existence $(OBJ) are going to be checked when making $(NAME), not the 'obj' folder.
Solution:
NAME = lib.a
INC = lib.h
FLAGS = -Wall -Wextra -Werror
SRC = function1.c function2.c function3.c function4.c
DIR_OBJ = obj/
OBJ = $(SRC:%.c=$(DIR_OBJ)%.o)
all: $(NAME)
$(NAME): $(OBJ)
@$(AR) rcs $@ $^
@ranlib $(NAME)
$(DIR_OBJ)%.o:%.c
@mkdir -p $(dir $@)
@$(CC) $(FLAGS) -I $(INC) -c $< -o $@
clean:
@$(RM) -rf $(DIR_OBJ)
fclean: clean
@$(RM) $(NAME)
re: fclean all
I think I covered it with this example, let me know if I missed a detail.
Good luck with your projects!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | blackghost |
| Solution 3 |
