Re: Is it possible to break from a GMAKE foreach loop and then exit from make?

Pierre Rouleau <[email protected]>
Newsgroups gmane.comp.gnu.make.general
Message-ID <CALTqLia2Hc1RRyfAUrO9JSWzFdqCuaODX3=JTUvWuFKPFn5b2Q@mail.gmail.com>
On Sat, May 28, 2022 at 2:11 AM Kaz Kylheku <[email protected]> wrote:

> On 2022-05-27 06:35, Pierre Rouleau wrote:
> > Hi all,
> >
> > I have a makefile tha patches the kernel but does not check if the patch
> > succeeded.
> > The rule is shown below.  It uses a foreach loop to apply a set of
> patches
> > identified by
> > a list of patches.
> >
> > Is it possible to use the `|| exit 1' construct inside the text portion
> of
> > the foreach loop to detect
> > failing patches and stop make execution?
>
> As you know, foreach is run by Make, like a macro. The generated shell code
> then performs exit detection.
>
> What you probably want is to generate clauses joined by &&
>
>   $(foreach ....) --> patch < this && patch < that && ... && patch < last
>
> You mean unroll the loop manually?
Unfortunately the file I'm dealing with is part of a *large* build system
with over 2000 make file, with make recursion and multi-layer decision
making
 that end up building the list of patch files, storing it inside a
variable.

Are you also saying that adding `|| exit 1' to the statement inside the
foreach loop would not work?
ie as in:
        (cd $(OUTPUT_ROOT_DIR)/$(CFG_GLOBAL_LINUX_VERSION); $(foreach
thepatch,$(KERNEL_PATCH_ONE),echo patching $(thepatch); patch
--ignore-whitespace -p1 < $(thepatch) || exit 1;))



> I believe that "set -e" also works, keeping in mind that each recipe
> line is run in a separate shell invocation (in the absence of .ONESHELL:
> being used).
>
> So that is to say:
>
>    target: prereq
>         set -e; command; command; command; ...
>
> with set -e, the shell will bail upon the first unsuccessful command,
> with a failed termination status, much like the way Make bails on the
> first unsuccessful recipe line.
>
> Compare the effect of removing "set -e" from this Makefile:
>
>   .PHONY: all
>
>   all:
>         set -e; echo foo; false; true
>
> Interesting: with set -e it stops on false, without it, it completes as if
everything was fine.
In the end do you mean that all I could do is prepend the rule with  `set
-e; ' and that would ensure termination on the first error?
As in:
         set -e; (cd $(OUTPUT_ROOT_DIR)/$(CFG_GLOBAL_LINUX_VERSION);
$(foreach thepatch,$(KERNEL_PATCH_ONE),echo patching $(thepatch); patch
--ignore-whitespace -p1 < $(thepatch)))



>
> >
> > ie, Is it possible to transform the following:
> >
> > $(OUTPUT_ROOT_DIR)/.kernel_patched: $(OUTPUT_ROOT_DIR)/.kernel_original
> >         @echo -e "Applying only specific patch to kernel"
> >         (cd $(OUTPUT_ROOT_DIR)/$(CFG_GLOBAL_LINUX_VERSION); $(foreach
> > thepatch,$(KERNEL_PATCH_ONE),echo patching $(thepatch); patch
> > --ignore-whitespace -p1 < $(thepatch);))
> >
> >
> > into this and is it the best way or are there better alternatives?
>
> The better alternative is to patch like it's 2002 and use the quilt
> program.
>
> I agree that it'd be nice to use quilt, unfortunately, the work
environment I have to deal with is somewhat constrained...
However, thanks for the advice, I might be able to use it in other
circumstances.

-- 
/Pierre
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.