Created at:

make (portable) notes

This page is about techniques for building your Makefile in a portable way. This tips can be used for different flavours of make.

For specific NetBSD make tips, see this page.

Dependencies that are needed for a file but are not needed to generate it

I have a RST (reStructuredText) file that will be converted to HTML. The main file main.rst include other files::

    foo
    bar

Makefile is used to generate the resulting HTML file::

all.html: all.rst dep.rst
	rst2html $> $@

The problem is that $> expands to all dependencies, not the first one.

It is actually more complex than that. I want to parse dep.rst separately by a parser of myself that checks the validity of blocks of code. So, my actual Makefile looks like that::

all.html: all.rst
	rst2html $> $@

all.rst: dep.rst

dep.rst:
	check $@

This approach has a problem: it doesn't execute check command. So, the next try was to make dep.rst a phony target::

all.html: all.rst
	rst2html $> $@

all.rst: dep.rst

.PHONY: dep.rst

dep.rst:
	check $@

This has another problem. check command is always executed but when dep.rst is updated, all.html is not created again (they are now phony targets and no timestamp verification is made against them -- actualy they aren't even files :-]).

Well, I can simply make all.html depend on everyone and hardcode the first dependency instead of using $>::

all.html: all.rst dep.rst
	rst2html all.rst $@

dep.rst:
	check $@

This has another problem: all.html is updated when dep.rst and all.rst are newer, but the check command is never executed. The reason is that dep.rst doesn't have any dependency to compare against.

Finally I found a satisfactory solution without having to do any ugly hack. If, in last example, dep.rst is not built because it doesn't have any dependency to compare. So let's create a dep.check file that is the *target* and make dep.rst a dependency of it. It would work, but it would not to be good to have lots of temporary files in the development directory. So I personally chose to make check files phony targets, with the issue of having it being executed always (if you want to make it a phony target or not, it is something you might think). Result was::

all: dep.check all.html

all.html: all.rst
	rst2html all.rst $@

all.rst: dep.rst
	touch $@

.PHONY: dep.check
dep.check: dep.rst
	check $>

If you have lots of source files, you can use your make tool features. I'm using NetBSD make, which has powerful features and I prefer over GNU make. My resulting Makefile is similar to the example below. I'm using a variable called RSTDOCS to hold names of all reStructuredText that are not 00-all.rst. CHECKS hold names of phony targets to be executed::

RSTDOCS = boot.rst fdisk.rst
CHECKS = ${RSTDOCS:.rst=.check}

TARGETS = 00-all.html

all: ${CHECKS} ${TARGETS}

00-all.html: 00-all.rst
	rst2html ${.ALLSRC} ${.TARGET}

00-all.rst: ${RSTDOCS}
	touch ${.TARGET}

# Check all rst files
.for rst in ${RSTDOCS}
check=${rst:.rst=.check}
${check}: ${rst}
	awk -f tools/source.awk ${.ALLSRC}
.endfor

.PHONY: clean
clean:
	rm -f ${TARGETS}