This weekend, my roommate asked me to make a website for him. I wrote it in PHP so I could just make some templates and he could import them, but it bothered me that I was rendering a static website with PHP. The easiest solution seemed to be running every file though PHP before uploading the site, so I needed a Makefile.
There's quite a bit in this file that was new to me, so I figured it might be helpful for my loyal readers to explain it.
Implicit rules are any Make file that involves a wildcard. The wildcard in this case is
%. For example, this rule will be used any time we need to compile .c files into .o files:
%.o : %.c gcc -o $@ $<
Notice that it reads like a normal rule, just using a wildcard: "When you need any .o file, create it from a .c file with the same name". Also notice the automatic variables,
$@ is the target (the file to be created) and
$< is the name of the first target (the file to make it out of). There are also other automatic variables, but these were the most useful to me.
GNU Make comes with several built-in functions. You call them in this form:
$(function_name, param1, param2, etc)
The text functions were the ones I used most, like
patsubst (terribly named), which are variations on find/replace, and
filter-out (better names). I could imagine the others being useful too (strip, sort, etc.). There are also several other kinds of function whichs seem useful (see the link).
The way Make works is by checking the target file's timestamp and rebuilding if it's old. This becomes a problem if you don't actually create the target file — for example, with the
dist targets. You don't create an "all" file, it's just a name. Make's way of dealing with this is phony targets, which basically tells it "the target isn't actually a file", so it doesn't check that file, it just always trys to build. This has two advantages:
- It's very slightly faster (because it's not checking for a file that should never exist).
- It's slightly safer (because if that file every does exist, it'll still work right.
Using a phony target looks like this:
.PHONY : all .PHONY : clean .PHONY : dist
This is a minor one, but if you want an empty target, just end it with a semi-colon (
all: $(DEPENDS) ;
And that's all for today's show. Tune in next week.