verbose.mk: fallback to standard file descriptors
authorMichael Pratt <mcpratt@pm.me>
Wed, 18 May 2022 03:06:36 +0000 (23:06 -0400)
committerChristian Marangi <ansuelsmth@gmail.com>
Fri, 5 Jan 2024 15:25:14 +0000 (16:25 +0100)
In order to pass a status message at runtime,
which is usually listing subtargets
of a Makefile target or an error message,
from a child invocation of Make (submake)
through the parent process to the terminal,
the file descriptors 8 and 9 are opened to be used
by the functions MESSAGE and ERROR_MESSAGE.

However, there are situations where those functions
can be called while not in a submake or a subshell
or a child process which results in a shell error:

/bin/bash: 8: Bad file descriptor

Commit aee3594ffcb72ae3e18c3719012d52519ee2d160
("verbose.mk: print ERROR messages in non-verbose")
has exposed this issue to more cases, but it is not the root cause.

To solve this, use the exit code of the first printf attempt
to the alternative file descriptors in order to tell whether
the standard file descriptors need to be used instead.
In order to get rid of the "Bad file descriptor" error, stderr is
redirected to null after grouping the two printf alternatives
into one command to combine outputs.

For ERROR_MESSAGE, the real message is redirected to stderr
after redirecting the error from the attempted printing to null.

For MESSAGE, without redirection, the Make function "shell"
will absorb the actual message from stdout and input the value into the Makefile,
therefore the dummy variable "_NULL", previously used merely for causing
a call to the MESSAGE function to trigger without writing target rules,
now has and a real value when defined, so rename it to "_MESSAGE"
as a placeholder for the real message when the output should be stdout.

When "_MESSAGE" has a value, use Make function "info" to
finally bring it from the Makefile to the terminal.

This also fixes what is likely a typo, in that
while file descriptor 9 is meant to redirect to stderr
for use in error messages like in the function ERROR_MESSAGE,
that function has printf redirecting to file descriptor 8 instead.

Fixes: a4c8d4e37 ("build: make the color of the 'configuration out of sync' warning red")
Signed-off-by: Michael Pratt <mcpratt@pm.me>
include/verbose.mk

index 4487a207e87775812a7088369156465508a20ef5..f6aa0d701213907f8493afa408d723a246a7686c 100644 (file)
@@ -30,12 +30,18 @@ ifeq ($(IS_TTY),1)
 endif
 
 define ERROR_MESSAGE
-  printf "$(_R)%s$(_N)\n" "$(1)" >&8
+  { \
+       printf "$(_R)%s$(_N)\n" "$(1)" >&9 || \
+       printf "$(_R)%s$(_N)\n" "$(1)"; \
+  } >&2 2>/dev/null
 endef
 
 ifeq ($(findstring s,$(OPENWRT_VERBOSE)),)
   define MESSAGE
-       printf "$(_Y)%s$(_N)\n" "$(1)" >&8
+       { \
+               printf "$(_Y)%s$(_N)\n" "$(1)" >&8 || \
+               printf "$(_Y)%s$(_N)\n" "$(1)"; \
+       } 2>/dev/null
   endef
 
   ifeq ($(QUIET),1)
@@ -44,9 +50,12 @@ ifeq ($(findstring s,$(OPENWRT_VERBOSE)),)
     else
       _DIR:=
     endif
-    _NULL:=$(if $(MAKECMDGOALS),$(shell \
+    _MESSAGE:=$(if $(MAKECMDGOALS),$(shell \
                $(call MESSAGE, make[$(MAKELEVEL)]$(if $(_DIR), -C $(_DIR)) $(MAKECMDGOALS)); \
     ))
+    ifneq ($(strip $(_MESSAGE)),)
+      $(info $(_MESSAGE))
+    endif
     SUBMAKE=$(MAKE)
   else
     SILENT:=>/dev/null $(if $(findstring w,$(OPENWRT_VERBOSE)),,2>&1)