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: Hongyi Zhao
Subject: Re: Can the exit status of the code block in @(...) be obtained from outside the @() structure?
Date: Fri, 21 Jan 2022 09:24:29 +0800

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 ().
>
> 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.
>
> 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 \
>

Based on your comments above, I've now rewritten the original script
into the following:

```
# Copyright (C) 2001-2016 Quantum ESPRESSO group
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License. See the file `License' in the root directory
# of the present distribution.
#
# Utilities

###########################################################
# Template function
# $(1) = package name
# $(2) = package URL
# $(3) = directory name
# $(4) = plugin/code name
###########################################################

define download_and_unpack
  @package = $(1)
  @package_URL = $(2)
  @package_directory = $(3)
  @package_code = $(4)
  @package_archive = ../archive/`echo "$(package)" | sed 's/.*\///;s/.*=//'`

  @(
  if ! gzip -t $(package_archive) > /dev/null 2>&1 ; then \
    rm -fr $(package_archive); \
    rm -fr ../$(package_directory); \
    wget -O $(package_archive) $(package_URL) > /dev/null 2>&1; \
    if [ $$? -ne 0 ]; then \
      curl -o $(package_archive) $(package_URL) > /dev/null 2>&1; \
      if [ $$? -ne 0 ]; then \
        echo "*** Unable to download $(package_code). Test whether
curl or wget is installed and working," ; \
        echo "*** if you have direct access to internet. If not, copy
into archive/ the file" ; \
        echo "*** located here $(package_URL)" ; \
        exit 1 ; \
      fi ; \
    fi ; \
  fi
  ) ; \
  if [ $$? -eq 0 -a ! -e ../$(package_directory) ]; then \
    (gzip -dc $(package_archive) | \
    (cd ../ ; tar -xvf - )) ; \
    if [ $$? -ne 0 ]; then \
      echo "*** Unable to download $(package_URL)." ; \
      echo "*** Verify that the url is correct." ; \
      exit 1 ; \
    else \
      (cd ../ ; ln -s $(package) $(package_directory)) ; \
    fi ; \
  fi
endef
``

However, the following error will be triggered when compiling one of
the targets:
```
$ git log -1
commit ee54a437ab630be869cd12aa767418303f530e8d (HEAD -> develop,
origin/develop, origin/HEAD, hongyi-zhao/develop)
Merge: 98866d877 f35839efb
Author: giannozz <paolo.giannozzi@uniud.it>
Date:   Thu Jan 20 13:25:47 2022 +0000

    Merge branch 'develop' into 'develop'

    Enhance the robustness of `install/install_utils` script.

    See merge request QEF/q-e!1722


$ module load mkl mpi compiler
$ ./configure --with-scalapack=intel MPIF90=mpiifort
$ make -j44 all
$ make -j44 w90
test -d bin || mkdir bin
cd install ; make -f extlibs_makefile liblapack
make[1]: Entering directory '/home/werner/q-e/install'
make[1]: Nothing to be done for 'liblapack'.
make[1]: Leaving directory '/home/werner/q-e/install'
( cd install ; make -f plugins_makefile w90 || exit 1 )
make[1]: Entering directory '/home/werner/q-e/install'
make[1]: package: Command not found
make[1]: *** [plugins_makefile:94: uncompress-w90] Error 127
make[1]: Leaving directory '/home/werner/q-e/install'
make: *** [Makefile:239: w90] Error 1

```
What is going on here, and where is my mistake? See here [1] for some
relevant discussion.

[1] https://gitlab.com/QEF/q-e/-/issues/454

Regards,
HZ



reply via email to

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