Day 16 of 60: I strongly dislike M4

Which is a problem because the Sendmail build system is written in it.

Here's the problem I'm trying to solve.



As mentioned previously, Sendmail supports a DESTDIR variable, which you can set on the make command line, to specify a prefix to be added to the all the installation paths.

The problem is that the build infrastructure doesn't create some necessary directories. Specifically, it won't create:

$DESTDIR/usr/lib
$DESTDIR/usr/bin
$DESTDIR/usr/share/man/cat8
$DESTDIR/usr/share/man/cat5
$DESTDIR/usr/share/man/cat1

Some of the code to support creating this is easy, but I've run in to problem with links.m4.

Specifically, this bit of code:

define(`bldMAKE_TARGET_LINKS',
` for i in $2; do \
rm -f $$i; \
ln -s ${DESTDIR}$1 $$i; \
done'
)dnl


The loop body needs to be modified with a mkdir call, like so:

define(`bldMAKE_TARGET_LINKS',
` for i in $2; do \
-mkdir `dirname $$i`; \
rm -f $$i; \
ln -s ${DESTDIR}$1 $$i; \
done'
)dnl


to ensure that the directory in which the link is going to be created will work.

The problem is the backticks. They don't play nicely with M4. I thought I could fix this with changequote, but this code doesn't work:

dnl Change the quote definition temporarily so that
dnl we can use backticks in the next bit of Makefile
changequote(",")dnl
define("bldMAKE_TARGET_LINKS",
" for i in $2; do \
-mkdir -p `dirname $$i`; \
rm -f $$i; \
ln -s ${DESTDIR}$1 $$i; \
done"
)dnl
dnl Change the quotes back
changequote(, )dnl


More specifically, I get errors like this:

.../library.m4:17 bad macro name

Where library.m4 includes links.m4.

What's especially hateful is that if I cut and paste the code in to a separate m4 file it works fine (read: it produces the correct output).

Anyone know how I might fix this?

PS: Using other characters as quotes (e.g., changequote([, ]) doesn't work, and nor does using $(...) instead of backticks. Solaris' /bin/sh (which make(1) uses) doesn't understand that construct.

8 comments:

  1. changequote(,) doesn't reset the quotes, it turns off quoting. I think you want changequote(`,').

    I put your macro in my site.config.m4, with cq.([,]) before and cq.(`,') at the end and it works fine. If I use cq.(,) at the end, it explodes spectacularly.

    The reason it works standalone is because there's nothing else to quote, so turning quoting off doesn't cause a problem.

    ReplyDelete
  2. You can, of course, ignore the backslashes in the previous comment. Seems to be a bug in WordPress.

    ReplyDelete
  3. Not sure why I used blockquote instead of code. Sigh.

    ReplyDelete
  4. Ironically, my last post had a quoting error... (In the exposition, not the patch.) I used '<' as a quote character, which generally doesn't work well in HTML. Doh.

    In order to get [stuff `command` more stuff] in the output, I put [`stuff ``command`''' more stuff'] in the macro definition. Actually the output is [stuff `command`'' more stuff] but the [''] is effectively removed by the shell.

    ReplyDelete
  5. Grrr! Wordpress 'smart quotes' buggered it up this time. Sod it, read the patch!

    ReplyDelete
  6. Bingo. Committed, with related changes, in 1097.

    ReplyDelete
  7. [...] The issues with M4 have been resolved. A colleague, Andre Lucas, took up the challenge and worked out a fix which he describes in detail. And ministat’s now looking much better. It’s grown some useful new options, a lot of documentation, and can now (optionally) generate plots in colour. Look below the fold for two example plots. [...]

    ReplyDelete
  8. If Sendmail is driving you insane, I'd strongly recommend Exim. It's an excellent MTA.

    ReplyDelete