Makefile的bonus规则无法识别文件变更的问题求助
问题描述
我有一个包含all和bonus规则的Makefile:
all规则依赖srcs_files和common_files两组文件,执行make all后修改任意依赖文件,再次执行make能识别变更并重新编译。bonus规则依赖common_files和bonus_files,首次编译正常,但修改这两类文件后执行make bonus,会返回提示:make: 'bonus' is up to date。
附Makefile代码:
NAME = fractol NAME_B = fractol_b CC = cc CFLAGS = -Wall -Wextra -Werror XFLAGS = -lbsd -lmlx -lXext -lX11 COMMON_FILES = quit zoom ft_atof colors_part1 colors_part2 SRCS_FILES = main fractal hooks movement BONUS_FILES = main_bonus fractal_bonus hooks_bonus movement_bonus newton_bonus HEADERS_FILES = fractol buttons ft_printf COMMON = $(addprefix $(C_DIR), $(addsuffix .c, $(COMMON_FILES))) SRCS = $(addprefix $(SRCS_DIR), $(addsuffix .c, $(SRCS_FILES))) OBJS = $(addprefix $(OBJS_DIR), $(addsuffix .o, $(SRCS_FILES))) OBJS_C = $(addprefix $(OBJS_C_DIR), $(addsuffix .o, $(COMMON_FILES))) OBJS_B = $(addprefix $(OBJS_B_DIR), $(addsuffix .o, $(BONUS_FILES))) HEADERS = $(addprefix $(HEADERS_DIR), $(addsuffix .h, $(HEADERS_FILES))) BONUS = $(addprefix $(BONUS_DIR), $(addsuffix .c, $(BONUS_FILES))) SRCS_DIR = srcs/ C_DIR = common_srcs/ OBJS_DIR = objs/ OBJS_C_DIR = objs_common/ OBJS_B_DIR = objs_bonus/ HEADERS_DIR = headers/ LIB_DIR = libs/ BONUS_DIR = bonus/ all: mkdir -p $(OBJS_DIR) mkdir -p $(OBJS_C_DIR) make $(NAME) $(OBJS_DIR)%.o: $(SRCS_DIR)%.c $(CC) $(CFLAGS) -c $< -o $@ $(OBJS_C_DIR)%.o: $(C_DIR)%.c $(CC) $(CFLAGS) -c $< -o $@ $(OBJS_B_DIR)%.o: $(BONUS_DIR)%.c $(CC) $(CFLAGS) -c $< -o $@ $(NAME): $(HEADERS) $(OBJS) $(OBJS_C) libs $(CC) $(CFLAGS) $(COMMON) $(SRCS) libs/libftprintf.a $(XFLAGS) -o $(NAME) bonus: $(HEADERS) libs mkdir -p $(OBJS_B_DIR) mkdir -p $(OBJS_C_DIR) make $(NAME_B) $(NAME_B): $(OBJS_B) $(OBJS_C) $(CC) $(CFLAGS) $(COMMON) $(BONUS) libs/libftprintf.a $(XFLAGS) -o $(NAME_B) $(HEADERS): ln printf/srcs/ft_printf.h $(HEADERS_DIR) libs: $(HEADERS) make -C ./printf mkdir -p $(LIB_DIR) mv ./printf/libftprintf.a $(LIB_DIR) clean: make clean -C ./printf rm -rf $(OBJS_DIR) rm -rf $(OBJS_C_DIR) rm -rf $(OBJS_B_DIR) fclean: clean rm -rf libs rm -rf $(HEADERS_DIR)ft_printf.h rm -rf $(NAME) rm -rf $(NAME_B) re: fclean all .PHONY: all clean fclean re
我需要让make bonus能识别依赖文件的变更,请问该如何修复?
问题原因
bonus规则的依赖仅包含$(HEADERS)和libs,这两个文件在首次编译后很少变更,导致make认为bonus始终是最新状态。bonus规则内使用递归调用make $(NAME_B),打断了make的依赖检查链,无法直接感知$(NAME_B)的底层依赖(bonus_files、common_files)变更。
修复方案
方案1:调整依赖结构(推荐)
直接让bonus规则指向目标文件$(NAME_B),并确保$(NAME_B)关联所有必要依赖,移除递归调用:
修改相关规则如下:
# 让bonus直接依赖目标文件 bonus: $(NAME_B) # 扩展$(NAME_B)的依赖,包含所有需要检查变更的文件 $(NAME_B): $(HEADERS) $(OBJS_B) $(OBJS_C) libs mkdir -p $(OBJS_B_DIR) mkdir -p $(OBJS_C_DIR) $(CC) $(CFLAGS) $(OBJS_B) $(OBJS_C) libs/libftprintf.a $(XFLAGS) -o $(NAME_B)
方案2:标记bonus为PHONY(不推荐)
若要保留递归调用,可将bonus加入PHONY列表,强制每次执行make bonus都重新运行规则:
.PHONY: all clean fclean re bonus
此方法会跳过依赖检查,强制重新编译,浪费资源,仅作为临时替代方案。
额外优化建议
当前编译命令直接使用.c文件而非.o文件,会绕过.o文件的缓存,每次都重新编译所有源文件。建议改为使用.o文件链接,提升编译效率:
# 修改$(NAME)的编译命令 $(NAME): $(HEADERS) $(OBJS) $(OBJS_C) libs $(CC) $(CFLAGS) $(OBJS) $(OBJS_C) libs/libftprintf.a $(XFLAGS) -o $(NAME) # 修改$(NAME_B)的编译命令(和方案1配合使用) $(NAME_B): $(HEADERS) $(OBJS_B) $(OBJS_C) libs mkdir -p $(OBJS_B_DIR) mkdir -p $(OBJS_C_DIR) $(CC) $(CFLAGS) $(OBJS_B) $(OBJS_C) libs/libftprintf.a $(XFLAGS) -o $(NAME_B)
内容的提问来源于stack exchange,提问作者romachad
相关产品推荐
相关产品推荐

