diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java
index a22c7a3f327d15..f5ca99384c657a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java
@@ -176,7 +176,6 @@ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env)
// TODO(b/78578234): Make this the default and remove the late-bound versions.
.add(attr("libc_top", LABEL).allowedFileTypes())
.add(attr(LIBC_TOP_ATTR, LABEL).value(LIBC_TOP_VALUE))
-
.add(attr(FDO_OPTIMIZE_ATTR, LABEL).singleArtifact().value(FDO_OPTIMIZE_VALUE))
.add(
attr(FDO_PROFILE_ATTR, LABEL)
@@ -194,6 +193,10 @@ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env)
.value(CppRuleClasses.LIPO_CONTEXT_COLLECTOR)
.skipPrereqValidatorCheck())
.add(attr("proto", Type.STRING))
+ .add(
+ attr("toolchain_identifier", Type.STRING)
+ .nonconfigurable("Used in configuration creation")
+ .value(""))
.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
index 317d52db40b630..73d6c538c10cc4 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
@@ -55,6 +55,35 @@
* This class represents the C/C++ parts of the {@link BuildConfiguration}, including the host
* architecture, target architecture, compiler version, and a standard library version. It has
* information about the tools locations and the flags required for compiling.
+ *
+ *
Before {@link CppConfiguration} is created, two things need to be done:
+ *
+ *
+ * - choosing a {@link CcToolchainRule} label from {@code toolchains} map attribute of {@link
+ * CcToolchainSuiteRule}.
+ *
- selection of a {@link
+ * com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CToolchain} from the
+ * CROSSTOOL file.
+ *
+ *
+ * The process goes as follows:
+ *
+ *
Check for existence of {@link CcToolchainSuiteRule}.toolchains[|], if
+ * --compiler is specified, otherwise check for {@link CcToolchainSuiteRule}.toolchains[].
+ *
+ *
+ * - if a value is found, load the {@link CcToolchainRule} rule and look for the {@code
+ * toolchain_identifier} attribute.
+ *
-
+ *
+ * - if the attribute exists, loop through all the {@code CToolchain}s in CROSSTOOL and
+ * select the one with the matching toolchain identifier.
+ *
- otherwise fall back to selecting the CToolchain from CROSSTOOL by matching the --cpu
+ * and --compiler values.
+ *
+ * - If a value is not found, select the CToolchain from CROSSTOOL by matching the --cpu and
+ * --compiler values, and construct the key as follows: |.
+ *
*/
@AutoCodec
@Immutable
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java
index e20e3a0d4c8088..48ec524c0b0973 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfigurationLoader.java
@@ -32,6 +32,7 @@
import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig;
@@ -142,9 +143,6 @@ protected CppConfigurationParameters createParameters(
if (file == null) {
return null;
}
- CrosstoolConfig.CToolchain toolchain =
- CrosstoolConfigurationLoader.selectToolchain(
- file.getProto(), options, cpuTransformer.getTransformer());
PathFragment fdoPath = null;
Label fdoProfileLabel = null;
@@ -168,18 +166,17 @@ protected CppConfigurationParameters createParameters(
Label ccToolchainLabel;
Target crosstoolTop;
-
+ CrosstoolConfig.CToolchain toolchain = null;
try {
crosstoolTop = env.getTarget(crosstoolTopLabel);
} catch (NoSuchThingException e) {
throw new IllegalStateException(e); // Should have been found out during redirect chasing
}
+ String desiredCpu = cpuTransformer.getTransformer().apply(options.get(Options.class).cpu);
if (crosstoolTop instanceof Rule
&& ((Rule) crosstoolTop).getRuleClass().equals("cc_toolchain_suite")) {
Rule ccToolchainSuite = (Rule) crosstoolTop;
-
- String desiredCpu = cpuTransformer.getTransformer().apply(options.get(Options.class).cpu);
String key =
desiredCpu + (cppOptions.cppCompiler == null ? "" : ("|" + cppOptions.cppCompiler));
Map toolchains =
@@ -187,13 +184,21 @@ protected CppConfigurationParameters createParameters(
.get("toolchains", BuildType.LABEL_DICT_UNARY);
ccToolchainLabel = toolchains.get(key);
if (ccToolchainLabel == null) {
+ // If the cc_toolchain_suite does not contain entry for --cpu|--compiler (or only --cpu if
+ // --compiler is not present) we select the toolchain by looping through all the toolchains
+ // in the CROSSTOOL file and selecting the one that matches --cpu (and --compiler, if
+ // present). Then we use the toolchain.target_cpu|toolchain.compiler key to get the
+ // cc_toolchain label.
+ toolchain =
+ CrosstoolConfigurationLoader.selectToolchain(
+ file.getProto(), options, cpuTransformer.getTransformer());
ccToolchainLabel = toolchains.get(toolchain.getTargetCpu() + "|" + toolchain.getCompiler());
}
if (ccToolchainLabel == null) {
String errorMessage =
String.format(
"cc_toolchain_suite '%s' does not contain a toolchain for CPU '%s'",
- crosstoolTopLabel, toolchain.getTargetCpu());
+ crosstoolTopLabel, desiredCpu);
if (cppOptions.cppCompiler != null) {
errorMessage = errorMessage + " and compiler " + cppOptions.cppCompiler;
}
@@ -221,6 +226,22 @@ protected CppConfigurationParameters createParameters(
"The label '%s' is not a cc_toolchain rule", ccToolchainLabel));
}
+ if (toolchain == null) {
+ // If cc_toolchain_suite contains an entry for the given --cpu and --compiler options, we
+ // select the toolchain by its identifier if "toolchain_identifier" attribute is present.
+ // Otherwise, we fall back to going through the CROSSTOOL file to select the toolchain using
+ // the legacy selection mechanism.
+ String identifier =
+ NonconfigurableAttributeMapper.of((Rule) ccToolchain)
+ .get("toolchain_identifier", Type.STRING);
+ toolchain =
+ identifier.isEmpty()
+ ? CrosstoolConfigurationLoader.selectToolchain(
+ file.getProto(), options, cpuTransformer.getTransformer())
+ : CrosstoolConfigurationLoader.getToolchainByIdentifier(
+ file.getProto(), identifier, desiredCpu, cppOptions.cppCompiler);
+ }
+
Label sysrootLabel = getSysrootLabel(toolchain, cppOptions.libcTopLabel);
return new CppConfigurationParameters(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java
index caed2d37b6ecb7..a475aeb1a2f2e3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CrosstoolConfigurationLoader.java
@@ -18,6 +18,7 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
+import com.google.common.base.Strings;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.io.BaseEncoding;
@@ -375,7 +376,7 @@ public static CrosstoolConfig.CToolchain selectToolchain(
+ cpuBuilder
+ "]");
}
- checkToolChain(selectedIdentifier, desiredCpu);
+ checkToolchain(selectedIdentifier, desiredCpu);
for (CrosstoolConfig.CToolchain toolchain : release.getToolchainList()) {
if (toolchain.getToolchainIdentifier().equals(selectedIdentifier)) {
@@ -406,15 +407,14 @@ private static void describeToolchainList(StringBuilder message,
}
/**
- * Makes sure that {@code selectedIdentifier} is a valid identifier for a toolchain,
- * i.e. it starts with a letter or an underscore and continues with only dots, dashes,
- * spaces, letters, digits or underscores (i.e. matches the following regular expression:
- * "[a-zA-Z_][\.\- \w]*").
+ * Makes sure that {@code selectedIdentifier} is a valid identifier for a toolchain, i.e. it
+ * starts with a letter or an underscore and continues with only dots, dashes, spaces, letters,
+ * digits or underscores (i.e. matches the following regular expression: "[a-zA-Z_][\.\- \w]*").
*
- * @throws InvalidConfigurationException if selectedIdentifier does not match the
- * aforementioned regular expression.
+ * @throws InvalidConfigurationException if selectedIdentifier does not match the aforementioned
+ * regular expression.
*/
- private static void checkToolChain(String selectedIdentifier, String cpu)
+ private static void checkToolchain(String selectedIdentifier, String cpu)
throws InvalidConfigurationException {
// If you update this regex, please do so in the javadoc comment too, and also in the
// crosstool_config.proto file.
@@ -438,4 +438,47 @@ public static CrosstoolConfig.CrosstoolRelease getCrosstoolReleaseProto(
selectToolchain(file.getProto(), options, cpuTransformer);
return file.getProto();
}
+
+ /**
+ * Selects a crosstool toolchain based on the toolchain identifier.
+ *
+ * @throws InvalidConfigurationException if no matching toolchain can be found, if multiple
+ * toolchains with the same identifier are found, or if the target_cpu or compiler of the
+ * selected toolchain are not the same as --cpu and --compiler options.
+ */
+ public static CrosstoolConfig.CToolchain getToolchainByIdentifier(
+ CrosstoolConfig.CrosstoolRelease proto,
+ String toolchainIdentifier,
+ String cpu,
+ @Nullable String compiler)
+ throws InvalidConfigurationException {
+ checkToolchain(toolchainIdentifier, cpu);
+ CrosstoolConfig.CToolchain selectedToolchain = null;
+ for (CrosstoolConfig.CToolchain toolchain : proto.getToolchainList()) {
+ if (toolchain.getToolchainIdentifier().equals(toolchainIdentifier)) {
+ if (selectedToolchain != null) {
+ throw new InvalidConfigurationException(
+ String.format("Multiple toolchains with '%s' identifier", toolchainIdentifier));
+ }
+ selectedToolchain = toolchain;
+ }
+ }
+ if (selectedToolchain == null) {
+ throw new InvalidConfigurationException(
+ String.format("Toolchain identifier '%s' was not found", toolchainIdentifier));
+ }
+ if ((compiler != null && !selectedToolchain.getCompiler().equals(compiler))
+ || !selectedToolchain.getTargetCpu().equals(cpu)) {
+ throw new InvalidConfigurationException(
+ String.format(
+ "The selected toolchain's cpu and compiler must match the command line options:\n"
+ + " --cpu: %s, toolchain.target_cpu: %s\n"
+ + " --compiler: %s, toolchain.compiler: %s",
+ cpu,
+ selectedToolchain.getTargetCpu(),
+ Strings.nullToEmpty(compiler),
+ selectedToolchain.getCompiler()));
+ }
+ return selectedToolchain;
+ }
}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuiteTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuiteTest.java
index f6925f2d855d32..869601122dd020 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuiteTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuiteTest.java
@@ -380,4 +380,316 @@ public void testCcToolchainLabelFromAttributes() throws Exception {
.contains("The label '//cc:invalid-label' is not a cc_toolchain rule");
}
}
+
+ @Test
+ public void testCcToolchainFromToolchainIdentifier() throws Exception {
+ scratch.file(
+ "cc/BUILD",
+ "filegroup(name='empty')",
+ "filegroup(name='everything')",
+ "TOOLCHAIN_NAMES = [",
+ " 'k8',",
+ " 'ppc',",
+ " 'darwin',",
+ " 'windows']",
+ "[cc_toolchain(",
+ " name = NAME,",
+ " cpu = 'banana',",
+ " all_files = ':empty',",
+ " ar_files = ':empty',",
+ " as_files = ':empty',",
+ " compiler_files = ':empty',",
+ " dwp_files = ':empty',",
+ " linker_files = ':empty',",
+ " strip_files = ':empty',",
+ " objcopy_files = ':empty',",
+ " dynamic_runtime_libs = [':empty'],",
+ " static_runtime_libs = [':empty'],",
+ ") for NAME in TOOLCHAIN_NAMES]",
+ "[cc_toolchain(",
+ " name = NAME + '-override',",
+ " cpu = 'banana',",
+ " all_files = ':empty',",
+ " ar_files = ':empty',",
+ " as_files = ':empty',",
+ " compiler_files = ':empty',",
+ " dwp_files = ':empty',",
+ " linker_files = ':empty',",
+ " strip_files = ':empty',",
+ " objcopy_files = ':empty',",
+ " dynamic_runtime_libs = [':empty'],",
+ " static_runtime_libs = [':empty'],",
+ " toolchain_identifier = NAME + '-from-attribute'",
+ ") for NAME in TOOLCHAIN_NAMES]",
+ "cc_toolchain(",
+ " name = 'invalid',",
+ " cpu = 'banana',",
+ " all_files = ':empty',",
+ " ar_files = ':empty',",
+ " as_files = ':empty',",
+ " compiler_files = ':empty',",
+ " dwp_files = ':empty',",
+ " linker_files = ':empty',",
+ " strip_files = ':empty',",
+ " objcopy_files = ':empty',",
+ " dynamic_runtime_libs = [':empty'],",
+ " static_runtime_libs = [':empty'],",
+ " toolchain_identifier = 'invalid-toolchain',",
+ ")",
+ "cc_toolchain(",
+ " name = 'duplicate',",
+ " cpu = 'banana',",
+ " all_files = ':empty',",
+ " ar_files = ':empty',",
+ " as_files = ':empty',",
+ " compiler_files = ':empty',",
+ " dwp_files = ':empty',",
+ " linker_files = ':empty',",
+ " strip_files = ':empty',",
+ " objcopy_files = ':empty',",
+ " dynamic_runtime_libs = [':empty'],",
+ " static_runtime_libs = [':empty'],",
+ " toolchain_identifier = 'duplicate-toolchain',",
+ ")",
+ "cc_toolchain(",
+ " name = 'wrong-compiler',",
+ " cpu = 'banana',",
+ " all_files = ':empty',",
+ " ar_files = ':empty',",
+ " as_files = ':empty',",
+ " compiler_files = ':empty',",
+ " dwp_files = ':empty',",
+ " linker_files = ':empty',",
+ " strip_files = ':empty',",
+ " objcopy_files = ':empty',",
+ " dynamic_runtime_libs = [':empty'],",
+ " static_runtime_libs = [':empty'],",
+ " toolchain_identifier = 'wrong-compiler-toolchain',",
+ ")",
+ "cc_toolchain_suite(",
+ " name = 'suite',",
+ " toolchains = {",
+ " 'k8': ':k8-override',",
+ " 'k8|compiler': ':k8',",
+ " 'k8|compiler-from-attribute': ':k8-override',",
+ " 'ppc|compiler': ':invalid',",
+ " 'ppc|compiler-from-attribute': ':ppc-override',",
+ " 'k8|compiler1': ':duplicate',",
+ " 'k8|right-compiler': ':wrong-compiler',",
+ " 'x64_windows' : ':windows',",
+ " 'x64_windows|compiler' : ':windows',",
+ " 'x64_windows|compiler-from-attribute' : ':windows',",
+ " 'x64_windows|compiler1' : ':windows',",
+ " 'x64_windows|right-compiler' : ':windows',",
+ " 'darwin' : ':darwin',",
+ " 'darwin|compiler' : ':darwin',",
+ " 'darwin|compiler-from-attribute' : ':darwin',",
+ " 'darwin|compiler1' : ':darwin',",
+ " 'darwin|right-compiler' : ':darwin',",
+ " },",
+ " proto = \"\"\"",
+ "major_version: 'v1'",
+ "minor_version: '0'",
+ "default_target_cpu: 'k8'",
+ "default_toolchain {",
+ " cpu: 'k8'",
+ " toolchain_identifier: 'k8-toolchain-identifier'",
+ "}",
+ "default_toolchain {",
+ " cpu: 'ppc'",
+ " toolchain_identifier: 'ppc-toolchain-identifier'",
+ "}",
+ "default_toolchain {",
+ " cpu: 'darwin'",
+ " toolchain_identifier: 'darwin-toolchain-identifier'",
+ "}",
+ "default_toolchain {",
+ " cpu: 'x64_windows'",
+ " toolchain_identifier: 'windows-toolchain-identifier'",
+ "}",
+ "toolchain {",
+ " compiler: 'compiler'",
+ " target_cpu: 'k8'",
+ " toolchain_identifier: 'k8-toolchain-identifier'",
+ " host_system_name: 'linux'",
+ " target_system_name: 'linux'",
+ " abi_version: 'cpu-abi'",
+ " abi_libc_version: ''",
+ " target_libc: 'local'",
+ " builtin_sysroot: 'sysroot'",
+ " default_grte_top: '//cc:grtetop'",
+ "}",
+ "toolchain {",
+ " compiler: 'compiler-from-attribute'",
+ " target_cpu: 'k8'",
+ " toolchain_identifier: 'k8-from-attribute'",
+ " host_system_name: 'linux'",
+ " target_system_name: 'linux'",
+ " abi_version: 'cpu-abi'",
+ " abi_libc_version: ''",
+ " target_libc: 'local'",
+ " builtin_sysroot: 'sysroot'",
+ " default_grte_top: '//cc:grtetop'",
+ "}",
+ "toolchain {",
+ " compiler: 'compiler'",
+ " target_cpu: 'ppc'",
+ " toolchain_identifier: 'ppc-toolchain-identifier'",
+ " host_system_name: 'linux'",
+ " target_system_name: 'linux'",
+ " abi_version: 'cpu-abi'",
+ " abi_libc_version: ''",
+ " target_libc: 'local'",
+ " builtin_sysroot: 'sysroot'",
+ " default_grte_top: '//cc:grtetop'",
+ "}",
+ "toolchain {",
+ " compiler: 'compiler-from-attribute'",
+ " target_cpu: 'ppc'",
+ " toolchain_identifier: 'ppc-from-attribute'",
+ " host_system_name: 'linux'",
+ " target_system_name: 'linux'",
+ " abi_version: 'cpu-abi'",
+ " abi_libc_version: ''",
+ " target_libc: 'local'",
+ " builtin_sysroot: 'sysroot'",
+ " default_grte_top: '//cc:grtetop'",
+ "}",
+ "toolchain {",
+ " compiler: 'compiler'",
+ " target_cpu: 'darwin'",
+ " toolchain_identifier: 'darwin-toolchain-identifier'",
+ " host_system_name: 'linux'",
+ " target_system_name: 'linux'",
+ " abi_version: ''",
+ " abi_libc_version: ''",
+ " target_libc: ''",
+ " builtin_sysroot: 'sysroot'",
+ " default_grte_top: '//cc:grtetop'",
+ "}",
+ "toolchain {",
+ " compiler: 'compiler-from-attribute'",
+ " target_cpu: 'darwin'",
+ " toolchain_identifier: 'darwin-from-attribute'",
+ " host_system_name: 'linux'",
+ " target_system_name: 'linux'",
+ " abi_version: 'cpu-abi'",
+ " abi_libc_version: ''",
+ " target_libc: 'local'",
+ " builtin_sysroot: 'sysroot'",
+ " default_grte_top: '//cc:grtetop'",
+ "}",
+ "toolchain {",
+ " compiler: 'compiler'",
+ " target_cpu: 'x64_windows'",
+ " toolchain_identifier: 'windows-toolchain-identifier'",
+ " host_system_name: 'windows'",
+ " target_system_name: 'windows'",
+ " abi_version: ''",
+ " abi_libc_version: ''",
+ " target_libc: ''",
+ " builtin_sysroot: 'sysroot'",
+ " default_grte_top: '//cc:grtetop'",
+ "}",
+ "toolchain {",
+ " compiler: 'compiler-from-attribute'",
+ " target_cpu: 'x64_windows'",
+ " toolchain_identifier: 'windows-from-attribute'",
+ " host_system_name: 'linux'",
+ " target_system_name: 'linux'",
+ " abi_version: 'cpu-abi'",
+ " abi_libc_version: ''",
+ " target_libc: 'local'",
+ " builtin_sysroot: 'sysroot'",
+ " default_grte_top: '//cc:grtetop'",
+ "}",
+ "toolchain {",
+ " compiler: 'compiler1'",
+ " target_cpu: 'k8'",
+ " toolchain_identifier: 'duplicate-toolchain'",
+ " host_system_name: 'linux'",
+ " target_system_name: 'linux'",
+ " abi_version: 'cpu-abi'",
+ " abi_libc_version: ''",
+ " target_libc: 'local'",
+ " builtin_sysroot: 'sysroot'",
+ " default_grte_top: '//cc:grtetop'",
+ "}",
+ "toolchain {",
+ " compiler: 'compiler2'",
+ " target_cpu: 'k8'",
+ " toolchain_identifier: 'duplicate-toolchain'",
+ " host_system_name: 'linux'",
+ " target_system_name: 'linux'",
+ " abi_version: 'cpu-abi'",
+ " abi_libc_version: ''",
+ " target_libc: 'local'",
+ " builtin_sysroot: 'sysroot'",
+ " default_grte_top: '//cc:grtetop'",
+ "}",
+ "toolchain {",
+ " compiler: 'wrong-compiler'",
+ " target_cpu: 'k8'",
+ " toolchain_identifier: 'wrong-compiler-toolchain'",
+ " host_system_name: 'linux'",
+ " target_system_name: 'linux'",
+ " abi_version: 'cpu-abi'",
+ " abi_libc_version: ''",
+ " target_libc: 'local'",
+ " builtin_sysroot: 'sysroot'",
+ " default_grte_top: '//cc:grtetop'",
+ "}",
+ "\"\"\"",
+ ")");
+
+ scratch.file("a/BUILD", "cc_binary(name='b', srcs=['b.cc'])");
+
+ useConfiguration("--crosstool_top=//cc:suite", "--cpu=k8");
+ ConfiguredTarget c = getConfiguredTarget("//a:b");
+ CppConfiguration config = getConfiguration(c).getFragment(CppConfiguration.class);
+ assertThat(config.getToolchainIdentifier()).isEqualTo("k8-from-attribute");
+
+ useConfiguration("--crosstool_top=//cc:suite", "--cpu=ppc");
+ c = getConfiguredTarget("//a:b");
+ config = getConfiguration(c).getFragment(CppConfiguration.class);
+ assertThat(config.getToolchainIdentifier()).isEqualTo("ppc-toolchain-identifier");
+
+ useConfiguration(
+ "--crosstool_top=//cc:suite", "--compiler=compiler-from-attribute", "--cpu=ppc");
+ config = getConfiguration(getConfiguredTarget("//a:b")).getFragment(CppConfiguration.class);
+ assertThat(config.getToolchainIdentifier()).isEqualTo("ppc-from-attribute");
+
+ try {
+ useConfiguration("--crosstool_top=//cc:suite", "--compiler=compiler", "--cpu=ppc");
+ getConfiguration(getConfiguredTarget("//a:b")).getFragment(CppConfiguration.class);
+ fail("expected failure because ppc|compiler entry points to an invalid toolchain identifier");
+ } catch (InvalidConfigurationException e) {
+ assertThat(e)
+ .hasMessageThat()
+ .contains("Toolchain identifier 'invalid-toolchain' was not found");
+ }
+
+ try {
+ useConfiguration("--crosstool_top=//cc:suite", "--compiler=compiler1", "--cpu=k8");
+ getConfiguration(getConfiguredTarget("//a:b")).getFragment(CppConfiguration.class);
+ fail("expected failure because of duplicate toolchain identifier");
+ } catch (InvalidConfigurationException e) {
+ assertThat(e)
+ .hasMessageThat()
+ .contains("Multiple toolchains with 'duplicate-toolchain' identifier");
+ }
+
+ try {
+ useConfiguration("--crosstool_top=//cc:suite", "--compiler=right-compiler", "--cpu=k8");
+ getConfiguration(getConfiguredTarget("//a:b")).getFragment(CppConfiguration.class);
+ fail("expected failure because toolchain.compiler does not equal --compiler");
+ } catch (InvalidConfigurationException e) {
+ assertThat(e)
+ .hasMessageThat()
+ .contains(
+ "The selected toolchain's cpu and compiler must match the command line options:\n"
+ + " --cpu: k8, toolchain.target_cpu: k8\n"
+ + " --compiler: right-compiler, toolchain.compiler: wrong-compiler");
+ }
+ }
}