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




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.


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.

  • What if I want to change the file suffix for the files in the outputs folder to something other than txt? I can't think of a clean way to do that with subst... – hugomg Dec 6 '16 at 20:49
  • There are many functions in gnu make. I updated my answer with an example. – meuh Dec 6 '16 at 21:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.