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}