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 16:20:01 +0800

On Fri, Jan 21, 2022 at 9:24 AM 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 ().
> >
> > 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)

I wonder if the followin formats shoud be used here?

  @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]