MakeFile 编译所有文件,即使这些文件已经编译并且在那之后没有被触及

MakeFile compiling all the files even if those were already compiled and weren't touched after that

这是我的 makefile

CFLAGS=-Wall -g -lm

SHELL=/bin/bash

CFILES=$(wildcard *.c)
OBJECTS=$(patsubst %.c,%,$(CFILES))

.PHONY: clean status all

all: $(OBJECTS)

#%:%.c
#   gcc $(CFLAGS) -o $@ $^

$(OBJECTS): $(CFILES)
    @echo "Running : $@ -> $^"
#   gcc $(CFLAGS) -o $@ $(patsubst %,%.c,$@) 

clean:
    rm -f $(OBJECTS)

status:
    @git status
    @git diff --stat

push: clean
    git push

当我使用 %:%.c(Makefile 中注释的规则)时 运行 没问题。通过所有这些,我只能认为规则 $(OBJECTS): $(CFILES) 以某种方式认为 OBJECTS 中的任何目标都取决于 $(CFILES).[=16= 中的所有值]

因此,每当它构建任何单个 binray 时,它都会发现它依赖于所有 CFILES,因此如果其中任何一个被修改,它都会重新编译任何 c 文件。

所以我想知道是否有更好的方法来编写规则 $(OBJECTS): $(CFILES),如果这是导致问题的原因。否则,如果此规则不是导致此问题的罪魁祸首。我知道我可以使用 %:%.c 但我认为它会导致一些问题,因为这条规则也适用于 something.h.

我是 Makefile 的新手,所以如果你也详细说明原因会很有帮助,所以以后我可以防止这种情况发生

你的猜测是对的。当你写:

foo bar biz : foo.c bar.c biz.c
        # do something

(这是 make 在扩展变量后看到的),make 将其解释为:

foo : foo.c bar.c biz.c
        # do something
bar : foo.c bar.c biz.c
        # do something
biz : foo.c bar.c biz.c
        # do something

您的问题有点令人困惑,因为您使用的是术语“对象”,它通常表示对象文件 (foo.o),而不是二进制文件或可执行文件。

无论如何,你可以安全地做你想做的 static pattern rules:

$(OBJECTS): % : %.c
        @echo "Running : $< -> $@"
#       gcc $(CFLAGS) -o $@ $<