'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