T-Dawg
T-Dawg

Reputation: 83

Why does make recompile all files?

My goal is the following: I have a directory src which contains markdown files (.md). I want to run a command on each of these files so that the comments are removed and the edited files are stored in a separate directory. For this I want to use make.

This is the Makefile I have:

.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

While this works in general, I noticed that the command is executed on all files, even though I changed only one single file.

Example: I have 3 Files src/a.md, src/b.md and src/c.md. Now I run make and all files are correctly generated in the build folder. Now I only edit c.md and run make again. I would expect that make only "compiles" src/c.md anew but instead all three files are compiled again. What am I doing wrong?

Upvotes: 0

Views: 113

Answers (1)

Norman Gray
Norman Gray

Reputation: 12514

Your line

$(DSTS): $(SRCS)

is saying ‘All of the DSTS depend on all of the SRCS’, so whenever any one of the $(SRCS) is newer than any of the $(DSTS), this pandoc action will be run.

That's not what you want to express. What you want is something more like

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

all: $(DSTS)

That says that all of the $(DSTS) should be up to date, and the pattern rule teaches Make what each one depends on, and how to build it, if it is out of date.

(As a general point, looking your original rule, it's rarely the right thing to do to have multiple targets in a rule, as you have with $(DSTS); also note that in your original, $< always refers only to the first of the dependencies in $(SRCS))

Upvotes: 2

Related Questions