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