Why SHELL defaults to sh.exe

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Why SHELL defaults to sh.exe

Christian Jullien

Hi team,

 

I wonder why Windows native gnumake.exe defaults to sh.exe ?

Building gnumake.exe with build_w32.bat (which defaults to cl.exe) still uses sh.exe while IMHO it should default to cmd.exe

 

In an ideal world, I should be able to get for example all .c source files with:

 

FILES   = $(shell dir /b *.c)

 

all:

        @echo $(SHELL)

        @echo $(FILES)

 

But if fails unless I first set SHELL as with

 

SHELL = cmd

FILES = $(shell dir /b *.c)

 

all:

        @echo $(SHELL)

        @echo $(FILES)

 

To not break current practice can you please add a new build_w32.bat option –-with-cmd

 

Options:

  --without-guile   Do not compile Guile support even if found

  --with-cmd        Use cmd.exe shell instead of sh.exe

  --debug           Make a Debug build--default is Release

  --x86             Make a 32bit binary--default is 64bit

  --help            Display these instructions and exit

 

Even better if you’re able to pass a shell

 

Options:

  --without-guile      Do not compile Guile support even if found

  --with-shell <shell> Specifies default SHELL instead of sh.exe

  --debug              Make a Debug build--default is Release

  --x86                Make a 32bit binary--default is 64bit

  --help               Display these instructions and exit

 

C:> build_w32.bat –with-shell PowerShell

 

 

Reply | Threaded
Open this post in threaded view
|

Re: Why SHELL defaults to sh.exe

Eli Zaretskii
> From: "Christian Jullien" <[hidden email]>
> Date: Thu, 23 Jan 2020 11:27:53 +0100
>
> I wonder why Windows native gnumake.exe defaults to sh.exe ?

Historical reasons.

> Building gnumake.exe with build_w32.bat (which defaults to cl.exe) still uses sh.exe while IMHO it should
> default to cmd.exe

It only defaults to sh.exe if it finds one on PATH.  If you are using
native Windows tools, why would you have sh.exe on PATH? there are no
known good native Windows ports of any Unixy shell, AFAIK, only broken
ones.

If you don't have sh.exe on PATH, GNU Make on Windows will use cmd.exe.

> In an ideal world, I should be able to get for example all .c source files with:
>
>  
>
> FILES   = $(shell dir /b *.c)

In GNU Make, you have the $wildcard function instead, so no need to
use the shell in this case.

Reply | Threaded
Open this post in threaded view
|

RE: Why SHELL defaults to sh.exe

Christian Jullien
Dear Eli,

From your explanation, it seems there is something broken at least with
make-4.3. Here is what I have done:
cmd> tar xvzf make-4.3.tar.gz    <= unmodified from Git
cmd> cd make-4.3
cmd> build_w32.bat
...
.\WinRel build succeeded.
        1 file(s) copied.
        1 file(s) copied.

Reduce Windows env down to the minimum:

set Path=C:\WINDOWS\system32;C:\WINDOWS
set INCLUDE=
set LIB=
set SHELL=
set HOME=

Looking for sh of bash somewhere

cmd>sh
'sh' is not recognized as an internal or external command,
operable program or batch file.
cmd>bash
'bash' is not recognized as an internal or external command,
operable program or batch file.

cmd>WinRel
cmd>dir *.exe
 Volume in drive F is New Volume
 Volume Serial Number is 12C9-E1B4

 Directory of F:\make-4.3\WinRel

2020-01-23  15:39           336,384 gnumake.exe

Now the test:

cmd>type Makefile
all:
        @echo $(SHELL)
cmd>.\gnumake
sh.exe    <=== Argl!!



-----Original Message-----
From: Eli Zaretskii [mailto:[hidden email]]
Sent: Thursday, January 23, 2020 15:33
To: [hidden email]
Cc: [hidden email]
Subject: Re: Why SHELL defaults to sh.exe

> From: "Christian Jullien" <[hidden email]>
> Date: Thu, 23 Jan 2020 11:27:53 +0100
>
> I wonder why Windows native gnumake.exe defaults to sh.exe ?

Historical reasons.

> Building gnumake.exe with build_w32.bat (which defaults to cl.exe) still
uses sh.exe while IMHO it should
> default to cmd.exe

It only defaults to sh.exe if it finds one on PATH.  If you are using
native Windows tools, why would you have sh.exe on PATH? there are no
known good native Windows ports of any Unixy shell, AFAIK, only broken
ones.

If you don't have sh.exe on PATH, GNU Make on Windows will use cmd.exe.

> In an ideal world, I should be able to get for example all .c source files
with:
>
>  
>
> FILES   = $(shell dir /b *.c)

In GNU Make, you have the $wildcard function instead, so no need to
use the shell in this case.


Reply | Threaded
Open this post in threaded view
|

Re: Why SHELL defaults to sh.exe

Eli Zaretskii
> From: "Christian Jullien" <[hidden email]>
> Cc: <[hidden email]>
> Date: Thu, 23 Jan 2020 15:54:50 +0100
>
> cmd>type Makefile
> all:
>         @echo $(SHELL)
> cmd>.\gnumake
> sh.exe    <=== Argl!!

