Make Command – Apply Rule to Every File Matching a Pattern

make

I am working on a project that has a directory structure that looks a bit like this:

inputs/
   a.txt
   b.txt
   c.txt

outputs/
   a.out
   b.out
   c.out

makefile

The files in the outputs folder are generated from the files in the inputs folder and I want to automatically update them whenever one of the input files changes.

I tried to do this by creating a makefile with a pattern rule. (To keep this question simple, I'm just copying the input file instead of transforming it)

outputs/%.txt: inputs/%.out
    cp $< $@

However, this makefile didn't quite do what I want. If I run make outputs/a.txt it will apply the rule that I wrote and regenerate the output file if it is outdated but if I just run make then nothing happens:

make: *** No targets.  Stop.

Is there a way to tell make that by default I want to generate an output file for every file in the inputs folder?

edit: made the output files have a different file suffix than the input files.

Best Answer

You would typically do this with a makefile something like this:

IN = $(wildcard inputs/*.txt)
OUT = $(subst inputs/,outputs/,$(IN))

outputs/%.txt: inputs/%.txt
        cp $< $@

default:  $(OUT)

This makes the default target (the first one in the file), depend on OUT which is the glob expansion of the existing files in IN with the directory string changed from inputs to outputs.


If you want to change the suffix there are lots of other builtin functions to manipulate the targets. For example you can add an intervening operation:

IN2 = $(addsuffix .out,$(basename $(IN)))

The basename function will remove the trailing .txt, and the addsuffix will add a trailing .out.

Related Question