kbuild: make V=2 tell why a target is rebuild

tell why a a target got build
   enabled by make V=2
      Output (listed in the order they are checked):
         (1) - due to target is PHONY
         (2) - due to target missing
         (3) - due to: file1.h file2.h
         (4) - due to command line change
         (5) - due to missing .cmd file
         (6) - due to target not in $(targets)
(1) We always build PHONY targets
(2) No target, so we better build it
(3) Prerequisite is newer than target
(4) The command line stored in the file named dir/.target.cmd
    differed from actual command line. This happens when compiler
    options changes
(5) No dir/.target.cmd file (used to store command line)
(6) No dir/.target.cmd file and target not listed in $(targets)
    This is a good hint that there is a bug in the kbuild file

This patch is inspired by a patch from: Milton Miller <miltonm@bga.com>

Cc: Milton Miller <miltonm@bga.com>
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
diff --git a/Makefile b/Makefile
index 22451c2..440a133 100644
--- a/Makefile
+++ b/Makefile
@@ -1101,6 +1101,7 @@
 		echo '')
 
 	@echo  '  make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
+	@echo  '  make V=2   [targets] 2 => give reason for rebuild of target'
 	@echo  '  make O=dir [targets] Locate all output files in "dir", including .config'
 	@echo  '  make C=1   [targets] Check all c source with $$CHECK (sparse by default)'
 	@echo  '  make C=2   [targets] Force check of all c source with $$CHECK'
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 1d6ffb2..3d52389 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -129,7 +129,7 @@
 
 # echo command. Short version is $(quiet) equals quiet, otherwise full command
 echo-cmd = $(if $($(quiet)cmd_$(1)), \
-	echo '  $(call escsq,$($(quiet)cmd_$(1)))';)
+	echo '  $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
 
 # >'< substitution is for echo to work,
 # >$< substitution to preserve $ when reloading .cmd file
@@ -164,3 +164,42 @@
 	@set -e;                                                             \
 	$(rule_$(1)))
 
+###
+# why - tell why a a target got build
+#       enabled by make V=2
+#       Output (listed in the order they are checked):
+#          (1) - due to target is PHONY
+#          (2) - due to target missing
+#          (3) - due to: file1.h file2.h
+#          (4) - due to command line change
+#          (5) - due to missing .cmd file
+#          (6) - due to target not in $(targets)
+# (1) PHONY targets are always build
+# (2) No target, so we better build it
+# (3) Prerequisite is newer than target
+# (4) The command line stored in the file named dir/.target.cmd
+#     differed from actual command line. This happens when compiler
+#     options changes
+# (5) No dir/.target.cmd file (used to store command line)
+# (6) No dir/.target.cmd file and target not listed in $(targets)
+#     This is a good hint that there is a bug in the kbuild file
+ifeq ($(KBUILD_VERBOSE),2)
+why =                                                                        \
+    $(if $(filter $@, $(PHONY)),- due to target is PHONY,                    \
+        $(if $(wildcard $@),                                                 \
+            $(if $(strip $(any-prereq)),- due to: $(any-prereq),             \
+                $(if $(arg-check),                                           \
+                    $(if $(cmd_$@),- due to command line change,             \
+                        $(if $(filter $@, $(targets)),                       \
+                            - due to missing .cmd file,                      \
+                            - due to $(notdir $@) not in $$(targets)         \
+                         )                                                   \
+                     )                                                       \
+                 )                                                           \
+             ),                                                              \
+             - due to target missing                                         \
+         )                                                                   \
+     )
+
+echo-why = $(call escsq, $(strip $(why)))
+endif