Make cc_toolchain_config tool_paths configurable

Issue #5380

RELNOTES: None
PiperOrigin-RevId: 239020370
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/mock/cc_toolchain_config.bzl b/src/test/java/com/google/devtools/build/lib/analysis/mock/cc_toolchain_config.bzl
index b262286..60c7611 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/mock/cc_toolchain_config.bzl
+++ b/src/test/java/com/google/devtools/build/lib/analysis/mock/cc_toolchain_config.bzl
@@ -74,6 +74,8 @@
     dynamic_linking_mode = "dynamic_linking_mode",
     static_linking_mode = "static_linking_mode",
     compiler_param_file = "compiler_param_file",
+    objcopy_embed_flags = "objcopy_embed_flags",
+    ld_embed_flags = "ld_embed_flags",
 )
 
 _no_legacy_features_feature = feature(name = _FEATURE_NAMES.no_legacy_features)
@@ -150,6 +152,16 @@
     ],
 )
 
+_simple_layering_check_feature = feature(
+    name = _FEATURE_NAMES.layering_check,
+    flag_sets = [
+        flag_set(
+            actions = [ACTION_NAMES.cpp_compile],
+            flag_groups = [flag_group(flags = ["<flag>"])],
+        ),
+    ],
+)
+
 _header_modules_feature = feature(
     name = _FEATURE_NAMES.header_modules,
     implies = ["use_header_modules", "header_module_compile"],
@@ -659,6 +671,32 @@
     ],
 )
 
+_objcopy_embed_flags_feature = feature(
+    name = _FEATURE_NAMES.objcopy_embed_flags,
+    enabled = True,
+    flag_sets = [
+        flag_set(
+            actions = ["objcopy_embed_data"],
+            flag_groups = [
+                flag_group(flags = ["-objcopy-flag-1", "foo"]),
+            ],
+        ),
+    ],
+)
+
+_ld_embed_flags_feature = feature(
+    name = _FEATURE_NAMES.ld_embed_flags,
+    enabled = True,
+    flag_sets = [
+        flag_set(
+            actions = ["ld_embed_data"],
+            flag_groups = [
+                flag_group(flags = ["-ld-flag-1", "bar"]),
+            ],
+        ),
+    ],
+)
+
 _feature_name_to_feature = {
     _FEATURE_NAMES.no_legacy_features: _no_legacy_features_feature,
     _FEATURE_NAMES.do_not_split_linking_cmdline: _do_not_split_linking_cmdline_feature,
@@ -695,9 +733,12 @@
     _FEATURE_NAMES.link_env: _link_env_feature,
     _FEATURE_NAMES.static_linking_mode: _static_linking_mode_feature,
     _FEATURE_NAMES.dynamic_linking_mode: _dynamic_linking_mode_feature,
+    _FEATURE_NAMES.objcopy_embed_flags: _objcopy_embed_flags_feature,
+    _FEATURE_NAMES.ld_embed_flags: _ld_embed_flags_feature,
     "header_modules_feature_configuration": _header_modules_feature_configuration,
     "env_var_feature_configuration": _env_var_feature_configuration,
     "host_and_nonhost_configuration": _host_and_nonhost_configuration,
+    "simple_layering_check": _simple_layering_check_feature,
 }
 
 _static_link_as_dot_lib_pattern = artifact_name_pattern(
@@ -717,6 +758,11 @@
     "static_link_as_dot_a": _static_link_as_dot_a_pattern,
 }
 
+_tool_for_action_config = {
+    "objcopy_embed_data": "objcopy_embed_data_tool",
+    "ld_embed_data": "ld_embed_data_tool",
+}
+
 def _get_features_for_configuration(name):
     f = _feature_name_to_feature[name]
     if f == None:
@@ -726,10 +772,11 @@
     else:
         return [f]
 
-def _get_action_config(name):
+def _get_action_config(name, path):
     return action_config(
         action_name = name,
-        tools = [tool(path = "DUMMY_TOOL")],
+        enabled = True,
+        tools = [tool(path = path)],
     )
 
 def _get_artifact_name_pattern(name):
@@ -738,6 +785,9 @@
         fail("Artifact name pattern not defined: " + name)
     return artifact
 