Why is that a problem?

If you do

  .\gnumake -f-
  all:
  dir *c
  ^Z

does it not invoke cmd.exe's DIR command?  It does here.

All you've shown is the value of $(SHELL) set by Make internally,
that's all.  It doesn't mean this will be the shell that will be
invoked to execute shell commands.

Reply | Threaded
Open this post in threaded view
|

Re: Why SHELL defaults to sh.exe

Eli Zaretskii
> From: "Christian Jullien" <[hidden email]>
> Date: Thu, 23 Jan 2020 20:18:17 +0100
>
> Hum I see! It only a problem if I want to execute something if a sh.exe
> exists.
>
> search:
> ifeq ($(SHELL),sh.exe)
> grep something file
> else
> find "something" file
> endif

If you want to depend on the value of $(SHELL), set it explicitly in
the Makefile.

In any case, the above logic is flawed, because 'grep' can be
available on Windows as well (I certainly have it here), and 'find'
could actually invoke a ported GNU 'find'.  IME, it is much better to
have Make variables for such commands, and let users set them from the
Make command line.

Reply | Threaded
Open this post in threaded view
|

RE: Why SHELL defaults to sh.exe

Christian Jullien
Perhaps my sample was too simple.
If I supply a Makefile that can work with or without sh.exe presence (on any
user machines) I must rely on what make knows about the shell.
Forcing SHELL= obviously does not work.
Another example, Cygwin which provides a sh.exe also dir.exe which gives a
different output. If SHELL is sh.exe or cmd.exe output is different

ifeq ($(SHELL),sh.exe)
LIST=$(shell dir)
else
LIST=$(shell dir /b)
endif

For my need, which is to have a gnumake coming with tcc.exe, I know how to
automatically patch and build make with sh.exe replaced by cmd.exe in source
file. So it's not a problem for me. I just wanted to point out something
which I find not consistency (aka a bug).

I'm more interested to have my patches for built_w32.bat and
src/config.h.W32.template integrated to the next release.

Anyway many thanks you're your time and patience.


C.


-----Original Message-----
From: Eli Zaretskii [mailto:[hidden email]]
Sent: Thursday, January 23, 2020 20:26
To: [hidden email]
Cc: [hidden email]
Subject: Re: Why SHELL defaults to sh.exe

> From: "Christian Jullien" <[hidden email]>
> Date: Thu, 23 Jan 2020 20:18:17 +0100
>
> Hum I see! It only a problem if I want to execute something if a sh.exe
> exists.
>
> search:
> ifeq ($(SHELL),sh.exe)
> grep something file
> else
> find "something" file
> endif

If you want to depend on the value of $(SHELL), set it explicitly in
the Makefile.

In any case, the above logic is flawed, because 'grep' can be
available on Windows as well (I certainly have it here), and 'find'
could actually invoke a ported GNU 'find'.  IME, it is much better to
have Make variables for such commands, and let users set them from the
Make command line.


Reply | Threaded
Open this post in threaded view
|

Re: Why SHELL defaults to sh.exe

Eli Zaretskii
> From: "Christian Jullien" <[hidden email]>
> Cc: <[hidden email]>
> Date: Thu, 23 Jan 2020 21:07:26 +0100
>
> Perhaps my sample was too simple.
> If I supply a Makefile that can work with or without sh.exe presence (on any
> user machines) I must rely on what make knows about the shell.

I'm saying such strategy is not the best one on Windows, because there
are too many variables the name of the shell doesn't capture.  Even if
you have some sh.exe somewhere, you cannot know what kind of shell is
it (Bash? zsh? something else?) and what exactly is it capable of on
Windows.  Programs that can be expected to be found on Unix might
exist on Windows as well, but you cannot be sure.

So a better strategy is to leave it up to the user to decide whether
to run in Unix mode or in Windows mode, and whether to call, say,
'del' or 'rm'.

Another, better method of detecting whether you are on Windows is to
probe the $(OS) variable: all modern versions of Windows have it set,
so your probability of a correct decision is much higher in that
case.  (But issues with what commands to employ still apply even in
that case.)

> Another example, Cygwin which provides a sh.exe also dir.exe which gives a
> different output. If SHELL is sh.exe or cmd.exe output is different

That's the same problem as the one with having 'find' from GNU
Findutils or from Windows.  It's part of the "which commands to
invoke" issue discussed above, nothing new.

> For my need, which is to have a gnumake coming with tcc.exe, I know how to
> automatically patch and build make with sh.exe replaced by cmd.exe in source
> file. So it's not a problem for me. I just wanted to point out something
> which I find not consistency (aka a bug).

It is a subtle issue, but I don't consider it a bug, since GNU Make on
Windows behaves like that since its first ported version.  You need to
be aware of that subtlety, but once you are, it is rarely a real issue
in practice.

Maybe we could remove that nowadays, but I have no way of knowing
what, if anything, that will break, and no motivation to work on a
change that can potentially destabilize what has been a very stable
program.