#635646 make: please fall back to system() when command is not found on $PATH

Package:
make
Source:
make-dfsg
Description:
utility for directing compilation
Submitter:
Jonathan Nieder
Date:
2023-02-13 14:48:07 UTC
Severity:
wishlist
Tags:
#635646#5
Date:
2011-07-27 21:15:22 UTC
From:
To:
Hi,

Trying the following makefile:

	test:
		command -v ls

I get the following result:

	$ make
	command -v ls
	make: command: Command not found
	make: *** [test] Error 127
	$ sh -c 'command -v ls'
	/bin/ls

but POSIX sayeth

| An execution line is built from the command line by removing any
| prefix characters. Except as described under the at-sign prefix, the
| execution line shall be written to the standard output, optionally
| preceded by a <tab>. The execution line shall then be executed by a
| shell as if it were passed as the argument to the system( ) interface,
| except that the shell −e option shall also be in effect.

The cause is that "make" expects to be run on a POSIX system, where
non-special shell builtins like "command" would be available for use
by execvp (see sh_cmds[] in job.c).  See the explanation by Jilles
Tjoelker at
http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=43;bug=436466
for more details.

I can imagine two fixes, and both seem separately valuable:

 a. one hand hand, introducing a new package to provide those
    non-special builtins that are not provided by some pseudo-essential
    package (using alternatives to deal with alternative
    implementations where necessary):

	#!/bin/sh
	command -p ${0##*/} "$@"

 b. on the other hand, teaching "make" to handle ENOENT from execvp by
    falling back to the shell.  (The shell can print a message about
    it if that ENOENT was actually due to a missing shared library or
    interpreter.)  This way, "make" could even use shell builtins that
    are not mandated by POSIX when the system shell happens to
    implement them.

This report is about (b).  Thoughts?

#635646#10
Date:
2016-02-16 20:34:38 UTC
From:
To:
URL:
  <http://savannah.gnu.org/bugs/?47171>

                 Summary:  please fall back to system() when command is not
found on $PATH
                 Project: make
            Submitted by: srivasta
            Submitted on: Tue 16 Feb 2016 02:34:37 PM CST
                Severity: 3 - Normal
              Item Group: Enhancement
                  Status: None
                 Privacy: Public
             Assigned to: None
             Open/Closed: Open
         Discussion Lock: Any
       Component Version: None
        Operating System: None
           Fixed Release: None
           Triage Status: None

#635646#13
Date:
2016-02-17 03:34:08 UTC
From:
To:
If you had stated that the bug is that the ".POSIX" target doesn't conform to
this (from make info):

`.POSIX'
     If `.POSIX' is mentioned as a target, then the makefile will be
     parsed and run in POSIX-conforming mode.  This does _not_ mean
     that only POSIX-conforming makefiles will be accepted: all advanced
     GNU `make' features are still available.  Rather, this target
     causes `make' to behave as required by POSIX in those areas where
     `make''s default behavior differs.

     In particular, if this target is mentioned then recipes will be
     invoked as if the shell had been passed the `-e' flag: the first
     failing command in a recipe will cause the recipe to fail
     immediately.

Then I think you'd be right.  In fact, in adding ".POSIX:" to your makefile
_still_ results in the same error, so I would classify the bug as belonging
to the .POSIX target failure to act "as if the shell had been passed the `-e'
flag".

Note that trying your makefile with "SHELL := /bin/sh -e" does result in the
expected behavior, though its only a w/a.

#635646#14
Date:
2016-02-17 03:28:58 UTC
From:
To:
If you had stated that the bug is that the ".POSIX" target doesn't conform to
this (from make info):

`.POSIX'
     If `.POSIX' is mentioned as a target, then the makefile will be
     parsed and run in POSIX-conforming mode.  This does _not_ mean
     that only POSIX-conforming makefiles will be accepted: all advanced
     GNU `make' features are still available.  Rather, this target
     causes `make' to behave as required by POSIX in those areas where
     `make''s default behavior differs.

     In particular, if this target is mentioned then recipes will be
     invoked as if the shell had been passed the `-e' flag: the first
     failing command in a recipe will cause the recipe to fail
     immediately.

Then I think you'd be right.  In fact, in adding ".POSIX:" to your makefile
_still_ results in the same error, so I would classify the bug as belonging to
the .POSIX target failure to act "as if the shell had been passed the `-e' flag".

Note that trying your makefile with "SHELL := /bin/sh -e" does result in the
expected behavior, though its still a bug.

#635646#15
Date:
2020-05-20 23:21:53 UTC
From:
To:
URL:
  <https://savannah.gnu.org/bugs/?58420>

                 Summary: PATH changes are not applied in $(shell) function
                 Project: make
            Submitted by: srivasta
            Submitted on: Wed 20 May 2020 06:21:52 PM CDT
                Severity: 3 - Normal
              Item Group: Bug
                  Status: None
                 Privacy: Public
             Assigned to: None
             Open/Closed: Open
         Discussion Lock: Any
       Component Version: 4.3
        Operating System: None
           Fixed Release: None
           Triage Status: None
--- BEGIN --- PATH := /nonexistent:$(PATH) default: @echo "make variable PATH=$(PATH)" @echo "in target commands, PATH=$$PATH" @echo "in \$$(shell commands), PATH=$(shell echo "$$PATH")" --- END --- 'make' generates the output for me: make variable PATH=/nonexistent:/home/ben/bin:/usr/lib/ccache:/usr/local/sbin:/usr/sbin:/sbin:/home/ben/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games in target commands, PATH=/nonexistent:/home/ben/bin:/usr/lib/ccache:/usr/local/sbin:/usr/sbin:/sbin:/home/ben/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games in $(shell commands), PATH=/home/ben/bin:/usr/lib/ccache:/usr/local/sbin:/usr/sbin:/sbin:/home/ben/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games I can't see any documentation that says the PATH variable is special, so I think this is a bug. I would guess that make defers evaluating the PATH variable into the environment, in case it's recursively expanded, but only re-evaulates it before running target commands. Ben.