Since the question is how to write reusable code in Make files, I will give an example of using template rules in GNU Make (it seems that this is what you use, since you mention the .PHONY target), However, if you do not use any or dependency control, it might be easier to do this with a shell script - something like:
#!/bin/sh TASKS="task01 task02 task03" for i in $TASKS; do rm $i $i.ext $io -f; compiler $i.ext -O2 --make; ./$i; done
But, to extend the principle of Make, we have another problem to solve. Lines of the form:
task01-all: task01-clean task01 task01-run
Do not tell Make in what order to create the preconditions - you just need to ensure that they all run before task01-all is built. Instead, each step to start should depend on the step in front of it. Something like that:
TASKS=task01-run task02-run task03-run .PHONY: all $(TASKS) $(TASKS:run=clean) all: $(TASKS) $(TASKS:run=clean): %-clean: rm $* $*.ext $*.o -f %: %.ext | %-clean compiler $< -O2 --make $(TASKS): %-run: % ./$<
Rules with % are called "template rules" and they are a great tool to avoid re-writing the same rule several times for different purposes. One caveat is that Make does not usually check template rules for the .PHONY target; we tell Make to do this explicitly, a prefix of these rules with a list of goals and a second colon (for example, $(TASKS): .
Since task01-run needs task01 to work, we make %-run dependent on % . In addition, your Makefile shows that you want to run cleanup every time, so we make % dependent on %-clean . Since %-clean does not actually produce any output, we make this order-only dependency. Make will not look for a timestamp or anything else; it first runs the %-clean rule anytime it is necessary to run the % rule. Dependencies "Order only" are placed after | :
%: %.ext | %-clean
It is worth mentioning that one of the strengths is that it can save time by not repeating work that does not need to be repeated - i.e. it only triggers a rule if the dependencies are newer than the target. Thus, you can leave the dependency on %-clean , which will cause make to run only compiler $< -O2 --make if %.ext newer than % :
%: %.ext compiler $< -O2 --make
Then you can add a rule only to run all %-clean targets:
.PHONY: all $(TASKS) $(TASKS:run=clean) clean clean: $(TASKS:run=clean)
Last thing: I use some special variables in recipes. $@ means the goal is being built. $< denotes the first dependency. $* denotes the "core" of the pattern rule (that is, the part matched by % ).