make-alpha
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Handling of SHELL by GNU make: not POSIX compliant


From: David Boyce
Subject: Re: Handling of SHELL by GNU make: not POSIX compliant
Date: Mon, 07 Oct 2002 12:41:25 -0400

Soren,

Sorry for the late and lengthy response. I'll address your points up top here because my response didn't interleave well with yours.

First, to your last point that the proposed change might not achieve "any practical improvement for anybody". Believe me, I don't have time to go looking for technical standards violations to quibble with. On the contrary, as with most bugs, I discovered this one only when it jumped up and bit me. I can't be the judge of how common the problem is or will be, but I assure you it did have a practical effect on me at least.

Next, regarding your Windows concerns: I don't know if there's a fixed GNU policy but as far as I know POSIX conformance is just not a concern on Windows. In particular the handling of SHELL is already a completely different case on Windows, for good reason as you note, so I see no reason the Windows behavior should change at all. When I argued for POSIX conformance I was thinking only of POSIX platforms. Sorry for not making that clear before.

However, let's go into that in some detail anyway. One of the Windows differences is that SHELL is inherited from the env, and if you're using that feature then "my" POSIX fix would have no effect even if implemented on Windows. So it only affects someone who might be setting SHELL _explicitly_ in a main Makefile and depending on its being automatically exported for use in sub-Makefiles. One might argue that even in this case, requiring

        export SHELL    := bash

would be both more intuitive and more self-documenting than

        SHELL   := bash

which codifies the hidden assumption that in GNU make SHELL, unlike any other make variable and unlike any other make program, will be automatically exported. However, I'm personally agnostic on the question of how SHELL is handled on Windows and will leave that to people using GNU make there.

It's worth reiterating the importance of POSIX on the Unix side, though. POSIX doesn't do invention, it describes existing behavior. Thus, "non-POSIX-conformant" is shorthand for "incompatible (in this way) with Solaris make, HPUX make, AIX make, and just about every other Unix make program". Which is how I ran across it in the first place and which is a pretty big deal, IMO.

Let me explain what I'm doing as an example of why it matters (note, this is Unix-specific). In my spare time, currently copious since I'm unemployed, I'm developing a build-auditing tool. The idea is you run a build under control of my program and it keeps a record of all files opened during that build. For anyone familiar with ClearCase the idea is to get something like its "config records" but without requiring the special ClearCase filesystem. Instead of communicating with the filesystem as ClearCase does, my tool inserts a shim into the shared-library call sequence using LD_PRELOAD and uses it to intercept and record uses of open() and related system calls. Consider it analogous to "truss -o /tmp/truss.out -f -t open,creat", more or less, but more portable and entirely in user space.

This is working pretty well. It would potentially let you replace or augment timestamp-based dependency analysis with checksum/CRC/MD5 'fingerprints' in the way cook et al do. I also have a sample impementation using it to generate full autodependencies very much in the manner of "gcc -MD" except, of course, for being language independent and getting ALL the dependencies.

So next I come to the question of how best to actually integrate it with make. The checksum-based dependency stuff would require major surgery on the make program (any make, not necessarily GNU) and I'm not ready to even consider that. But the auto dependency generation can, in theory, be easily integrated by telling make to run all build commands under control of the auditor. Imagine I set

        SHELL := truss -o /tmp/truss.out -f -t open,creat

