Partially fix MacOS llvm coverage collection

This allows setting GCOV on the command line to overwrite the default setting, which points to /usr/bin/gcov. In order to use this, you also need to disable the gcov coverage feature and enable the llvm coverage feature instead. The full command-line looks like this:

GCOV=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/llvm-profdata bazel coverage --features=llvm_coverage_map_format --features=-gcc_coverage_map_format //cpp:test

Progress on #10457.

Original change by ulfjack
RELNOTES: None.
PiperOrigin-RevId: 300583709
diff --git a/tools/cpp/osx_cc_configure.bzl b/tools/cpp/osx_cc_configure.bzl
index a6fc3a1..a372804 100644
--- a/tools/cpp/osx_cc_configure.bzl
+++ b/tools/cpp/osx_cc_configure.bzl
@@ -139,6 +139,13 @@
                  "https://github.com/bazelbuild/bazel/issues with the following:\n" +
                  error_msg)
 
+        tool_paths = {}
+        gcov_path = repository_ctx.os.environ.get("GCOV")
+        if gcov_path != None:
+            if not gcov_path.startswith("/"):
+                gcov_path = repository_ctx.which(gcov_path)
+            tool_paths["gcov"] = gcov_path
+
         escaped_include_paths = _get_escaped_xcode_cxx_inc_directories(repository_ctx, cc, xcode_toolchains)
         write_builtin_include_directory_paths(repository_ctx, cc, escaped_include_paths)
         escaped_cxx_include_directories = []
@@ -149,7 +156,12 @@
         repository_ctx.template(
             "BUILD",
             paths["@bazel_tools//tools/osx/crosstool:BUILD.tpl"],
-            {"%{cxx_builtin_include_directories}": "\n".join(escaped_cxx_include_directories)},
+            {
+                "%{cxx_builtin_include_directories}": "\n".join(escaped_cxx_include_directories),
+                "%{tool_paths_overrides}": ",\n        ".join(
+                    ['"%s": "%s"' % (k, v) for k, v in tool_paths.items()],
+                ),
+            },
         )
     else:
         configure_unix_toolchain(repository_ctx, cpu_value = "darwin", overriden_tools = overriden_tools)
diff --git a/tools/osx/crosstool/BUILD.tpl b/tools/osx/crosstool/BUILD.tpl
index 1610da4..dcd7002 100644
--- a/tools/osx/crosstool/BUILD.tpl
+++ b/tools/osx/crosstool/BUILD.tpl
@@ -87,6 +87,7 @@
         compiler = "compiler",
         cpu = arch,
         cxx_builtin_include_directories = [%{cxx_builtin_include_directories}],
+        tool_paths_overrides = {%{tool_paths_overrides}},
     )
     for arch in OSX_TOOLS_ARCHS
 ]
diff --git a/tools/osx/crosstool/cc_toolchain_config.bzl b/tools/osx/crosstool/cc_toolchain_config.bzl
index 495edef..37ef0ab 100644
--- a/tools/osx/crosstool/cc_toolchain_config.bzl
+++ b/tools/osx/crosstool/cc_toolchain_config.bzl
@@ -5936,20 +5936,21 @@
         ),
     ]
 
+    tool_paths = dict()
     if (ctx.attr.cpu == "armeabi-v7a"):
-        tool_paths = [
-            tool_path(name = "ar", path = "/bin/false"),
-            tool_path(name = "compat-ld", path = "/bin/false"),
-            tool_path(name = "cpp", path = "/bin/false"),
-            tool_path(name = "dwp", path = "/bin/false"),
-            tool_path(name = "gcc", path = "/bin/false"),
-            tool_path(name = "gcov", path = "/bin/false"),
-            tool_path(name = "ld", path = "/bin/false"),
-            tool_path(name = "nm", path = "/bin/false"),
-            tool_path(name = "objcopy", path = "/bin/false"),
-            tool_path(name = "objdump", path = "/bin/false"),
-            tool_path(name = "strip", path = "/bin/false"),
-        ]
+        tool_paths = {
+            "ar": "/bin/false",
+            "compat-ld": "/bin/false",
+            "cpp": "/bin/false",
+            "dwp": "/bin/false",
+            "gcc": "/bin/false",
+            "gcov": "/bin/false",
+            "ld": "/bin/false",
+            "nm": "/bin/false",
+            "objcopy": "/bin/false",
+            "objdump": "/bin/false",
+            "strip": "/bin/false",
+        }
     elif (ctx.attr.cpu == "darwin_x86_64" or
           ctx.attr.cpu == "ios_arm64" or
           ctx.attr.cpu == "ios_arm64e" or
@@ -5962,22 +5963,24 @@
           ctx.attr.cpu == "watchos_armv7k" or
           ctx.attr.cpu == "watchos_i386" or
           ctx.attr.cpu == "watchos_x86_64"):
-        tool_paths = [
-            tool_path(name = "ar", path = "libtool"),
-            tool_path(name = "compat-ld", path = "/usr/bin/ld"),
-            tool_path(name = "cpp", path = "/usr/bin/cpp"),
-            tool_path(name = "dwp", path = "/usr/bin/dwp"),
-            tool_path(name = "gcc", path = "cc_wrapper.sh"),
-            tool_path(name = "gcov", path = "/usr/bin/gcov"),
-            tool_path(name = "ld", path = "/usr/bin/ld"),
-            tool_path(name = "nm", path = "/usr/bin/nm"),
-            tool_path(name = "objcopy", path = "/usr/bin/objcopy"),
-            tool_path(name = "objdump", path = "/usr/bin/objdump"),
-            tool_path(name = "strip", path = "/usr/bin/strip"),
-        ]
+        tool_paths = {
+            "ar": "libtool",
+            "compat-ld": "/usr/bin/ld",
+            "cpp": "/usr/bin/cpp",
+            "dwp": "/usr/bin/dwp",
+            "gcc": "cc_wrapper.sh",
+            "gcov": "/usr/bin/gcov",
+            "ld": "/usr/bin/ld",
+            "nm": "/usr/bin/nm",
+            "objcopy": "/usr/bin/objcopy",
+            "objdump": "/usr/bin/objdump",
+            "strip": "/usr/bin/strip",
+        }
     else:
         fail("Unreachable")
 
+    tool_paths.update(ctx.attr.tool_paths_overrides)
+
     out = ctx.actions.declare_file(ctx.label.name)
     ctx.actions.write(out, "Fake executable")
     return [
@@ -5995,7 +5998,7 @@
             compiler = compiler,
             abi_version = abi_version,
             abi_libc_version = abi_libc_version,
-            tool_paths = tool_paths,
+            tool_paths = [tool_path(name = name, path = path) for (name, path) in tool_paths.items()],
             make_variables = make_variables,
             builtin_sysroot = builtin_sysroot,
             cc_target_os = cc_target_os,
@@ -6011,6 +6014,7 @@
         "cpu": attr.string(mandatory = True),
         "compiler": attr.string(),
         "cxx_builtin_include_directories": attr.string_list(),
+        "tool_paths_overrides": attr.string_dict(),
         "_xcode_config": attr.label(default = configuration_field(
             fragment = "apple",
             name = "xcode_config_label",