rmyorston / busybox-w32

WIN32 native port of BusyBox.
https://frippery.org/busybox
Other
670 stars 124 forks source link

Commands after semicolon are not executed in Makefile #409

Closed smalltalkman closed 4 months ago

smalltalkman commented 4 months ago

When executing the following Makefile snippet:

check-regression: tests/config-flags.pm
    @rm -f $(testfiles)
    if test -f '$(top_srcdir)/tests/run_make_tests'; then \
      if $(PERL) -v >/dev/null 2>&1; then \
        case `cd '$(top_srcdir)'; pwd` in `pwd`) : ;; \
          *) test -d tests || mkdir tests; \
         rm -f srctests; \
         if ln -s '$(top_srcdir)/tests' srctests; then \
           for f in run_make_tests run_make_tests.pl test_driver.pl scripts thelp.pl; do \
             rm -f tests/$$f; ln -s ../srctests/$$f tests; \
           done; fi ;; \
        esac; \
        echo "cd tests && $(PERL) $(PERLFLAGS) ./run_make_tests.pl -srcdir $(abs_top_srcdir) -make $(GMK_OUTDIR)/make$(EXEEXT) $(MAKETESTFLAGS)"; \
        (cd tests && $(PERL) $(PERLFLAGS) ./run_make_tests.pl; echo $$? >.test-result) 2>&1 | tee $(testlog); \
        er=$$(cat $(testresult)); if test "$$er" -ne 0; then \
          dirnm="$(errorpre)-$$($(rand_string))"; fnm="$$dirnm.tar.gz"; \
          rm -rf "$$dirnm"; mkdir "$$dirnm"; \
          $(AMTAR) chf - $(errordetails) | (cd "$$dirnm"; $(AMTAR) xf -); \
          $(AMTAR) chf - "$$dirnm" | eval GZIP= gzip $(GZIP_ENV) -c >"$$fnm"; \
          echo "*** Testing FAILED!  Details: $$fnm"; \
          echo '*** Please report to <$(PACKAGE_BUGREPORT)>'; echo; \
          exit $$er; \
        fi; \
      else \
        echo "Can't find a working Perl ($(PERL)); the test suite requires Perl."; \
      fi; \
    else \
      echo "Can't find the $(PACKAGE_NAME) test suite ($(top_srcdir)/tests)."; \
    fi

Actual execution of the command:

if test -f './tests/run_make_tests'; then \
  if perl -v >/dev/null 2>&1; then \
    case `cd '.'; pwd` in `pwd`) : ;; \
      *) test -d tests || mkdir tests; \
         rm -f srctests; \
         if ln -s './tests' srctests; then \
           for f in run_make_tests run_make_tests.pl test_driver.pl scripts thelp.pl; do \
             rm -f tests/$f; ln -s ../srctests/$f tests; \
           done; fi ;; \
    esac; \
    echo "cd tests && perl  ./run_make_tests.pl -srcdir D:/gym/softwares/busybox/home/root/make-4.4.1 -make ../make.exe "; \
    (cd tests && perl  ./run_make_tests.pl; echo $? >.test-result) 2>&1 | tee test-suite.log; \
    er=$(cat tests/.test-result); if test "$er" -ne 0; then \
      dirnm="makeerror-4.4.1-x86_64-w64-mingw32-$(awk 'BEGIN{srand(); c = "abcdefghijklmnopqrstuvwxyz0123456789"; print substr(c,int(rand()*36),1) "" substr(c,int(rand()*36),1) "" substr(c,int(rand()*36),1) "" substr(c,int(rand()*36),1);}')"; fnm="$dirnm.tar.gz"; \
      rm -rf "$dirnm"; mkdir "$dirnm"; \
      ${TAR-tar} chf - config.status config.log src/config.h src/mkconfig.h  test-suite.log tests/work | (cd "$dirnm"; ${TAR-tar} xf -); \
      ${TAR-tar} chf - "$dirnm" | eval GZIP= gzip --best -c >"$fnm"; \
      echo "*** Testing FAILED!  Details: $fnm"; \
      echo '*** Please report to <bug-make@gnu.org>'; echo; \
      exit $er; \
    fi; \
  else \
    echo "Can't find a working Perl (perl); the test suite requires Perl."; \
  fi; \
else \
  echo "Can't find the GNU Make test suite (./tests)."; \
fi

When perl ./run_make_tests.pl returns non-zero, the command echo $? >.test-result in (cd tests && perl ./run_make_tests.pl; echo $? >.test-result) 2>&1 | tee test-suite.log; was not executed.

Executing (cd tests && perl ./run_make_tests.pl; echo $? >.test-result) 2>&1 | tee test-suite.log; in sh can get the correct results.

Similar to (https://github.com/rmyorston/busybox-w32/issues/408), subsequent commands continue to run when using gnu make (although busybox sh is still used). The difference is that (https://github.com/rmyorston/busybox-w32/issues/408) the reason is that the command ulimit cannot be found, while the current scenario is that the perl script returns a non-zero value.

rmyorston commented 4 months ago

OK, I think I see what's going on. The POSIX standard for make says:

The execution line shall then be executed by a shell as if it were passed as the argument to the system() interface, except that if errors are not being ignored then the shell -e option shall also be in effect.

However, it seems that modern versions of make (GNU and BSD) don't set the shell -e option when executing commands, whereas make in busybox-w32 did. As a result any failure of a command in a synchronous list like false; echo OK would cause the target to fail.

I've altered busybox-w32 make to skip the shell -e option, as an extension. The strict POSIX behaviour still applies in POSIX mode, but that isn't the default.

Please try the latest prerelease binary (PRE-5327 or above).

smalltalkman commented 4 months ago

Please try the latest prerelease binary (PRE-5327 or above).

Great, it works fine:

# 
# wget https://ftp.gnu.org/gnu/make/make-4.4.1.tar.gz
# tar -zxvf make-4.4.1.tar.gz
# 
# cp -rp    make-4.4.1 make-4.4.1.orig
# cd        make-4.4.1
# 
# ./configure --build=$(gcc -dumpmachine) --prefix=$ROOT/usr/local
# 
# install_busybox
# 
# make
# make check
# make install
# make uninstall
# 
# uninstall_busybox
# 

It would be nice if busybox-w32 make could call internal commands directly. I now have to install busybox to PATH in order to use make. (I am not familiar with busybox architecture, please ignore my ignorance)

rmyorston commented 4 months ago

It would be nice if busybox-w32 make could call internal commands directly. I now have to install busybox to PATH in order to use make.

I'm not sure why that would be. busybox-w32 make should always use the busybox-w32 shell to run commands so no reference to PATH should be necessary.

smalltalkman commented 4 months ago

It would be nice if busybox-w32 make could call internal commands directly. I now have to install busybox to PATH in order to use make.

After detailed testing, it was confirmed that the commands that need to be installed in the PATH are all called by creating a new process by gnu make during the make check process, so they have nothing to do with busybox-w32 make.