(of course this wouldn't actually work because make assumes $SHELL to be a single word and insists on invoking it with a -c flag, not to mention truss would keep overwriting its tmp file, but you get the idea). If I do the above in any regular make, all my build commands will be run under control of truss and I'll get audits in /tmp. Very nice. If I do it with GNU make, my shell EV will become "corrupted: and if any child process does anything with it I'll end up with truss trussing truss. Very much not good. It boils down to the Heisenbergian principle: any auditor which has a profound effect on the process it's auditing is useless. And inadvertently changing the SHELL EV for all children is pretty profound; as you say it's one of the major Unix system EV's.

I do have the workaround Paul suggested of saving the 'real' value of SHELL aside as REAL_SHELL and setting SHELL=$REAL_SHELL in the auditor program. This works and I've used it for my proof of concept but it's offensive.

IMO the real problem is the overloading of the name $SHELL by make some 3 decades ago; there really is no correlation beween the concepts "what is my preferred shell?" and "what command to I want to use, within this particular Makefile, to control my build scripts?". The original author of make, observing that the answer to the latter question was most commonly /bin/sh, used SHELL for the macro that controlled it (early versions of make actually contained commented-out code to inherit SHELL, showing that he didn't realize his mistake till after the fact). The long-standing hack of not inheriting SHELL is really a workaround for the fact that he should have used, say, MAKECMD instead and had that default to /bin/sh without ever involving $SHELL.

FWIW GNU make already has something similar (MAKESHELL), though it's currently implemented only on Windows, but I'd argue that ideally the name wouldn't even contain the substring 'SHELL' because it implies that one must use a shell-like command. And I don't see why that constraint is necessary.

At the risk of being too wordy, let me pursue that angle a bit. Make novices often tend to act as if its only use is to compile C code and need to be reminded that it's really a general-purpose rules engine that can be used to manage anything involving targets, dependencies, and recipes. NIS databases are a classic example. But how general-purpose is it really? In the basic make rule:

targets: dependencies
        command ...

I can use absolutely any set of files for my targets and likewise for dependencies. But do I have the same range of options when it comes to 'command'? No. I'm constrained to running '/bin/sh -c "command ..."'. I can replace /bin/sh with another program but (a) it must accept -c and -e flags with similar semantics to /bin/sh and (b) to do it with GNU make I have to blow away my $SHELL environment var. In a really ideal world, MAKECMD could be assigned an arg vector allowing,say, {} or % to represent the "command ..." string but that's a pretty major change. Paul has said he's considered a SHELLFLAGS (aka MAKECMDFLAGS) which might be a reasonable compromise. Anyway, this is all blue sky stuff beyond the current question; I just bring it up to illustrate that make is noticeably less flexible than it could be when it comes to invoking recipes.

Summary time: my bottom line argument is that there is *no* logical correlation between a user's preferred shell and a Makefile's preferred command executor, and that GNU make should respect this boundary at least as much as POSIX does.

Sorry for the length.

-David Boyce

I don't see this issue affecting me much anytime soon, and probably i
ought to keep my mouth shut. But I found myself provoked in a wondering
kind of way.

I am "provoked" into having questions about the meaning of all this. It
seems to me that "What You Expect (tm)" would be for any subprocess (sub
shell, child process) to inherit the setting for "SHELL" that is in
effect in the Makefile. I strain my meager experience to think of a
situation in which you'd want child processes of 'make' to have a value
of SHELL that's different in the environment of that process than it is
in the value of the 'make' macro 'SHELL'. To what possible end would
such an inconsistency be maintained? Can anyone give me an example?

As a 'make' user on a platform that requires shell issues to be handled
differently (historically always has -- Windows / DOS) I am also
wondering how an attempt to change the behavior of 'make' in the manner
David Boyce seems to be suggesting would impact me and those like me. It
appears IMHO that we totally rely on 'make' setting SHELL in the
environment of child processes since we cannot be guaranteed otherwise
that SHELL will be useful or correct -- the native "shell"-like entity
on our platforms being basically a big problem issue that many have
sought to avoid by installing a foreign, ported Bourne-compatible shell
(sh, bash, zsh, ksh).

To sum up, my possibly naive understanding is that one would ordinarily
expect the setting for a parameter of such a primary importance as SHELL
to be propagated to all children -- and to their children, which is what
we are talking about right? -- of the 'make' application. We who have
any familiarity with 'make' at all understand how SHELL is already
specially-treated in that there is a "no-inherit" policy on *nix-ish
platforms and a differing "inherit" policy on DOS/Win -ish ones; and it
seems to me that layering on additional complexity (that 'make's idea of
SHELL and 'make's children's idea of SHELL would possibly differ) to
that already complex situation simply makes things harder for users
without achieving any practical improvement for anybody?

   Regards,
    Soren A




_______________________________________________
Make-alpha mailing list
address@hidden
http://mail.gnu.org/mailman/listinfo/make-alpha

--
-------------------------------------------------------------------------------
 Paul D. Smith <address@hidden>          Find some GNU make tips at:
 http://www.gnu.org                     http://make.paulandlesley.org
"Please remain calm...I may be mad, but I am a professional." --Mad Scientist






reply via email to

[Prev in Thread] Current Thread [Next in Thread]