title: How to get the exit status and the output of a $(shell command) before make 4.2?
body: <p>On <a href="https://fossies.org/diffs/make/4.1_vs_4.2/NEWS-diff.html" rel="nofollow noreferrer">make version 4.2 {2016}</a> was added the variable <code>.SHELLSTATUS</code>. But my most linux are using make version <code>4.1</code>. How I can I get the exit status and the output results of the make $(shell ...) command on older make versions?</p>
  
  <p>With make 4.2, I can do this:</p>
  
  <pre><code>newmake:
      printf '%s\n' "$(shell command &amp;&amp; \
          ( printf 'Successfully created the zip file!\n'; exit 0 ) || \
          ( printf 'Error: Could not create the zip file!\n'; exit 1 ) )"
      printf 'Exit status: '%s'\n' "${.SHELLSTATUS}"
  </code></pre>
  
  <p>Which run correctly:</p>
  
  <pre><code>printf '%s\n' "Successfully created the zip file!"
  Successfully created the zip file!
  printf 'Exit status: '%s'\n' "0"
  Exit status: 0
  </code></pre>
  
  <p>But, if I am using make 4.1 or older, there is no <code>.SHELLSTATUS</code> variable. Then, I am trying to define my own <code>.SHELLSTATUS</code> variable like this:</p>
  
  <pre><code>oldmake:
      printf '%s\n' "$(shell command &amp;&amp; \
          ( printf 'Successfully created the zip file!\n'; $(eval exit_status := 0) echo ${exit_status} &gt; /dev/null ) || \
          ( printf 'Error: Could not create the zip file!\n'; $(eval exit_status := 1) echo ${exit_status} &gt; /dev/null ) )"
      printf 'Exit status: '%s'\n' "${exit_status}"
  </code></pre>
  
  <p>But, it does not run correctly:</p>
  
  <pre><code>printf '%s\n' "Successfully created the zip file!"
  Successfully created the zip file!
  printf 'Exit status: '%s'\n' "1"
  Exit status: 1
  </code></pre>
  
  <p>As you can see, the right message was print, but the exit status should be <code>0</code>, not <code>1</code>. </p>
  
  <h3>Notice</h3>
  
  <p>The messages <code>Successfully created the zip file!</code> and <code>Error: Could not create the zip file!</code> are purely illustrative and cannot be used outside <code>$(shell ...)</code>. What do I have inside shell is a full featured <code>Python</code> script which outputs its results to the screen:</p>
  
  <pre><code>define NEWLINE
  
  
  endef
  
  define RELEASE_CODE
  from __future__ import print_function
  import os
  import zipfile
  
  version = "${version}"
  if not version:
      print( "Error: You need pass the release version. For example: make release version=1.1", end="@NEWNEWLINE@" )
      exit(1)
  
  CURRENT_DIRECTORY = os.path.dirname( os.path.realpath( __file__ ) )
  print( "Packing files on %s" % CURRENT_DIRECTORY, end="@NEWNEWLINE@" )
  
  file_names = []
  initial_file_names = [
      "Makefile",
      "build.bat",
      "fc-portuges.def",
      os.path.join("setup", "makefile.mk"),
      os.path.join("setup", "scripts", "timer_calculator.sh"),
  ]
  
  for direcory_name, dirs, files in os.walk(CURRENT_DIRECTORY):
  
      if ".git" in direcory_name:
          continue
  
      for filename in files:
          filepath = os.path.join( direcory_name, filename )
  
          if ".git" in filepath or not ( filepath.endswith( ".tex" )
                  or filepath.endswith( ".bib" )
                  or filepath.endswith( ".pdf" ) ):
              continue
  
          file_names.append( filepath )
  
  for filename in initial_file_names:
      filepath = os.path.join( CURRENT_DIRECTORY, filename )
      file_names.append( filepath )
  
  zipfilepath = os.path.join( CURRENT_DIRECTORY, version + ".zip" )
  zipfileobject = zipfile.ZipFile(zipfilepath, mode="w")
  zipfilepathreduced = os.path.dirname( os.path.dirname( zipfilepath ) )
  
  try:
      for filename in file_names:
          relative_filename = filename.replace( zipfilepathreduced, "" )
          print( relative_filename, end="@NEWNEWLINE@" )
          zipfileobject.write( filename, relative_filename, compress_type=zipfile.ZIP_DEFLATED )
  
  except Exception as error:
      print( "", end="@NEWNEWLINE@" )
      print( "An error occurred: %s" % error, end="@NEWNEWLINE@" )
      exit(1)
  
  finally:
      zipfileobject.close()
  
  print( "", end="@NEWNEWLINE@" )
  print( "Successfully created the release version on:@NEWNEWLINE@  %s!" % zipfilepath , end="" )
  endef
  
  all:
      printf '%s\n' "$(shell echo \
          '$(subst ${NEWLINE},@NEWLINE@,${RELEASE_CODE})' | \
          sed 's/@NEWLINE@/\n/g' | python - &amp;&amp; \
          printf 'Successfully created the zip file!\n' || \
          printf 'Error: Could not create the zip file!\n' )" | sed 's/@NEWNEWLINE@/\n/g'
  </code></pre>
  
  <p>Now it runs correctly, but I am missing the python exit code, which can be fixed with this <code>.SHELLSTATUS</code>:</p>
  
  <pre><code>all:
      printf '%s\n' "$(shell echo \
          '$(subst ${NEWLINE},@NEWLINE@,${RELEASE_CODE})' | \
          sed 's/@NEWLINE@/\n/g' | python - &amp;&amp; \
          ( printf 'Successfully created the zip file!\n'; exit 0 ) || \
          ( printf 'Error: Could not create the zip file!\n'; exit 1 ) )" | sed 's/@NEWNEWLINE@/\n/g'
      exit "${.SHELLSTATUS}"
  </code></pre>
  
  <p>But, it only works for make version <code>4.2</code> or newer.</p>
  
  <p>Related:</p>
  
  <ol>
  <li><a href="https://askubuntu.com/questions/93499/assign-standard-exit-status-to-a-makefile-variable">https://askubuntu.com/questions/93499/assign-standard-exit-status-to-a-makefile-variable</a></li>
  <li><a href="https://stackoverflow.com/questions/8742783/returning-value-from-called-function-in-a-shell-script">Returning value from called function in a shell script</a></li>
  <li><a href="https://stackoverflow.com/questions/16315089/how-to-get-exit-status-of-a-shell-command-used-in-gnu-makefile">How to get exit status of a shell command used in GNU Makefile?</a></li>
  <li><a href="https://stackoverflow.com/questions/50817458/how-to-make-gnu-make-fail-if-a-shell-command-assigned-to-a-variable-failed">How to make GNU Make fail if a shell command assigned to a variable failed?</a></li>
  <li><a href="https://stackoverflow.com/questions/748445/shell-status-codes-in-make">Shell status codes in make</a></li>
  <li><a href="https://stackoverflow.com/questions/39767904/create-zip-archive-with-multiple-files">Create zip archive with multiple files</a></li>
  <li><a href="https://stackoverflow.com/questions/47588379/zip-multiple-files-with-multiple-result-in-python">Zip Multiple files with multiple result in Python</a></li>
  <li><a href="https://stackoverflow.com/questions/16091904/python-zip-how-to-eliminate-absolute-path-in-zip-archive-if-absolute-paths-for">python/zip: How to eliminate absolute path in zip archive if absolute paths for files are provided?</a></li>
  <li><a href="https://stackoverflow.com/questions/55681576/how-to-send-input-on-stdin-to-a-python-script-defined-inside-a-makefile">How to send input on stdin to a python script defined inside a Makefile?</a></li>
  </ol>