Makefile does not invoke action after touching the target file

Viewed 45

Here is my Makefile:

NAME        := libftprintf.a

LIB         := ar rcs
CC          := gcc
CFLAGS      := -Wall -Wextra -Werror

SRCS_DIR    := ./sources/
HDRS_DIR    := ./headers/
OBJS_DIR    := ./objectives/

SRCS_FILES  := ft_conv.c \
                ft_eval_hex.c \
                ft_eval_number.c \
                ft_eval_string.c \
                ft_parsers.c \
                ft_strs_join.c \
                ft_eval_char.c \
                ft_eval_int.c \
                ft_eval_percent.c \
                ft_handler.c \
                ft_printf.c

HDRS_FILES  := ft_conv.h \
                ft_eval_hex.h \
                ft_eval_number.h \
                ft_eval_string.h \
                ft_parsers.h \
                ft_strs_join.h \
                ft_eval_char.h \
                ft_eval_int.h \
                ft_eval_percent.h \
                ft_handler.h \
                ft_printf.h

OBJS_FILES  := $(SRCS_FILES:.c=.o)

SRCS        := $(addprefix $(SRCS_DIR),$(SRCS_FILES))
HDRS        := $(addprefix $(HDRS_DIR),$(HDRS_FILES))
OBJS        := $(addprefix $(OBJS_DIR),$(OBJS_FILES))

LIBFT_DIR   := ./libft/
LIBFT_NAME  := libft.a
LIBFT       := $(addprefix $(LIBFT_DIR),$(LIBFT_NAME))

RM          := rm -rf

all: $(NAME)

bonus: all
bonus_one: all
bonus_two: all

$(NAME): $(OBJS)
    $(LIB) $(NAME) $(OBJS) $(LIBFT)

$(OBJS_DIR)%.o: $(SRCS_DIR)%.c $(HDRS) Makefile | $(OBJS_DIR) subsystem
    $(CC) $(CFLAGS) -c $< -o $@ -I $(HDRS_DIR) -I $(LIBFT_DIR)

subsystem:
    @$(MAKE) -C $(LIBFT_DIR)

$(OBJS_DIR):
    mkdir $(OBJS_DIR)

clean:
    @$(MAKE) -C $(LIBFT_DIR) clean
    $(RM) $(OBJS_DIR)

fclean: clean
    @$(MAKE) -C $(LIBFT_DIR) fclean
    $(RM) $(NAME)

re: fclean all

.PHONY: all subsystem bonus bonus_one bonus_two clean fclean re

The problem is so: if I do make all, then touch libftprintf.a I would expect that make all will rebuild libftprintf.a since it was changed and target all depends on that file. However, make does nothing and I can't understand this behavior. Also, there is one more minor issue: during make all I create a directory objectives where I store all .o files. Calling make fclean and make all entirely rebuilds the target, however calling make re results in an error:

rm -rf ./objectives/
rm -rf *libft objectives here*
rm -rf libft.a
rm -rf libftprintf.a
make: *** No rule to make target `objectives', needed by `objectives/ft_conv.o'.  Stop.

If I call make re right after this error, the target builds as always. Also, if I change re target to this, I do not receive any errors:

re:
    @$(MAKE) fclean
    @$(MAKE) all

Could not find solutions to my problems anywhere on the Internet.

1 Answers

Touching libprintf.a won't cause anything to rebuild. Make rebuilds targets that are out of date. Out of date means that either the target doesn't exist, or some prerequisite of the target is newer than the target.

After you run make then libprintf.a is up to date, which means it's newer than all its prerequisites. Running touch libprintf.a just makes it even newer than its prerequisites than it was before, so make still considers it up to date.

If you want to rebuild libprintf.a you need to touch (or delete) one of its prerequisites, not the target itself.

The reason for your second issue seems to be related to the makefile in the libft subdirectory. It seems like you're using the --no-print-directories option here: you should avoid using that, at least as long as you're debugging, so that you can see where make is going and which makefile it's running.

Related