You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Makefile执行异常问题咨询:修改目标文件后未触发重建及re目标执行报错

让我们一步步解决你遇到的两个Makefile问题:


问题1:touch libftprintf.a后make all不重建库

原因分析

你的$(NAME)目标规则写法有两个致命问题:

$(NAME): $(OBJS) $(LIB) $(NAME) $(OBJS) $(LIBFT)
  1. 依赖列表里重复了$(NAME)(目标文件本身)—— Make会默认认为目标的时间戳肯定比自身新,所以永远不会触发重建逻辑。
  2. 这个规则没有执行命令—— Make完全不知道该如何从依赖生成libftprintf.a,只能依赖隐含规则,但隐含规则无法处理静态库的打包逻辑。

当你touch libftprintf.a更新时间戳后,Make对比依赖时会发现目标的时间戳比所有依赖都新(甚至包括它自己),自然判定不需要任何操作。

解决方案

修正$(NAME)规则,去掉重复依赖,添加正确的静态库打包命令:

$(NAME): $(OBJS) $(LIBFT)
	$(LIB) $(NAME) $(OBJS)
	# 可选:如果需要把libft的内容合并到当前库,取消下面注释
	# ar -x $(LIBFT)
	# $(LIB) $(NAME) *.o
	# rm -f *.o
  • $(LIB)是你定义的ar rcs,这个命令会把$(OBJS)里的目标文件打包进libftprintf.a。
  • 如果需要让libftprintf.a包含libft的所有内容(避免链接时同时指定两个库),可以先解压libft的目标文件,再一起打包。

问题2:make re首次执行报错,第二次才正常

原因分析

你的原re目标写法是:

re: fclean all

Make处理这种链式目标时,会先执行fclean(删除objectives目录和库文件),再执行all。但问题出在:

  1. $(OBJS)的规则中,$(OBJS_DIR)是order-only依赖(用|标记),加上原$(NAME)规则没有命令,导致Make的依赖解析逻辑出现时序混乱,无法正确触发$(OBJS_DIR)的创建规则。
  2. 当你改成re: @$(MAKE) fclean @$(MAKE) all后正常,是因为这种写法是嵌套执行Make进程—— 第一个make fclean完全执行完毕(目录被删除)后,才启动新的Make进程执行all,新进程会重新完整解析依赖,正确创建objectives目录。

解决方案

推荐采用嵌套Make的写法,彻底避免时序问题:

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

把两个命令分开写,确保fclean完全执行后再启动all的构建,上下文完全隔离,不会出现依赖解析的混乱。

另外可以给mkdir命令加-p参数,避免目录已存在时报错,让Makefile更健壮:

$(OBJS_DIR): 
	mkdir -p $(OBJS_DIR)

修正后的完整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) $(LIBFT)
	$(LIB) $(NAME) $(OBJS)
	# 可选:合并libft到当前库
	# ar -x $(LIBFT)
	# $(LIB) $(NAME) *.o
	# rm -f *.o

$(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 -p $(OBJS_DIR)

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

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

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

.PHONY: all subsystem bonus bonus_one bonus_two clean fclean re

内容的提问来源于stack exchange,提问作者lteresia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 20:12:43