Makefile for checking spelling

219 Views Asked by At

I am trying to configure a makefile so that I can use aspell in it to check a folder of .mb files. I am not sure how to configure it but I tried this:

spellcheck-en:
    for f in src/docs/en/*.md; do aspell --lang=en check $f; done

The thing is, the makefile is not reading the $f so when I run 'make spellcheck-en' I get this:

Error: You must specify a file name.
Error: You must specify a file name.
Error: You must specify a file name.
Error: You must specify a file name.
Error: You must specify a file name.
make: *** [Makefile:29: spellcheck-en] Error 255

However, running this: "for f in src/docs/en/*.md; do aspell --lang=en check $f; done" on the terminal is not an issue. Is there another way to indicate $f in a makefile?

Thank you.

1

There are 1 best solutions below

2
Renaud Pacalet On BEST ANSWER

This answer is not about your issues which have been fixed in the comments. Your Makefile, while working after you'll replace $f by $$f, is not better than the equivalent shell script. It has 2 main drawbacks:

  • if you run again the same check and the text files did not change, they will be checked again which is useless,
  • the checks cannot be parallelized.

The following solves these two drawbacks:

# File Makefile
MDDIR   := src/docs/en
OKDIR   := .ok
MDFILES := $(wildcard $(MDDIR)/*.md)
OKFILES := $(patsubst $(MDDIR)/%.md,$(OKDIR)/%,$(MDFILES))

.PHONY: spellcheck-en
spellcheck-en: $(OKFILES)

$(OKDIR)/%: $(MDDIR)/%.md | $(OKDIR)
    aspell --lang=en check $<
    touch $@

$(OKDIR):
    mkdir -p $@

.PHONY: clean
clean:
    rm -rf $(OKDIR)

If you now run:

make -j8 spellcheck-en

or just (because being the first target spellcheck-en is the default goal):

make -j8

You'll check only the files that changed since the last check and you'll run these checks in parallel with up to 8 jobs at a time.

Explanations:

  • wildcard and patsubst are 2 GNU make functions.
  • Phony targets are declared as prerequisites of the .PHONY special target. They are targets that are not real files. Make needs to know about them, just in case a file with the same name exists.
  • $(OKDIR)/%: $(MDDIR)/%.md | $(OKDIR) ... is a pattern rule.
  • | $(OKDIR) is a order-only prerequisite.

All these are well explained in the GNU make manual.