Convert PHP to static pages with GNU Make

I recently moved an old website to a new server. For performance reasons, the new server is running nginx instead of Apache, and didn’t have nginx set up to use PHP. (The optimal way, apparently, is to use PHP-FGM, which currently requires you to patch and build PHP yourself, at least until PHP 5.4).

That was fine, though, because this old site only really needed PHP for one little thing that we could do without. In fact, the primary reason for using PHP here was to essentially append the header and footer sections to each unique page. Basically, we had stuff like:

[php]
<?php include(‘../header.inc’); ?>
… page contents …
<?php include(‘../footer.inc’); ?>
[/php]

on every page. What I needed was an automated process to convert all of these PHP pages into static pages. GNU Make, of course, is the de facto standard for automating something like this. Let’s give it a go:

First, I needed a list of all the files I wanted to generate. In vim, r!find . -name "*.php" gave me a nice list of all of my PHP files: “index.php”, “about.php”, “history.php”. I replaced all instances of “.php” with “.html” and assigned this list the name “PAGES”:

[code]
PAGES=\
./index.html \
./about.html \
./history.html
[/code]

We also need a list of the header and footer templates to properly detect when dependencies change:

[code]
TEMPLATES=header.inc footer.inc
[/code]

I wanted the generated files to go in a different directory, which I set as “PREFIX”:

[code]
PREFIX=../www
[/code]

The problem here is that we’ll need to change the working directory in the build process, so we need to make sure that our target is in an absolute filepath.

[code]
REALPREFIX=$(realpath $(PREFIX))
[/code]

Now we can begin writing the rules:

[code]
default: $(addprefix $(REALPREFIX)/,$(PAGES)) staticstuff
[/code]

We are first building a list of all the static HTML files that will be generated by appending PREFIX to each name. The rule “staticstuff” is explained below.

We then take advantage of pattern-matching to create a one-size-fits-all rule for converting PHP pages into static HTML pages:

[code]
$(REALPREFIX)/%.html : %.php $(TEMPLATES)
mkdir -p `dirname $@`
cd `dirname $<`; php `basename $<` > $@
[/code]

Basically, we are running each page and dumping the output into a new HTML file. Of course, we need to make any directories that don’t already exist. Note that we added “TEMPLATES” into the dependencies, because if any of the template files change, we need to regenerate the static page too.

We mustn’t forget all of our already-static content, like stylesheets and images. The easiest thing here was to simply use rsync and copy it all over:

[code]
staticstuff:
rsync -auvi \
–exclude=’*.php’ \
–exclude=’Makefile’ \
./ $(REALPREFIX)/
[/code]

And, for completeness:

[code]
clean:
rm -r $(REALPREFIX)/*
[/code]

Now, when I want to update my website, I just edit the original files and run “make”. If I ever feel like I need to switch back to a dynamic, PHP-running site, I can just use the files as they already are.

One Response to “Convert PHP to static pages with GNU Make”

  1. Paul Rafferty writes:

    This is cool – a very good use of make! I wrote a pretty painful script that generates a static copy of a complex wordpress site using wget and a bunch of bash/sed/awk crap to fix the many borked things. But this looks like it might be a much better (and simpler) option. Kudos.

Leave a Reply