+def _get_tool_path(name, path):
+    return tool_path(name = name, path = path)
+
 def _impl(ctx):
     toolchain_identifier = ctx.attr.toolchain_identifier
     host_system_name = ctx.attr.host_system_name
@@ -801,30 +851,35 @@
     action_configs = []
 
     for name in ctx.attr.action_configs:
-        action_configs.append(_get_action_config(name))
+        action_configs.append(
+            _get_action_config(name, _tool_for_action_config.get(name, default = "DUMMY_TOOL")),
+        )
 
     make_variables = []
 
-    tool_paths = [
-        tool_path(name = "ar", path = "/usr/bin/mock-ar"),
-        tool_path(
-            name = "compat-ld",
-            path = "/usr/bin/mock-compat-ld",
-        ),
-        tool_path(name = "cpp", path = "/usr/bin/mock-cpp"),
-        tool_path(name = "dwp", path = "/usr/bin/mock-dwp"),
-        tool_path(name = "gcc", path = "/usr/bin/mock-gcc"),
-        tool_path(name = "gcov", path = "/usr/bin/mock-gcov"),
-        tool_path(name = "ld", path = "/usr/bin/mock-ld"),
-        tool_path(name = "nm", path = "/usr/bin/mock-nm"),
-        tool_path(name = "objcopy", path = "/usr/bin/mock-objcopy"),
-        tool_path(name = "objdump", path = "/usr/bin/mock-objdump"),
-        tool_path(name = "strip", path = "/usr/bin/mock-strip"),
-        tool_path(
-            name = "llvm-profdata",
-            path = "/usr/bin/mock-llvm-profdata",
-        ),
-    ]
+    if ctx.attr.tool_paths == {}:
+        tool_paths = [
+            tool_path(name = "ar", path = "/usr/bin/mock-ar"),
+            tool_path(
+                name = "compat-ld",
+                path = "/usr/bin/mock-compat-ld",
+            ),
+            tool_path(name = "cpp", path = "/usr/bin/mock-cpp"),
+            tool_path(name = "dwp", path = "/usr/bin/mock-dwp"),
+            tool_path(name = "gcc", path = "/usr/bin/mock-gcc"),
+            tool_path(name = "gcov", path = "/usr/bin/mock-gcov"),
+            tool_path(name = "ld", path = "/usr/bin/mock-ld"),
+            tool_path(name = "nm", path = "/usr/bin/mock-nm"),
+            tool_path(name = "objcopy", path = "/usr/bin/mock-objcopy"),
+            tool_path(name = "objdump", path = "/usr/bin/mock-objdump"),
+            tool_path(name = "strip", path = "/usr/bin/mock-strip"),
+            tool_path(
+                name = "llvm-profdata",
+                path = "/usr/bin/mock-llvm-profdata",
+            ),
+        ]
+    else:
+        tool_paths = [_get_tool_path(name, path) for name, path in ctx.attr.tool_paths.items()]
 
     out = ctx.actions.declare_file(ctx.label.name)
     ctx.actions.write(out, "Fake executable")
@@ -869,6 +924,7 @@
         "artifact_name_patterns": attr.string_list(),
         "cc_target_os": attr.string(),
         "builtin_sysroot": attr.string(default = "/usr/grte/v1"),
+        "tool_paths": attr.string_dict(),
     },
     provides = [CcToolchainConfigInfo],
     executable = True,
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/Crosstool.java b/src/test/java/com/google/devtools/build/lib/packages/util/Crosstool.java
index e1c31ae..ddb4bf4 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/util/Crosstool.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/Crosstool.java
@@ -17,6 +17,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.rules.cpp.CppRuleClasses;
 import com.google.devtools.build.lib.testutil.TestConstants;
+import com.google.devtools.build.lib.util.Pair;
 import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig;
 import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CToolchain;
 import com.google.protobuf.TextFormat;
@@ -52,6 +53,7 @@
     private final ImmutableList<String> features;
     private final ImmutableList<String> actionConfigs;
     private final ImmutableList<String> artifactNamePatterns;
