打印一个句子,只有当一个 Makefile 规则被执行时

Printing a sentence, only if a Makefile rule is executed

我正在为一个学校项目定制我的 Makefile。

我想打印以下句子,但只有当我的 SRCS_DIR 中的 .c 文件已实际编译时。

All the .c files have been compiled successfully !

如果我将您在下面代码块第 3 行中看到的 printf 移动到最后一行,它会在编译每个 .c 文件后打印消息... 因此,我创建了一个 COMPILED 变量,我在 Makefile 的开头将其设置为 0,然后在编译期间将其值更改为 1(下面代码块中的第 11 行)。我尝试使用 ifeq 条件(下面代码块中的第 2 行),但是当我这样做时句子没有打印出来。

$(NAME): $(LIBFT_AR) $(OBJS)
ifeq ($(COMPILED), 1)
    printf "$(GREEN)> All the .c files have been compiled successfully !$(END)\n"
endif
    printf "$(BLUE)> Creating the executable file :$(END) $@\n"
    $(CC) $(OBJS) $(LIBFT_AR) -lreadline -o $(NAME)
    printf "$(GREEN)> Executable file has been created successfully !$(END)\n"

$(OBJS_DIR):
    mkdir -p $(addprefix $(OBJS_DIR)/, $(SUBDIRS_LST))

$(OBJS_DIR)/%.o: $(SRCS_DIR)/%.c $(INCS) Makefile | $(OBJS_DIR)
override COMPILED=1
    $(CC) $(CFLAGS) -I $(INCS_DIR) -c $< -o $@
    printf "$(BLUE)> Compiling :$(END) $<\n"

你对这个问题有什么解释吗and/or一个可以帮助我解决问题的解决方案?

谢谢!

Makefile 不是脚本语言。 Make 不读取 makefile 和 运行 读取每个规则。 Make 将 (1) 解析整个 makefile(以及任何包含的文件)并构建所有先决条件的内部图,而不是 (2) 运行 过时目标的配方。不在食谱中的内容始终在第一步中进行评估。食谱中的内容始终在第二步进行评估。

使用制表符缩进的行在食谱中(因此在第一步中进行评估)。 以 TAB 缩进的行在食谱中(因此被评估——这意味着,在第二步中给予 shell 执行)。

也许你现在可以明白为什么你的尝试不起作用:if-statements 和 COMPILED 的变量赋值总是在第一步中被评估,在 make 决定任何目标是否应该之前建成。

我不确定我是否理解您的目标。如果您的可执行文件的配方被调用,那么这意味着您的所有源文件都已编译:这就是 makefile 所做的。也许您正在尝试区分至少编译了一个源文件的构建和无需重新编译源文件但目标(可执行文件)已过期的构建?

如果这就是您想要的,解决问题的简单方法是使用自动变量;例如 $? automatic variable 扩展到已过时的先决条件列表。你可以这样做:

$(NAME): $(LIBFT_AR) $(OBJS)
        test -z '$(filter %.o,$?)' || printf "$(GREEN)> All the .c files have been compiled successfully !$(END)\n"
        printf "$(BLUE)> Creating the executable file :$(END) $@\n"
        $(CC) $(OBJS) $(LIBFT_AR) -lreadline -o $(NAME)
        printf "$(GREEN)> Executable file has been created successfully !$(END)\n"

$(filter ...) function 将扩展到 $? 变量中的 .o 个文件列表;如果那是空的,则没有 .o 个文件被重建。