On Friday 23 October 2009 19:40:05 Charles Wilson wrote:
> > I thought that too, but I *did* test the sample Makefile I
> > posted, on both Ubuntu-8.04 and MSYS/Win2K; GNU Make 3.81 in
> > both cases, and in both it did DTRT. Maybe it wouldn't work
> > with an earlier version? However, neither make's own Texinfo
> > documentation, nor my copy of Robert Mecklenburg's `Managing
> > Projects with GNU Make' (O'Reilly, 3rd edition), suggest that it
> > wouldn't.
> Odd. All of Cygwin's make-3.81-2, MSYS make (3.81, stock from
> MSYS-1.0.11), mingw32-make, and mandriva make 3.81-2mdv2008.0 fail
> in this simple case:
> Note that I don't even see "here" -- the error statement is
> triggered during initial parsing of the makefile, not during the
> execution of the 'all:' rule.
The abort is triggered at the point where make is forced to expand
the `$(error ...)' macro; since it is subject to recursive expansion,
that isn't necessarily when the Makefile is read; it is when the goal
which forces the expansion, (or an immediate assignment which does
likewise), is actioned.
> AFAICT, the only things that "guard" an $(error ...) are makefile
> conditionals, which is what we're trying avoid.
That's one scenario, but it *isn't* the only way...
> Maybe the make documentation needs an update...
Maybe. What is there is accurate, but may be lacking in detail,
particularly in respect of the inability to achieve a conditional
abort within shell commands. The Texinfo manual does offer an
example where the recursive evaluation occurs directly within the
commands associated with a goal which isn't actioned, (but doesn't
make it clear that it's conditional on the entire goal rather than
commands themselves), and that works just fine. In fact, my example
*appeared* to work for this very reason -- the individual goals for
`$(need-DESTDIR-compatibility)' were never actioned if `$(DESTDIR)'
was empty, resulting in apparently correct behaviour; however, I had
neglected to test for a non-empty `$(DESTDIR)' coupled with normal
*nix definitions for `$(prefix)' et al. :-( Of course, the abort is
falsely triggered for this "valid" usage, even though the `case'
command would have prevented it, had it been executed.
> >> +check-DESTDIR-compatibility:
> >> + ...
> >> + test 0 -eq $$status || break ;\
> > Adding this `test' to the actions for
> > `check-DESTDIR-compatibility' means that you capture and report
> > only the first of possibly more than one DESTDIR incompatibility
> > per `make' run; omit it, as I did, and you capture them all in a
> > single run, which I think is better.
> I put it in deliberately, because of the wacky way mingw/'s
> install directories are computed (tooldir vs. prefix);
Indeed. That's something else I think could do with an overhaul.
> do we
> really want to tell everybody they should "redefine" tooldir --
> which they may have never heard of, unless they are in the habit
> of building binutils and gcc -- when all they really need to do is
> redefine prefix?
> Plus, you get false positives:
I'd overlooked that likely scenario...
> if you have defined prefix as
> C:\MinGW, but have NOT actually defined includedir or libdir to
> anything special, then you get three error messages,
I agree, that would be bad; we definitely don't want such behaviour.
> I'll change it back if you insist, but I really think bailing out
> after the first error is /less/ confusing to end-users.
On reflection, I agree; no need to change it back.
> FYI, Ralf W. suggested the following:
> >> > +$(need-DESTDIR-compatibility):
> >> > + @case "$($@)" in *:*) \
> > Wouldn't ?:* suffice? Not that I'd like anyone to use a path
> > with a colon stuck in the middle of it on unix, but it certainly
> > wouldn't be a Win32 path.
> Is that change ok with you?
Yes. I'd considered it myself, and like Ralf, I wouldn't want to see
a colon embedded in a *nix path either; thus I left it as `*:*', even
though `?:*' is strictly a more accurate representation of our needs.
If you prefer the stricter accuracy, that's okay with me.
Taking all of the above on board, the updated example attached shows
one correct way to do this, while still using the `$(error ...)'
macro -- the `fail-DESTDIR-compatibility' goal, which invokes the
`$(error ...)' macro, is only ever invoked by a recursive `$(MAKE)';
(of course, using `echo' instead of `$(error ...)', the diagnostic
could be placed directly within the `$(need-DESTDIR-compatibility)'
commands, so obviating the need for the recursive `$(MAKE)' anyway).