Fix another case of tool_paths vs action configs

Copybara Import from https://github.com/bazelbuild/rules_cc/pull/739

BEGIN_PUBLIC
Fix another case of tool_paths vs action configs (#739)

This also dedups the helper function of this, which was merged in from 2
prs at once

Closes #739
END_PUBLIC

COPYBARA_INTEGRATE_REVIEW=https://github.com/bazelbuild/rules_cc/pull/739 from keith:ks/fix-another-case-of-tool_paths-vs-action-configs 1c87aef0c023ab54c2a3f1e03cf4e71c6beb0716
PiperOrigin-RevId: 949253682
Change-Id: I64ed614ce19faad0db9e54a275cc7acc7f242d18
diff --git a/cc/common/cc_helper.bzl b/cc/common/cc_helper.bzl
index dff899f..6a17c68 100644
--- a/cc/common/cc_helper.bzl
+++ b/cc/common/cc_helper.bzl
@@ -501,52 +501,39 @@
             compilation_contexts.append(dep[CcInfo].compilation_context)
     return compilation_contexts
 
-def _tool_path(cc_toolchain, tool, feature_configuration = None, action_name = None):
-    tool = cc_toolchain._tool_paths.get(tool, None)
-    if tool:
-        return tool
+def _tool_path(tool_paths, tool, feature_configuration = None, action_name = None, default = ""):
+    path = tool_paths.get(tool, None)
+    if path:
+        return path
     if feature_configuration != None and action_name != None:
         if not cc_common.action_is_enabled(
             feature_configuration = feature_configuration,
             action_name = action_name,
         ):
-            return None
+            return default
 
         return cc_common.get_tool_for_action(
             feature_configuration = feature_configuration,
             action_name = action_name,
-        )
-    return None
-
-def _tool_path_for_action(cc_toolchain, tool, feature_configuration, action_name):
-    path = cc_toolchain._tool_paths.get(tool, None)
-    if path:
-        return path
-    if action_name != None and cc_common.action_is_enabled(
-        feature_configuration = feature_configuration,
-        action_name = action_name,
-    ):
-        return cc_common.get_tool_for_action(
-            feature_configuration = feature_configuration,
-            action_name = action_name,
-        ) or ""
-    return ""
+        ) or default
+    return default
 
 def _get_toolchain_global_make_variables(cc_toolchain, feature_configuration):
+    tool_paths = cc_toolchain._tool_paths
     result = {
-        "CC": _tool_path_for_action(cc_toolchain, "gcc", feature_configuration, ACTION_NAMES.c_compile),
-        "AR": _tool_path_for_action(cc_toolchain, "ar", feature_configuration, ACTION_NAMES.cpp_link_static_library),
-        "NM": _tool_path_for_action(cc_toolchain, "nm", feature_configuration, None),
-        "LD": _tool_path_for_action(cc_toolchain, "ld", feature_configuration, ACTION_NAMES.cpp_link_executable),
-        "STRIP": _tool_path_for_action(cc_toolchain, "strip", feature_configuration, ACTION_NAMES.strip),
+        "CC": _tool_path(tool_paths, "gcc", feature_configuration, ACTION_NAMES.c_compile),
+        "AR": _tool_path(tool_paths, "ar", feature_configuration, ACTION_NAMES.cpp_link_static_library),
+        "NM": _tool_path(tool_paths, "nm", feature_configuration, None),
+        "LD": _tool_path(tool_paths, "ld", feature_configuration, ACTION_NAMES.cpp_link_executable),
+        "STRIP": _tool_path(tool_paths, "strip", feature_configuration, ACTION_NAMES.strip),
         "C_COMPILER": cc_toolchain.compiler,
     }  # buildifier: disable=unsorted-dict-items
 
-    obj_copy_tool = _tool_path_for_action(cc_toolchain, "objcopy", feature_configuration, ACTION_NAMES.objcopy_embed_data)
+    obj_copy_tool = _tool_path(tool_paths, "objcopy", feature_configuration, ACTION_NAMES.objcopy_embed_data)
     if obj_copy_tool != None:
         # objcopy is optional in Crostool.
         result["OBJCOPY"] = obj_copy_tool
-    gcov_tool = _tool_path_for_action(cc_toolchain, "gcov-tool", feature_configuration, None)
+    gcov_tool = _tool_path(tool_paths, "gcov-tool", feature_configuration, None)
     if gcov_tool:
         # gcovtool is optional in Crostool.
         result["GCOVTOOL"] = gcov_tool
