rmyorston / pdpmake

Public domain POSIX make
https://frippery.org/make
Other
106 stars 11 forks source link

Inconsistent $SHLVL #57

Closed ale5000-git closed 3 weeks ago

ale5000-git commented 1 month ago

If I insert:

dummy:
    echo $(SHLVL)

directly in the Makefile I get 1.

But if I execute a shell script from the Makefile and in the shell script I put echo ${SHLVL} then I get 3.

So what happened to the 2? Or am I missing something?

rmyorston commented 1 month ago

In the first instance:

If you want to see the value of SHLVL in the shell that runs the echo you need to use the command echo $${SHLVL} in the Makefile. That should display 2.

I get 2 for SHLVL from a shell script on Linux and 3 when using pdpmake from busybox-w32 on Windows. Can I suppose you're running on Windows?

If so, there are three shells involved:

On Linux it appears that system(3) doesn't actually run the second shell in this case, hence the scripts reports a SHLVL of 2.

Edit: On further consideration I think it's more accurate to say the second shell is also used to interpret the script. If the command line has more than just a call to the script the shell can't perform that optimisation and SHLVL is 3.

ale5000-git commented 1 month ago

I get 2 for SHLVL from a shell script on Linux and 3 when using pdpmake from busybox-w32 on Windows. Can I suppose you're running on Windows?

Yes.

With these: ./Makefile

dummy:
    echo ${SHLVL}
    echo $${SHLVL}
    ./show_shlvl.sh

./show_shlvl.sh

echo $SHLVL
sh -c 'echo $SHLVL'

in pdpmake I get:

echo 1
1
echo ${SHLVL}
2
./show_shlvl.sh
3
4

while in GNU make I get:

echo

echo ${SHLVL}
1
./show_shlvl.sh
1
1

So I guess pdpmake is correct and GNU make isn't.

rmyorston commented 1 month ago

I get the same results as you with pdpmake on Windows.

I'm unable to reproduce your results with GNU make on Windows. I've tried mingw32-make.exe from w64devkit and the make in MSYS2. In both cases I get:

~ $ mingw32-make.exe -f M57
echo 1
1
echo ${SHLVL}
2
./show_shlvl.sh
2
3
~ $

On Linux, GNU, BSD and Schily make all return the same as above. And so do a Linux-native pdpmake and pdpmake in a Linux-native BusyBox.

In my tests the only exceptional case is pdpmake in busybox-w32.

ale5000-git commented 1 month ago

I guess the one included in Ruby is just broken, I have found an older one and it works. I get from GNU Make 3.81 on Windows:

echo 1
1
echo ${SHLVL}
2
show_shlvl.sh
2
3
rmyorston commented 3 weeks ago

Somewhat unrelated to SHVLVL and pdpmake, I've been thinking about the missing optimisation in the busybox-w32 shell mentioned above.

There's one case where it can be applied: if the affected command is a script and the script interpreter is an applet. Consider this Makefile:

target:
    @./m57awk
    @./m57sh

where the commands are the following scripts:

#!/bin/awk -f
BEGIN { print "awk" }
#!/bin/sh
echo sh

In both cases the optimisation can be applied. Running the Makefile 1000 times in a loop takes 34.2 seconds with the FRP-5398 release; with the optimisation in PRE-5460 it takes 20.5 seconds.

In real life you won't get such a big speed-up, but it's worth having anyway.

ale5000-git commented 3 weeks ago

There is something I don't understand, if the optimization apply doesn't SHVLVL should maintain the same number?

rmyorston commented 3 weeks ago

busybox-w32 is correctly counting the number of shells, according to BusyBox's method of accounting. Even with the optimisation applied.

A Linux-native BusyBox (with standalone shell mode enabled and pdpmake included) uses system(3) from glibc, so it works differently from the one in busybox-w32. In particular, it uses bash to run commands on behalf of pdpmake, and as we've seen before bash uses a different method to account for shell levels.

ale5000-git commented 3 weeks ago

Thanks, I will close this since now it seems impraticable to improve it.