bug-make
[Top][All Lists]
Advanced

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

Re: .ONESHELL enhancements


From: Paul Smith
Subject: Re: .ONESHELL enhancements
Date: Thu, 14 Nov 2013 14:20:45 -0500

On Thu, 2013-11-14 at 11:05 -0700, Eric Blake wrote:
> Hello GNU make hackers,

Hi Eric.

> In today's Austin Group meeting (the people working on POSIX), we
> discussed an interesting proposal:
> 
> http://austingroupbugs.net/view.php?id=770

I'm subscribed to the mailing list and follow the various bug reports,
so I'm familiar with these efforts.

> Possible ideas mentioned on today's call:
> 
> * Add a .ENDONESHELL special target, so that .ONESHELL and .ENDONESHELL
> can be used in pairs to bracket sections of the makefile that have
> one-shell semantics.  But then you have to distinguish between .ONESHELL
> used in isolation for a global effect, even for earlier lines, vs.
> .ONESHELL/.ENDONESHELL used in pairs to leave earlier lines unchanged.
> Furthermore, in the case of included files, you really want push/pop
> semantics, where you push into .ONESHELL mode at the top of your file,
> then pop back into the prior mode (whether that was oneshell or
> multi-shell) at the end to leave the outer file semantics unchanged,
> rather than unconditionally turning oneshell off.

I am not excited by this option.  There is nothing like it currently
existing in make, for one thing.  Further even the above description is
not so well-defined for corner-cases: it feels too complex.  If we're
going to provide some kind of scoping capability for makefiles (which I
readily admit would be a big advance for complex makefile writing) then
I'd prefer to find something which can be more generally applied and
extended, and solves a larger set of problems.

> * Enhance .ONESHELL to behave more like .IGNORE, where one could write:
> 
> .ONESHELL: foo
> foo: bar
>       echo 1 &&
>       echo 2
> 
> where only the targets listed as prereqs of .ONESHELL are given oneshell
> semantics, and all other targets remain multi-shell.  If .ONESHELL is
> listed without prereqs, then it maintains its current meaning of a
> global switch for all targets.

This is the option that best follows existing practice, and is most
backward-compatible with existing behavior in GNU make.

However, there's something critical missing here: the treatment of
targets in implicit rules.  How does one apply .ONESHELL to a suffix
rule definition?  GNU make also supports pattern rules, so whatever
behavior is chosen would need to extend to pattern rules as well.  And
of course how to handle pattern rules with multiple targets needs to be
addressed; what if one of the target patterns appeared as a prerequisite
of .ONESHELL, and another did not?

> * Enhance .ONESHELL to be useful as a prerequisite, as in:
> 
> foo: bar .ONESHELL
>       echo 1 &&
>       echo 2
> 
> where the use of .ONESHELL as a target makes it obvious that foo will be
> executed differently (and where you don't have to search possibly many
> lines away to see if any .ONESHELL: list included foo in the list).
> [For that matter, could .IGNORE also be enhanced to be used as a prereq,
> in addition to its current semantics of being listed as the target whose
> prereqs have changed behavior?]

This is a very interesting idea.  There's no existing precedent for it
that I'm aware of, but it could nicely solve the problems of implicit
rules for example.

I don't think the "action at a distance" argument is compelling, unless
you made the additional requirement that .ONESHELL can only be provided
in the rule that defines the recipe; otherwise someone could have added
"foo: .ONESHELL" somewhere else just as easily.

Certainly some extra verbage would need to be added when discussing
automatic variables such as $^, to ensure that these special targets
would not be included in those variables.

It would be possible to add this behavior to .IGNORE (etc.) as well,
yes.

> * Add a .MULTISHELL or some other name to temporarily undo the effect of
> global .ONESHELL.  Again, being able to select groups of targets rather
> than being just an on-off switch would make this more appealing.

I don't think this is a good solution.  It's simple but it would be
pretty difficult to use correctly in the "library of included files"
scenario you've described for example.

> * Add a new special character, which if first in a recipe, means that
> individual recipe uses oneshell semantics (probably less appealing than
> the idea of an explicit prerequisite).

I'm not a fan of this one.  First we'd have to find a suitable
character: as David has pointed out in discussion the original proposal
of "~" is not workable.  This may not be insurmountable however.  I
worry that this is far too big of a hammer to use with this particular
nail.  There are very few prefix characters today, and adding new ones
is fraught with issues.  I feel like using one for this (useful, but IMO
relatively minor) feature is not appropriate.

Also it feels a little strange in that each line of a recipe can have
its own prefix characters... so what if "~" is added to a line in the
middle of a recipe?  Is it ignored?  Seems odd.  If not, does it mean
that starting from that line to the rest of the recipes are all given to
one shell?  Does each individual line have to use the prefix character
to ensure that it goes to the same shell (so if you don't give it for
one line it starts a different shell)?

I think any new prefix characters should be reserved for features which
are really intended to apply on a per line basis, and thus we really
need that power, and not something which is really per-target anyway.

And for GNU make, which will of course continue to support the
current .ONESHELL semantics, it's not clear how a "partial"
implementation (some lines ONESHELL, some not) would interact with a
global .ONESHELL setting.


>From the standpoint of implementation, beyond parsing complexities
(which are mostly straightforward from what I see) the work required for
any of these proposals would be minimal: we'd simply need to add a
per-target flag and check it in addition to the existing global flag in
the appropriate places.




reply via email to

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