rmyorston / busybox-w32

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

`make` does not apply `.DEFAULT` rule #354

Closed naksyl closed 10 months ago

naksyl commented 1 year ago

$ cat Makefile

.DEFAULT:
    @echo $@

target: file

$ make

make: nothing to be done for file
make: nothing to be done for target

Expected output (according to mingw32-make): file

or:

file make: nothing to be done for target # edit: target builds file so it is not empty rule Should it be moved to pdpmake?

rmyorston commented 1 year ago

Should it be moved to pdpmake?

I haven't had time to look into this yet but it probably is a pdpmake issue.

Leaving it here will be fine.

naksyl commented 1 year ago

Forgot to mention: invoking target explicitly from cli: $ make file works as expected.

rmyorston commented 1 year ago

It seems this was a regression introduced by an unnecessary change in commit 5f64589b84a7349316a04cdbe607a5824459b731. (The hash referenced in commit ac9ff15e24b4eb2413fc3c4c7b6f3bfc1166516c above is incorrect.)

Please try the latest prerelease binary.

If that works I'll apply the fix in pdpmake too.

naksyl commented 1 year ago

It works perfect for my personal Makefile. (I am using .DEFAULT for providing default pre and post target logger hook - whole thing is kind of task manager).

naksyl commented 1 year ago

pdpmake is kind of verbose (but probably it is a good thing). One thing that bothers me is printing make: nothing to be done for xxx to stderr. I know that this can be hide with @: as command or with redirecting stderr (and lost fatal messages) . When doing some comparison I discover small issue. I want to address this issue only but presenting my full research for completness.

Testing environment: $ uname -a Linux lenovo 5.15.90.1-microsoft-standard-WSL2 #1 SMP Fri Jan 27 02:56:13 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Make tools:

$ cat Makefile

.POSIX:

target: not_exist_rule

dummy_target: dummy_rule

dummy_rule:
        @:

empty_target: empty_rule

empty_rule:

Results (stderr in bold):

target pdpmake bmake make
target pdpmake: nothing to be done for not_exist_rule
pdpmake: nothing to be done for target
exit: 0
bmake: stopped in /home/naksyl
bmake: don't know how to make not_exist_rule. Stop
exit: 2
**make: * No rule to make target 'not_exist_rule', needed by 'target'. Stop.
exit: 2
not_exist_rule pdpmake: don't know how to make not_exist_rule
exit: 2
bmake: stopped in /home/naksyl
bmake: don't know how to make not_exist_rule. Stop
exit: 2
**make: * No rule to make target 'not_exist_rule'. Stop.
exit: 2
dummy_target pdpmake: nothing to be done for dummy_target
exit: 0
exit: 0 exit: 0
emty_target pdpmake: nothing to be done for empty_rule
pdpmake: nothing to be done for empty_target
exit: 0
exit: 0 make: Nothing to be done for 'empty_target'.
Exit: 0
empty_rule pdpmake: nothing to be done for empty_rule
exit: 0
exit: 0 make: Nothing to be done for 'empty_rule'.
exit: 0

The issue is: should pdpmake exit with 2 for target?

rmyorston commented 1 year ago

The issue is: should pdpmake exit with 2 for target?

It should. The commit from yesterday (which is also in pdpmake now) should fix that.

There are two additional commits in pdpmake:

The new commits will be ported to busybox-w32 in due course.

rmyorston commented 1 year ago

The new commits will be ported to busybox-w32 in due course.

Done.

naksyl commented 1 year ago

Thanks for Your work. Long live pdpmake !

naksyl commented 1 year ago

Follow GNU make's practice as to when to output that message.

You should review code for dry-run option (dummy_target case)

I know I'm a pain in the ass, but as You said:

where's the fun in doing it the easy way?

😄

~ $ for t in target dummy_target empty_target dummy_rule empty_rule; do
>     echo ----------------------------------------------------------------
>     echo $t:
>     echo -e '\tpdpmake:'
>     pdpmake -n $t | sed 's|^|\t\t|'
>     echo -e '\tgmake:'
>     wsl gmake -n $t | sed 's|^|\t\t|'
> done
----------------------------------------------------------------
target:
        pdpmake:
pdpmake: don't know how to make not_exist_rule
        gmake:
gmake: *** No rule to make target 'not_exist_rule', needed by 'target'.  Stop.
----------------------------------------------------------------
dummy_target:
        pdpmake:
                :
                pdpmake: nothing to be done for dummy_target
        gmake:
                :
----------------------------------------------------------------
empty_target:
        pdpmake:
                pdpmake: nothing to be done for empty_target
        gmake:
                gmake: Nothing to be done for 'empty_target'.
----------------------------------------------------------------
dummy_rule:
        pdpmake:
                :
        gmake:
                :
----------------------------------------------------------------
empty_rule:
        pdpmake:
                pdpmake: nothing to be done for empty_rule
        gmake:
                gmake: Nothing to be done for 'empty_rule'.

BTW I copy-paste Makefile (forgot about hard tab to space conversion). gmake happily prints:

gmake: Nothing to be done for 'dummy_rule'. (exit: 0)

but pdpmake did better (thanks to the strict posix policy):

pdpmake: (makefile:8): invalid target name '@' (exit: 2) 👍

naksyl commented 1 year ago

Found more important problem: make exits with 0 when target fails.

~ $ cat Makefile
all:
        @exit 42

~ $ for make in "./busybox64.exe make" "./busybox_pre64.exe make" gmake bmake; do
>     echo -------------------------------------------------------
>     echo $make
>     $make > >(sed 's/^/\tstdout: /') 2> >(sed 's/^/\tstderr: /' 1>&2)
>     status=$?
>     sleep 0.1
>     echo -e '\texit: ' $status
> done
-------------------------------------------------------
./busybox64.exe make
        stderr: make: (makefile:2): failed to build 'all'
        exit:  0
-------------------------------------------------------
./busybox_pre64.exe make
        stdout: make: (makefile:2): failed to build 'all'
        exit:  0
-------------------------------------------------------
gmake
        stderr: gmake: *** [Makefile:2: all] Error 42
        exit:  2
-------------------------------------------------------
bmake
        stderr: bmake: exec(exit) failed (No such file or directory)
        stdout: *** Error code 1
        stdout:
        stdout: Stop.
        stdout: bmake: stopped in /mnt/c/Users/naksyl/Projekty
        exit:  1
rmyorston commented 1 year ago

You should review code for dry-run option (dummy_target case)

Yes, that's inconsistent with GNU make. The -t option is also affected.

It should now be fixed, both here and in pdpmake.

rmyorston commented 1 year ago

make exits with 0 when target fails

This should now be fixed, both in busybox-w32 and pdpmake.

naksyl commented 1 year ago

Another redundant message small thing - needs better integration with busybox. When make is invoked as {/usr,}/bin/{pdp,}make:

~ $ echo > Makefile

~ $ make
make: no targets defined

~ $ /bin/make
make: can't resolve path for /bin/make: No such file or directory
make: no targets defined
rmyorston commented 1 year ago

Should be fixed now.