On Wed, Jan 19, 2022 at 2:56 AM Paul Smith <psm...@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? > 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