@@ -1068,9 +1055,9 @@
 
     # buildifier: disable=unsorted-dict-items
     env = {
-        "COVERAGE_GCOV_PATH": _tool_path(cc_toolchain, "gcov", feature_configuration, ACTION_NAMES.gcov),
-        "LLVM_COV": _tool_path(cc_toolchain, "llvm-cov", feature_configuration, ACTION_NAMES.llvm_cov),
-        "LLVM_PROFDATA": _tool_path(cc_toolchain, "llvm-profdata", feature_configuration, ACTION_NAMES.llvm_profdata),
+        "COVERAGE_GCOV_PATH": _tool_path(cc_toolchain._tool_paths, "gcov", feature_configuration, ACTION_NAMES.gcov, default = None),
+        "LLVM_COV": _tool_path(cc_toolchain._tool_paths, "llvm-cov", feature_configuration, ACTION_NAMES.llvm_cov, default = None),
+        "LLVM_PROFDATA": _tool_path(cc_toolchain._tool_paths, "llvm-profdata", feature_configuration, ACTION_NAMES.llvm_profdata, default = None),
         "GENERATE_LLVM_LCOV": "1" if cc_config.generate_llvm_lcov() else "0",
     }
     for k in list(env.keys()):
@@ -1140,6 +1127,7 @@
     tokenize = _tokenize,
     is_valid_shared_library_artifact = _is_valid_shared_library_artifact,
     is_valid_shared_library_name = _is_valid_shared_library_name,
+    tool_path = _tool_path,
     get_toolchain_global_make_variables = _get_toolchain_global_make_variables,
     get_cc_flags_make_variable = _get_cc_flags_make_variable,
     get_compilation_contexts_from_deps = _get_compilation_contexts_from_deps,
diff --git a/cc/private/rules_impl/cc_toolchain_provider_helper.bzl b/cc/private/rules_impl/cc_toolchain_provider_helper.bzl
index bd85338..1470797 100644
--- a/cc/private/rules_impl/cc_toolchain_provider_helper.bzl
+++ b/cc/private/rules_impl/cc_toolchain_provider_helper.bzl
@@ -152,11 +152,25 @@
     )
     tool_paths = _compute_tool_paths(toolchain_config_info, tools_directory)
     toolchain_features = cc_common.cc_toolchain_features(toolchain_config_info = toolchain_config_info, tools_directory = tools_directory)
+
+    # action_is_enabled only returns true for action_configs that are in
+    # requested_features (or transitively implied). Request the action names
+    # we fall back to below so the guard in tool_path returns true
+    # when those action_configs are declared.
     feature_configuration = toolchain_features.configure_features(
-        requested_features = toolchain_features.default_features_and_action_configs() + [ACTION_NAMES.llvm_profdata],
+        requested_features = toolchain_features.default_features_and_action_configs() + [
+            ACTION_NAMES.c_compile,
+            ACTION_NAMES.cpp_link_static_library,
+            ACTION_NAMES.cpp_link_executable,
+            ACTION_NAMES.strip,
+            ACTION_NAMES.objcopy_embed_data,
+            ACTION_NAMES.gcov,
+            ACTION_NAMES.llvm_profdata,
+        ],
     )
+
     fdo_context = create_fdo_context(
-        llvm_profdata = tool_paths.get("llvm-profdata"),
+        llvm_profdata = cc_helper.tool_path(tool_paths, "llvm-profdata", feature_configuration, ACTION_NAMES.llvm_profdata),
         all_files = attributes.all_files,
         zipper = attributes.zipper,
         cc_toolchain_config_info = toolchain_config_info,
@@ -235,15 +249,15 @@
         solib_dir = solib_directory,
         additional_make_variables = _additional_make_variables(toolchain_config_info.make_variables),
         legacy_cc_flags_make_variable = _legacy_cc_flags_make_variable(toolchain_config_info.make_variables),
-        objcopy_executable = tool_paths.get("objcopy", ""),
-        compiler_executable = tool_paths.get("gcc", ""),
+        objcopy_executable = cc_helper.tool_path(tool_paths, "objcopy", feature_configuration, ACTION_NAMES.objcopy_embed_data),
+        compiler_executable = cc_helper.tool_path(tool_paths, "gcc", feature_configuration, ACTION_NAMES.c_compile),
         preprocessor_executable = tool_paths.get("cpp", ""),
         nm_executable = tool_paths.get("nm", ""),
         objdump_executable = tool_paths.get("objdump", ""),
-        ar_executable = tool_paths.get("ar", ""),
-        strip_executable = tool_paths.get("strip", ""),
-        ld_executable = tool_paths.get("ld", ""),
-        gcov_executable = tool_paths.get("gcov", ""),
+        ar_executable = cc_helper.tool_path(tool_paths, "ar", feature_configuration, ACTION_NAMES.cpp_link_static_library),
+        strip_executable = cc_helper.tool_path(tool_paths, "strip", feature_configuration, ACTION_NAMES.strip),
+        ld_executable = cc_helper.tool_path(tool_paths, "ld", feature_configuration, ACTION_NAMES.cpp_link_executable),
+        gcov_executable = cc_helper.tool_path(tool_paths, "gcov", feature_configuration, ACTION_NAMES.gcov),
         build_variables_dict = build_variables_dict,
         build_variables = build_variables,
         all_files = attributes.all_files,