Re: .ONESHELL enhancement?
Paul Smith <[email protected]>
| Newsgroups | gmane.comp.gnu.make.devel |
|---|---|
| Organization | GNU's Not Unix! |
| Message-ID | <[email protected]> |
On Tue, 2009-09-22 at 18:43 -0400, David Boyce wrote: > On Tue, Sep 22, 2009 at 3:34 PM, Paul Smith <[email protected]> wrote: > > I can't speak to the Windows implementation, but why do you need to do > > any translation of the script on POSIX systems? You can pass a string > > containing a newline to the shell and it will work; you don't have to > > add in "&&" or ";" or anything. > > Because the semantics are different. Newline behaves more like ; than > &&, and for .ONESHELL too work we need && semantics. What you mean here is that to make .ONESHELL behavior be identical to current GNU make behavior, except that you get a potential performance boost and some simplicity in scripting, you would need && semantics. It would still WORK without them, it's just that error handling would be different. However, I'm not necessarily convinced by this argument. First, note that the latest POSIX standard mandates that make invoke shells with "set -e" enabled by default (a change, and a very serious one, from previous standards). If you follow the standard here then adding "&&" is NOT required, since the script will error out immediately anyway due to -e. Thus I don't think the standard intends that we should add "&&" at all. Unfortunately, GNU make does not (any longer) follow the standard here, so we're kind of stuck. I'm actually quite uneasy about attempts to interpret and modify the recipe string, even with something as ostensibly simple as concatenating logical lines with "&&". IME, it's always very dangerous and difficult to make these kinds of changes without incurring nasty side-effects. I think some of the examples Matt gives are quite telling: if a stated goal of .ONESHELL is to reduce the need for many continued lines then adding "&&" can cause problems: really instead of the fairly straightforward "the entire recipe is passed, as-is, to the shell", we have to discuss that each logical line in the recipe must be a self-enclosed shell statement. Take Matt's example here: > foo: bar > if test -s $< > then > echo 'nonempty' >$@ > else > echo 'empty' >$@ > fi This cannot work; ALL of these must use backslashes: foo: bar if test -s $<; then \ echo 'nonempty' >$@; \ else \ echo 'empty' >$@; \ fi I really don't see how you simplify your recipe writing in this situation: any complex recipe must continue to use backslashes to be sure that "&&" is not introduced where it's not wanted/valid. That's not even mentioning what happens if SHELL is set to something that's not a POSIX shell; if we have .ONESHELL it becomes (IMO) more likely someone will want to use a separate script interpreter like Perl or whatever (yes, I remember the -c flag problem but this can be worked around). Do we only add "&&" if we know we have a POSIX shell (similar to the fastpath computation)? This gets more and more complex. Instead, I would prefer to keep this simple. It's not identical in behavior to just pass the string unmodified, but it's very easy to understand what will happen and what make will do. People who want identical behavior add "set -e" in their scripts, maybe? At the same time I'd like to figure out what to do about this new POSIX requirement that we use -e: maybe if we can solve this, then the previous issue will not be such a problem. The last time this came up we discussed changing the shell invocation to "-e" by default if the .POSIX pseudo-target was set; I think this is the least we should do. I don't really like that the behavior changes in this somewhat magical way when you set .POSIX though. I do wonder how many makefiles will actually break if we make this change permanent even without .POSIX set. Another thing I've wanted to do for a long time was introduce a variable that controls the flags used with the shell. Right now we have hard-coded "-c" as the flag, but it would be really great if people could change this. Maybe a make variable like .SHELLFLAGS with a default value of "-c" (no quotes of course)? Then people could set it to "-ec" to get POSIX behavior, or even "-xec" for debugging. And, if they wanted to set SHELL to /usr/bin/perl they could set .SHELLFLAGS to "-e". Alternatively along with this flag we could introduce POSIX behavior as the default, then people whose makefiles didn't work that way could set .SHELLFLAGS to just "-c". -- ------------------------------------------------------------------------------- Paul D. Smith <[email protected]> Find some GNU make tips at: http://www.gnu.org http://make.mad-scientist.net "Please remain calm...I may be mad, but I am a professional." --Mad Scientist