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

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能识别依赖文件的变更,请问该如何修复?


问题原因
  1. bonus规则的依赖仅包含$(HEADERS)和libs,这两个文件在首次编译后很少变更,导致make认为bonus始终是最新状态。
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 15:05:34