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}