为什么 make 会重新编译所有文件?

Why does make recompile all files?

我的目标如下:我有一个目录 src,其中包含降价文件 (.md)。我想对每个文件执行 运行 命令,以便删除注释并将编辑后的文件存储在单独的目录中。为此,我想使用 make.

这是 Makefile 我有:

.PHONY: clean all

BUILD_DIR := build
SRC_DIRS := src

SRCS := $(shell find $(SRC_DIRS) -name *.md)
DSTS := $(patsubst $(SRC_DIRS)/%.md,$(BUILD_DIR)/%.md,$(SRCS))

all: $(DSTS)

# The aim of this is to remove all my comments from the final documents
$(DSTS): $(SRCS)
    pandoc --strip-comments -f markdown -i $< -t markdown -o $@

clean:
    rm $(BUILD_DIR)/*.md

虽然这通常有效,但我注意到该命令对所有文件都执行,即使我只更改了一个文件。

示例: 我有 3 个文件 src/a.mdsrc/b.mdsrc/c.md。现在我 运行 make 并且所有文件都在 build 文件夹中正确生成。现在我只再次编辑 c.md 和 运行 make。我希望 make 仅重新“编译”src/c.md,而是再次编译所有三个文件。我做错了什么?

你的线路

$(DSTS): $(SRCS)

表示“所有 DSTS 都依赖于 SRCS 的 all”,因此只要 $(SRCS) 中的任何一个比 [=13] 中的任何一个更新=],此 pandoc 操作将是 运行。

这不是你想表达的。你想要的更像是

$(BUILD_DIR)/%.md: $(SRC_DIRS)/%.md
    pandoc --strip-comments -f markdown -i $< -t markdown -o $@

all: $(DSTS)

也就是说所有 $(DSTS) 都应该是最新的,并且模式规则告诉 Make 每个依赖什么,以及如何构建它,如果它已经过时了。

(一般来说,查看您的原始规则,在规则中设置多个目标很少是正确的做法,就像您在 $(DSTS) 中所做的那样;另请注意,在您的原始规则中,$< 始终仅引用 $(SRCS))

中依赖项的 first