[bazel] Output explain file for debugging

NO_IFTTT=No changes needed to //build/bazel/scripts/workspace_utils.py:bazel_build_action

Change-Id: I9792f2ee4bd4b4eaa0afb83effabc0ddd7c4bebd
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1441928
Fuchsia-Auto-Submit: Jay Zhuang <jayzhuang@google.com>
Reviewed-by: David Turner <digit@google.com>
Commit-Queue: Jay Zhuang <jayzhuang@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 51b79e3..a8475ac 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -2209,6 +2209,11 @@
 #         This is only used for debugging.
 #     - Type: string
 #
+#   bazel_explain_file
+#     - Optional: Path to a file containing the explain output of the Bazel build command.
+#         This is only used for debugging.
+#     - Type: string
+#
 #   bazel_compdb_file
 #     - Optional: Path to a file including JSON compilation database for the
 #         Bazel targets built by this bazel_action().
diff --git a/build/bazel/bazel_action.gni b/build/bazel/bazel_action.gni
index 816e527..94bb9af 100644
--- a/build/bazel/bazel_action.gni
+++ b/build/bazel/bazel_action.gni
@@ -639,6 +639,17 @@
   _bazel_command_file = "${target_out_dir}/${target_name}.bazel_command.sh"
   _rebased_bazel_command_file = rebase_path(_bazel_command_file, root_build_dir)
 
+  # A file that will receive the explain output from the bazel_action.py script.
+  #
+  # The output is from dependency checker in Bazel build's execution phase to
+  # explain, for each build step, either why it is being executed, or that it is
+  # up-to-date.
+  #
+  # NOTE: This file will only include explain output from the `build` command,
+  # not other commands like `query`.
+  _bazel_explain_file = "${target_out_dir}/${target_name}.bazel_explain.txt"
+  _rebased_bazel_explain_file = rebase_path(_bazel_explain_file, root_build_dir)
+
   _timings_file = "${target_out_dir}/${target_name}.bazel_action_timings.json"
   _rebased_timings_file = rebase_path(_timings_file, root_build_dir)
 
@@ -688,6 +699,7 @@
     outputs = [
       _path_mapping,
       _bazel_command_file,
+      _bazel_explain_file,
       _debug_symbols_manifest,
       _rust_project_json,
       _timings_file,
@@ -736,6 +748,8 @@
              _rebased_bazel_command_file,
              "--timings-file",
              _rebased_timings_file,
+             "--explain-file",
+             _rebased_bazel_explain_file,
              "--path-mapping",
              _rebased_path_mapping,
              "--debug-symbols-manifest",
@@ -954,6 +968,7 @@
                 rebase_path(_all_licenses_spdx_file, root_build_dir)
             debug_symbols_manifest = _rebased_debug_symbols_manifest
             bazel_command_file = _rebased_bazel_command_file
+            bazel_explain_file = _rebased_bazel_explain_file
             path_mapping = _rebased_path_mapping
             timings_file = _rebased_timings_file
             build_events_log_json = _rebased_bazel_build_events_log_json
diff --git a/build/bazel/scripts/bazel_action.py b/build/bazel/scripts/bazel_action.py
index 690a5db..e4457c43 100644
--- a/build/bazel/scripts/bazel_action.py
+++ b/build/bazel/scripts/bazel_action.py
@@ -1301,6 +1301,11 @@
         help="If specified, write timings of each step in this script to file.",
     )
     parser.add_argument(
+        "--explain-file",
+        type=Path,
+        help="If specified, write explain output from Bazel to file.",
+    )
+    parser.add_argument(
         "--debug-symbols-manifest",
         help="If specified, write debug symbols manifest to file.",
     )
@@ -1546,7 +1551,12 @@
     command_profile_filename = (
         f"{args.gn_target_label[2:].replace(':', '/')}.command.profile.gz"
     )
-    cmd_args += ["--profile", f"{build_dir}/obj/{command_profile_filename}"]
+    cmd_args += [
+        "--profile",
+        f"{build_dir}/obj/{command_profile_filename}",
+        "--explain",
+        build_dir / args.explain_file,
+    ]
 
     if args.command_file:
         write_file_if_changed(
diff --git a/build/bazel/scripts/bazel_action_utils.py b/build/bazel/scripts/bazel_action_utils.py
index 716a15f..299796d 100644
--- a/build/bazel/scripts/bazel_action_utils.py
+++ b/build/bazel/scripts/bazel_action_utils.py
@@ -32,6 +32,7 @@
     gn_targets_licenses_spdx: str
     debug_symbols_manifest: str
     bazel_command_file: str = ""
+    bazel_explain_file: str = ""
     bazel_compdb_file: str = ""
     bazel_rust_project_json: str = ""
     path_mapping: str = ""