help-make
[Top][All Lists]
Advanced

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

Re: Can the exit status of the code block in @(...) be obtained from out


From: Britton Kerin
Subject: Re: Can the exit status of the code block in @(...) be obtained from outside the @() structure?
Date: Tue, 18 Jan 2022 18:59:27 -0900

On Tue, Jan 18, 2022 at 4:51 PM Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
>
> On Wed, Jan 19, 2022 at 2:56 AM Paul Smith <psmith@gnu.org> wrote:
> >
> > On Tue, 2022-01-18 at 10:14 +0800, Hongyi Zhao wrote:
> > > But it seems that the `$?' used above can't obtain the exit status of
> > > the code block in @(...) when used from outside the @() structure
> > > [2].  So, I want to know if I can reliably obtain the exit status of
> > > the code block in @(...) from outside the @() structure. Any hints
> > > will be greatly appreciated.
> >
> > First, of course you must use $$? not $?, because $? is a shell
> > variable not a make variable so you must escape it from make.
> >
> > Second, there's nothing magical about ().
>
> So, I would like to know when I should use () to group some commands
> and when not.
>
> > All versions of make, including GNU make, invoke each logical line of
> > the recipe in a separate shell.  There is no interaction between two
> > different shells: the exit code of one shell cannot be accessed by a
> > sibling shell.
> >
> > A rule like this:
> >
> >     foo:
> >             (exit 1)
> >             echo $$?
> >
> > causes make to invoke two different shells:
> >
> >   /bin/sh -c '(exit 1)'
> >   /bin/sh -c 'echo $?'
> >
> > The exit code of the first shell is not put into the $? variable of the
> > second shell.
> >
> > If you want to access the exit code of a previous command you must put
> > them both into the same shell, which means they both need to be in the
> > same logical line of the recipe.  So, this rule:
> >
> >     foo:
> >             (exit 1) ; \
> >             echo $$?
> >
> > invokes a single shell command:
> >
> >   /bin/sh -c '(exit 1) ; echo $?'
> >
> > now it will work as you expect.
>
> But see the following testings:
>
> werner@X10DAi-00:~$ /bin/sh -c '(exit 1); echo $?'
> 1
> werner@X10DAi-00:~$ /bin/sh -c 'exit 1; echo $?'
> werner@X10DAi-00:~$
>
> Why must I use () here, otherwise, the exit code will not be captured?

In the first case a subshell is started (via () syntax)) and immediately
exits with exit code 1; the subsequent echo $? prints the exit code of
that subshell.

In the second case exit 1 is performed first from the same shell that
was intended to execute the echo, and the echo never happens.

Britton

>
>
> > So, in your makefile rule, you just need to make sure that you add
> > semicolons and backslashes to ensure that the recipe is treated as one
> > logical line; change:
> >
> >   echo "*** located here $(2)" ; \
> >   exit 1 ; fi ; fi ; fi)
> >   if test $? -eq 0 -a ! -e ../$(3); then \
> >
> > to add the semicolon / backslash:
> >
> >   echo "*** located here $(2)" ; \
> >   exit 1 ; fi ; fi ; fi) ; \
> >   if test $$? -eq 0 -a ! -e ../$(3); then \
>
> Thank you for your correction.
>
> HZ
>



reply via email to

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