+    private final ImmutableList<Pair<String, String>> toolPaths;
 
     private CcToolchainConfig(
         String cpu,
@@ -64,7 +66,8 @@
         String targetLibc,
         ImmutableList<String> features,
         ImmutableList<String> actionConfigs,
-        ImmutableList<String> artifactNamePatterns) {
+        ImmutableList<String> artifactNamePatterns,
+        ImmutableList<Pair<String, String>> toolPaths) {
       this.cpu = cpu;
       this.compiler = compiler;
       this.toolchainIdentifier = toolchainIdentifier;
@@ -76,6 +79,7 @@
       this.features = features;
       this.actionConfigs = actionConfigs;
       this.artifactNamePatterns = artifactNamePatterns;
+      this.toolPaths = toolPaths;
     }
 
     public static Builder builder() {
@@ -87,6 +91,7 @@
       private ImmutableList<String> features = ImmutableList.of();
       private ImmutableList<String> actionConfigs = ImmutableList.of();
       private ImmutableList<String> artifactNamePatterns = ImmutableList.of();
+      private ImmutableList<Pair<String, String>> toolPaths = ImmutableList.of();
 
       public Builder withFeatures(String... features) {
         this.features = ImmutableList.copyOf(features);
@@ -103,6 +108,11 @@
         return this;
       }
 
+      public Builder withToolPaths(Pair<String, String>... toolPaths) {
+        this.toolPaths = ImmutableList.copyOf(toolPaths);
+        return this;
+      }
+
       public CcToolchainConfig build() {
         return new CcToolchainConfig(
             /* cpu= */ "k8",
@@ -115,7 +125,8 @@
             /* targetLibc= */ "local",
             features,
             actionConfigs,
-            artifactNamePatterns);
+            artifactNamePatterns,
+            toolPaths);
       }
     }
 
@@ -147,7 +158,8 @@
           /* targetLibc= */ "mock-libc-for-" + cpu,
           /* features= */ ImmutableList.of(),
           /* actionConfigs= */ ImmutableList.of(),
-          /* artifactNamePatterns= */ ImmutableList.of());
+          /* artifactNamePatterns= */ ImmutableList.of(),
+          /* toolPaths= */ ImmutableList.of());
     }
 
     public static CcToolchainConfig getDefaultCcToolchainConfig() {
@@ -167,6 +179,10 @@
           artifactNamePatterns.stream()
               .map(pattern -> "'" + pattern + "'")
               .collect(ImmutableList.toImmutableList());
+      ImmutableList<String> toolPathsList =
+          toolPaths.stream()
+              .map(toolPath -> String.format("'%s': '%s'", toolPath.first, toolPath.second))
+              .collect(ImmutableList.toImmutableList());
 
       return Joiner.on("\n")
           .join(
@@ -184,6 +200,7 @@
                   "  action_configs = [%s],", Joiner.on(",\n    ").join(actionConfigsList)),
               String.format(
                   "  artifact_name_patterns = [%s],", Joiner.on(",\n    ").join(patternsList)),
+              String.format("  tool_paths = {%s},", Joiner.on(",\n    ").join(toolPathsList)),
               "  )");
     }
   }
@@ -268,7 +285,8 @@
                     .map(feature -> feature.getName())
                     .collect(ImmutableList.toImmutableList()),
                 /* actionConfigs= */ ImmutableList.of(),
-                /* artifactNamePatterns= */ ImmutableList.of()));
+                /* artifactNamePatterns= */ ImmutableList.of(),
+                /* toolPaths= */ ImmutableList.of()));
       }
       ccToolchainConfigs = toolchainConfigInfoBuilder.build();
     }
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java
index 84739c4..eceb14e 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockCcSupport.java
@@ -118,6 +118,8 @@
           + "  }"
           + "}";
 
+  public static final String SIMPLE_LAYERING_CHECK_FEATURE_CONFIGURATION = "simple_layering_check";
+
   /** A feature configuration snippet useful for testing header modules. */
   public static final String HEADER_MODULES_FEATURE_CONFIGURATION =
       "feature {"
@@ -247,6 +249,9 @@
           + "  }"
           + "}";
 
+  public static final String HOST_AND_NONHOST_CONFIGURATION_FEATURES =
+      "host_and_nonhost_configuration";
+
   public static final String USER_COMPILE_FLAGS_CONFIGURATION =
       "feature {"
           + "  name: 'user_compile_flags'"