From 46e65d1fb236d0eea9d2f8511e7412d98b534fc6 Mon Sep 17 00:00:00 2001 From: hlopko Date: Thu, 13 Sep 2018 08:06:38 -0700 Subject: [PATCH] Do not rely on CppConfiguration package loading when selecting toolchain in cc_toolchain Rather re-select the toolchain for yourself. The next step will be to stop relying on CROSSTOOL in the CppConfiguration. #6072. RELNOTES: None. PiperOrigin-RevId: 212813981 --- .../rules/cpp/CToolchainSelectionUtils.java | 270 ++++++++++++++++++ .../build/lib/rules/cpp/CcToolchain.java | 35 +-- .../build/lib/rules/cpp/CppConfiguration.java | 23 ++ .../lib/rules/cpp/CppConfigurationLoader.java | 36 ++- .../cpp/CrosstoolConfigurationLoader.java | 183 +----------- .../devtools/build/lib/util/StringUtil.java | 10 + .../config/BuildConfigurationTest.java | 7 +- .../lib/packages/util/BazelMockCcSupport.java | 39 ++- .../build/lib/packages/util/Crosstool.java | 34 ++- .../packages/util/MockPlatformSupport.java | 3 +- .../rules/cpp/CcToolchainSelectionTest.java | 2 + .../lib/rules/cpp/CcToolchainSuiteTest.java | 17 +- .../build/lib/rules/cpp/CcToolchainTest.java | 47 --- .../build/lib/util/StringUtilTest.java | 9 + tools/cpp/CROSSTOOL.tpl | 5 - 15 files changed, 403 insertions(+), 317 deletions(-) create mode 100644 src/main/java/com/google/devtools/build/lib/rules/cpp/CToolchainSelectionUtils.java diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CToolchainSelectionUtils.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CToolchainSelectionUtils.java new file mode 100644 index 00000000000000..0dc900237f1f06 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CToolchainSelectionUtils.java @@ -0,0 +1,270 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.lib.rules.cpp; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; +import com.google.devtools.build.lib.util.StringUtil; +import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig; +import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CToolchain; +import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CrosstoolRelease; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import javax.annotation.Nullable; + +/** + * Utils class for logic responsible for selecting a CToolchain from the CROSSTOOL file given the + * cc_toolchain. + */ +public class CToolchainSelectionUtils { + + /** + * Do-it-all CToolchain selection method that considers toolchain identifiers, cpu/compiler + * attributes, and cpu/compiler options. Returns the CToolchain from the CROSSTOOL. If you need to + * call anything else than this, you're holding it wrong. + * + * @param identifierAttribute value of the cc_toolchain.toolchain_identifier attribute + * @param cpuAttribute value of the cc_toolchain.cpu attribute + * @param compilerAttribute value of the cc_toolchain.compiler attribute + * @param cpuOption value of the --cpu option + * @param compilerOption value of the --compiler option + * @param proto content of the CROSSTOOL file + * @param cpuTransformer because life is hard + * @return selected CToolchain or throws InvalidConfigurationException when not found. Never + * returns null. + */ + public static CToolchain selectCToolchain( + @Nullable String identifierAttribute, + @Nullable String cpuAttribute, + @Nullable String compilerAttribute, + String cpuOption, + @Nullable String compilerOption, + CrosstoolRelease proto, + Function cpuTransformer) + throws InvalidConfigurationException { + String identifierAttributeOrNull = StringUtil.emptyToNull(identifierAttribute); + String cpuAttributeOrNull = StringUtil.emptyToNull(cpuAttribute); + String compilerAttributeOrNull = StringUtil.emptyToNull(compilerAttribute); + + Preconditions.checkNotNull(cpuOption); + String compilerOptionOrNull = StringUtil.emptyToNull(compilerOption); + + return selectCToolchainNoEmptyStrings( + identifierAttributeOrNull, + cpuAttributeOrNull, + compilerAttributeOrNull, + cpuOption, + compilerOptionOrNull, + proto, + cpuTransformer); + } + + private static CToolchain selectCToolchainNoEmptyStrings( + String identifierAttribute, + String cpuAttribute, + String compilerAttribute, + String cpuOption, + String compilerOption, + CrosstoolRelease proto, + Function cpuTransformer) + throws InvalidConfigurationException { + CToolchain cToolchain = null; + // Use the identifier to find the CToolchain from the CROSSTOOL (this is the way how + // cc_toolchain will select CToolchain in the happy future, since it works with platforms). + if (identifierAttribute != null) { + cToolchain = getToolchainByIdentifier(proto, identifierAttribute); + } + if (cToolchain == null && cpuAttribute != null) { + // Let's try to select the CToolchain using cpu and compiler rule attributes (the semi-new + // way, compatible with platforms). + try { + cToolchain = + selectToolchainUsingCpuAndMaybeCompiler( + proto, + new CrosstoolConfigurationIdentifier(cpuAttribute, compilerAttribute), + cpuTransformer); + } catch (InvalidConfigurationException e) { + // We couldn't find the CToolchain using attributes, let's catch the exception and try + // with options. It's safe to ignore the exception here, since if it was caused by + // something else than the selection, it will be re-thrown below. + } + } + if (cToolchain == null) { + // We couldn't find the CToolchain using cpu and compiler attributes, let's try to select + // it using --cpu/--compiler options (the legacy way, doesn't work with platforms). + cToolchain = + selectToolchainUsingCpuAndMaybeCompiler( + proto, + new CrosstoolConfigurationIdentifier(cpuOption, compilerOption), + cpuTransformer); + } + return cToolchain; + } + + /** + * Selects a crosstool toolchain based on the toolchain identifier. + * + * @throws InvalidConfigurationException if no matching toolchain can be found, or if multiple + * toolchains with the same identifier are found. + */ + private static CToolchain getToolchainByIdentifier( + CrosstoolRelease proto, String toolchainIdentifier) throws InvalidConfigurationException { + checkToolchain(toolchainIdentifier); + CToolchain selectedToolchain = null; + for (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)); + } + return selectedToolchain; + } + + /** + * 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. + */ + private static void checkToolchain(String selectedIdentifier) + throws InvalidConfigurationException { + // If you update this regex, please do so in the javadoc comment too, and also in the + // crosstool_config.proto file. + String rx = "[a-zA-Z_][\\.\\- \\w]*"; + if (!selectedIdentifier.matches(rx)) { + throw new InvalidConfigurationException( + String.format( + "Toolchain identifier '%s' is illegal (does not match '%s')", + selectedIdentifier, rx)); + } + } + + /** + * Selects a crosstool toolchain corresponding to the given crosstool configuration options. If + * all of these options are null, it returns the default toolchain specified in the crosstool + * release. If only cpu is non-null, it returns the default toolchain for that cpu, as specified + * in the crosstool release. Otherwise, all values must be non-null, and this method returns the + * toolchain which matches all of the values. + * + * @throws NullPointerException if {@code release} is null + * @throws InvalidConfigurationException if no matching toolchain can be found, or if the input + * parameters do not obey the constraints described above + */ + public static CToolchain selectToolchainUsingCpuAndMaybeCompiler( + CrosstoolRelease release, + CrosstoolConfigurationIdentifier config, + Function cpuTransformer) + throws InvalidConfigurationException { + if (config.getCompiler() != null) { + ArrayList candidateToolchains = new ArrayList<>(); + for (CToolchain toolchain : release.getToolchainList()) { + if (config.isCandidateToolchain(toolchain)) { + candidateToolchains.add(toolchain); + } + } + switch (candidateToolchains.size()) { + case 0: + { + StringBuilder message = new StringBuilder(); + message.append("No toolchain found for"); + message.append(config.describeFlags()); + message.append(". Valid toolchains are: "); + describeToolchainList(message, release.getToolchainList()); + throw new InvalidConfigurationException(message.toString()); + } + case 1: + return candidateToolchains.get(0); + default: + { + StringBuilder message = new StringBuilder(); + message.append("Multiple toolchains found for"); + message.append(config.describeFlags()); + message.append(": "); + describeToolchainList(message, candidateToolchains); + throw new InvalidConfigurationException(message.toString()); + } + } + } + String selectedIdentifier = null; + // We use fake CPU values to allow cross-platform builds for other languages that use the + // C++ toolchain. Translate to the actual target architecture. + String desiredCpu = cpuTransformer.apply(config.getCpu()); + for (CrosstoolConfig.DefaultCpuToolchain selector : release.getDefaultToolchainList()) { + if (selector.getCpu().equals(desiredCpu)) { + selectedIdentifier = selector.getToolchainIdentifier(); + break; + } + } + + if (selectedIdentifier == null) { + HashSet seenCpus = new HashSet<>(); + StringBuilder cpuBuilder = new StringBuilder(); + for (CrosstoolConfig.DefaultCpuToolchain selector : release.getDefaultToolchainList()) { + if (seenCpus.add(selector.getCpu())) { + cpuBuilder.append(" ").append(selector.getCpu()).append(",\n"); + } + } + throw new InvalidConfigurationException( + "No default_toolchain found for cpu '" + + desiredCpu + + "'. Valid cpus are: [\n" + + cpuBuilder + + "]"); + } + checkToolchain(selectedIdentifier); + + for (CToolchain toolchain : release.getToolchainList()) { + if (toolchain.getToolchainIdentifier().equals(selectedIdentifier)) { + return toolchain; + } + } + + throw new InvalidConfigurationException( + "Inconsistent crosstool configuration; no toolchain " + + "corresponding to '" + + selectedIdentifier + + "' found for cpu '" + + config.getCpu() + + "'"); + } + + /** + * Appends a series of toolchain descriptions (as the blaze command line flags that would specify + * that toolchain) to 'message'. + */ + private static void describeToolchainList( + StringBuilder message, Collection toolchains) { + message.append("[\n"); + for (CrosstoolConfig.CToolchain toolchain : toolchains) { + message.append(" "); + message.append(toolchain.getToolchainIdentifier()); + message.append(": "); + message.append( + CrosstoolConfigurationIdentifier.fromToolchain(toolchain).describeFlags().trim()); + message.append(",\n"); + } + message.append("]"); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java index deb93bedcf5081..1ab84ded6611cf 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java @@ -30,7 +30,6 @@ import com.google.devtools.build.lib.analysis.LicensesProvider.TargetLicense; import com.google.devtools.build.lib.analysis.LicensesProviderImpl; import com.google.devtools.build.lib.analysis.MiddlemanProvider; -import com.google.devtools.build.lib.analysis.PlatformConfiguration; import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.analysis.RuleContext; @@ -689,11 +688,6 @@ private CppToolchainInfo getCppToolchainInfo( // Attempt to find a toolchain based on the target attributes, not the configuration. CToolchain toolchain = getToolchainFromAttributes(ruleContext, cppConfiguration); - if (toolchain == null) { - // Fall back to the toolchain info in the current configuration. - return cppConfiguration.getCppToolchainInfo(); - } - // If we found a toolchain, use it. try { toolchain = @@ -770,13 +764,6 @@ private static ImmutableMap getToolchainForSkylark( @Nullable private CToolchain getToolchainFromAttributes( RuleContext ruleContext, CppConfiguration cppConfiguration) throws RuleErrorException { - PlatformConfiguration platformConfig = - Preconditions.checkNotNull(ruleContext.getFragment(PlatformConfiguration.class)); - - if (!platformConfig.isToolchainTypeEnabled( - CppHelper.getToolchainTypeFromRuleClass(ruleContext))) { - return null; - } // Is there a toolchain proto available on the target directly? CToolchain toolchain = parseToolchainFromAttributes(ruleContext); @@ -784,27 +771,21 @@ private CToolchain getToolchainFromAttributes( return toolchain; } - // Use the attributes to find the proper toolchain from the CROSSTOOL. - if (ruleContext.attributes().get("cpu", Type.STRING).isEmpty()) { - ruleContext.throwWithRuleError("Using cc_toolchain target requires the attribute 'cpu' " - + "to be present"); - } - + String toolchainIdentifier = ruleContext.attributes().get("toolchain_identifier", Type.STRING); String cpu = ruleContext.attributes().get("cpu", Type.STRING); String compiler = ruleContext.attributes().get("compiler", Type.STRING); - if (compiler.isEmpty()) { - compiler = null; - } - CrosstoolConfigurationIdentifier config = new CrosstoolConfigurationIdentifier(cpu, compiler); - try { - return CrosstoolConfigurationLoader.selectToolchain( + return CToolchainSelectionUtils.selectCToolchain( + toolchainIdentifier, + cpu, + compiler, + cppConfiguration.getTransformedCpuFromOptions(), + cppConfiguration.getCompilerFromOptions(), cppConfiguration.getCrosstoolFile().getProto(), - config, cppConfiguration.getCpuTransformer()); } catch (InvalidConfigurationException e) { ruleContext.throwWithRuleError( - String.format("Error while using cc_toolchain: %s", e.getMessage())); + String.format("Error while selecting cc_toolchain: %s", e.getMessage())); return null; } } 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 3ce2c4574014cb..8b370d1b731c5b 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 @@ -20,6 +20,7 @@ import com.google.common.base.Verify; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.analysis.config.AutoCpuConverter; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.BuildConfiguration.Options.MakeVariableSource; import com.google.devtools.build.lib.analysis.config.BuildOptions; @@ -175,6 +176,8 @@ public String toString() { public static final String FDO_STAMP_MACRO = "BUILD_FDO_TYPE"; private final Label crosstoolTop; + private final String transformedCpuFromOptions; + private final String compilerFromOptions; private final CrosstoolFile crosstoolFile; // TODO(lberki): desiredCpu *should* be always the same as targetCpu, except that we don't check // that the CPU we get from the toolchain matches BuildConfiguration.Options.cpu . So we store @@ -263,6 +266,8 @@ static CppConfiguration create(CppConfigurationParameters params) return new CppConfiguration( params.crosstoolTop, + params.transformedCpu, + params.compiler, params.crosstoolFile, Preconditions.checkNotNull(params.commonOptions.cpu), crosstoolTopPathFragment, @@ -299,6 +304,8 @@ static CppConfiguration create(CppConfigurationParameters params) private CppConfiguration( Label crosstoolTop, + String transformedCpuFromOptions, + String compilerFromOptions, CrosstoolFile crosstoolFile, String desiredCpu, PathFragment crosstoolTopPathFragment, @@ -327,6 +334,8 @@ private CppConfiguration( boolean shouldProvideMakeVariables, CppToolchainInfo cppToolchainInfo) { this.crosstoolTop = crosstoolTop; + this.transformedCpuFromOptions = transformedCpuFromOptions; + this.compilerFromOptions = compilerFromOptions; this.crosstoolFile = crosstoolFile; this.desiredCpu = desiredCpu; this.crosstoolTopPathFragment = crosstoolTopPathFragment; @@ -898,6 +907,20 @@ public boolean startEndLibIsRequested() { return cppOptions.useStartEndLib; } + /** + * @return value from the --cpu option transformed using {@link CpuTransformer}. If it was not + * passed explicitly, {@link AutoCpuConverter} will try to guess something reasonable. + */ + public String getTransformedCpuFromOptions() { + return transformedCpuFromOptions; + } + + /** @return value from --compiler option, null if the option was not passed. */ + @Nullable + public String getCompilerFromOptions() { + return compilerFromOptions; + } + public boolean legacyWholeArchive() { return cppOptions.legacyWholeArchive; } 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 1a17c48719bb64..148a1808903f9f 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 @@ -91,9 +91,13 @@ public static class CppConfigurationParameters { protected final Label sysrootLabel; protected final CpuTransformer cpuTransformer; protected final CcToolchainConfigInfo ccToolchainConfigInfo; + protected final String transformedCpu; + protected final String compiler; CppConfigurationParameters( - CrosstoolConfigurationLoader.CrosstoolFile crosstoolFile, + String transformedCpu, + String compiler, + CrosstoolFile crosstoolFile, String cacheKeySuffix, BuildOptions buildOptions, PathFragment fdoPath, @@ -104,6 +108,8 @@ public static class CppConfigurationParameters { Label sysrootLabel, CpuTransformer cpuTransformer, CcToolchainConfigInfo ccToolchainConfigInfo) { + this.transformedCpu = transformedCpu; + this.compiler = compiler; this.crosstoolFile = crosstoolFile; this.cacheKeySuffix = cacheKeySuffix; this.commonOptions = buildOptions.get(BuildConfiguration.Options.class); @@ -169,19 +175,23 @@ protected CppConfigurationParameters createParameters( // 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 = + String identifierAttribute = NonconfigurableAttributeMapper.of((Rule) ccToolchain) .get("toolchain_identifier", Type.STRING); - CToolchain cToolchain; - if (!identifier.isEmpty()) { - cToolchain = - CrosstoolConfigurationLoader.getToolchainByIdentifier( - file.getProto(), identifier, transformedCpu, cppOptions.cppCompiler); - } else { - cToolchain = - CrosstoolConfigurationLoader.selectToolchain( - file.getProto(), options, cpuTransformer.getTransformer()); - } + String cpuAttribute = + NonconfigurableAttributeMapper.of((Rule) ccToolchain).get("cpu", Type.STRING); + String compilerAttribute = + NonconfigurableAttributeMapper.of((Rule) ccToolchain).get("compiler", Type.STRING); + + CToolchain cToolchain = + CToolchainSelectionUtils.selectCToolchain( + identifierAttribute, + cpuAttribute, + compilerAttribute, + transformedCpu, + cppOptions.cppCompiler, + file.getProto(), + cpuTransformer.getTransformer()); cToolchain = CppToolchainInfo.addLegacyFeatures( @@ -219,6 +229,8 @@ protected CppConfigurationParameters createParameters( } return new CppConfigurationParameters( + transformedCpu, + cppOptions.cppCompiler, file, file.getMd5(), options, 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 0ce2db0c233b63..296f2e715d1567 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,7 +18,6 @@ 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; @@ -44,9 +43,6 @@ import com.google.protobuf.UninitializedMessageException; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; import java.util.concurrent.ExecutionException; import javax.annotation.Nullable; @@ -294,182 +290,7 @@ public static CrosstoolConfig.CToolchain selectToolchain( throws InvalidConfigurationException { CrosstoolConfigurationIdentifier config = CrosstoolConfigurationIdentifier.fromOptions(options); - return selectToolchain(release, config, cpuTransformer); - } - - /** - * Selects a crosstool toolchain corresponding to the given crosstool configuration options. If - * all of these options are null, it returns the default toolchain specified in the crosstool - * release. If only cpu is non-null, it returns the default toolchain for that cpu, as specified - * in the crosstool release. Otherwise, all values must be non-null, and this method returns the - * toolchain which matches all of the values. - * - * @throws NullPointerException if {@code release} is null - * @throws InvalidConfigurationException if no matching toolchain can be found, or if the input - * parameters do not obey the constraints described above - */ - public static CrosstoolConfig.CToolchain selectToolchain( - CrosstoolConfig.CrosstoolRelease release, - CrosstoolConfigurationIdentifier config, - Function cpuTransformer) - throws InvalidConfigurationException { - if (config.getCompiler() != null) { - ArrayList candidateToolchains = new ArrayList<>(); - for (CrosstoolConfig.CToolchain toolchain : release.getToolchainList()) { - if (config.isCandidateToolchain(toolchain)) { - candidateToolchains.add(toolchain); - } - } - switch (candidateToolchains.size()) { - case 0: { - StringBuilder message = new StringBuilder(); - message.append("No toolchain found for"); - message.append(config.describeFlags()); - message.append(". Valid toolchains are: "); - describeToolchainList(message, release.getToolchainList()); - throw new InvalidConfigurationException(message.toString()); - } - case 1: - return candidateToolchains.get(0); - default: { - StringBuilder message = new StringBuilder(); - message.append("Multiple toolchains found for"); - message.append(config.describeFlags()); - message.append(": "); - describeToolchainList(message, candidateToolchains); - throw new InvalidConfigurationException(message.toString()); - } - } - } - String selectedIdentifier = null; - // We use fake CPU values to allow cross-platform builds for other languages that use the - // C++ toolchain. Translate to the actual target architecture. - String desiredCpu = cpuTransformer.apply(config.getCpu()); - for (CrosstoolConfig.DefaultCpuToolchain selector : release.getDefaultToolchainList()) { - if (selector.getCpu().equals(desiredCpu)) { - selectedIdentifier = selector.getToolchainIdentifier(); - break; - } - } - - if (selectedIdentifier == null) { - HashSet seenCpus = new HashSet<>(); - StringBuilder cpuBuilder = new StringBuilder(); - for (CrosstoolConfig.DefaultCpuToolchain selector : release.getDefaultToolchainList()) { - if (seenCpus.add(selector.getCpu())) { - cpuBuilder.append(" ").append(selector.getCpu()).append(",\n"); - } - } - throw new InvalidConfigurationException( - "No default_toolchain found for cpu '" - + desiredCpu - + "'. Valid cpus are: [\n" - + cpuBuilder - + "]"); - } - checkToolchain(selectedIdentifier, desiredCpu); - - for (CrosstoolConfig.CToolchain toolchain : release.getToolchainList()) { - if (toolchain.getToolchainIdentifier().equals(selectedIdentifier)) { - return toolchain; - } - } - - throw new InvalidConfigurationException("Inconsistent crosstool configuration; no toolchain " - + "corresponding to '" + selectedIdentifier + "' found for cpu '" + config.getCpu() + "'"); - } - - /** - * Appends a series of toolchain descriptions (as the blaze command line flags - * that would specify that toolchain) to 'message'. - */ - private static void describeToolchainList(StringBuilder message, - Collection toolchains) { - message.append("[\n"); - for (CrosstoolConfig.CToolchain toolchain : toolchains) { - message.append(" "); - message.append(toolchain.getToolchainIdentifier()); - message.append(": "); - message.append( - CrosstoolConfigurationIdentifier.fromToolchain(toolchain).describeFlags().trim()); - message.append(",\n"); - } - message.append("]"); - } - - /** - * 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. - */ - 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. - String rx = "[a-zA-Z_][\\.\\- \\w]*"; - if (!selectedIdentifier.matches(rx)) { - throw new InvalidConfigurationException(String.format( - "Toolchain identifier '%s' for cpu '%s' is illegal (does not match '%s')", - selectedIdentifier, cpu, rx)); - } - } - - protected static CrosstoolConfig.CrosstoolRelease getCrosstoolReleaseProto( - ConfigurationEnvironment env, - BuildOptions options, - Label crosstoolTop, - Function cpuTransformer) - throws InvalidConfigurationException, InterruptedException { - CrosstoolConfigurationLoader.CrosstoolFile file = - readCrosstool(env, crosstoolTop); - // Make sure that we have the requested toolchain in the result. Throw an exception if not. - 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; + return CToolchainSelectionUtils.selectToolchainUsingCpuAndMaybeCompiler( + release, config, cpuTransformer); } } diff --git a/src/main/java/com/google/devtools/build/lib/util/StringUtil.java b/src/main/java/com/google/devtools/build/lib/util/StringUtil.java index e7ea821d595284..bf4e6528952960 100644 --- a/src/main/java/com/google/devtools/build/lib/util/StringUtil.java +++ b/src/main/java/com/google/devtools/build/lib/util/StringUtil.java @@ -18,6 +18,7 @@ import com.google.common.collect.Iterables; import java.util.Collection; import java.util.Iterator; +import javax.annotation.Nullable; /** * Various utility methods operating on strings. @@ -134,4 +135,13 @@ public static String capitalize(String input) { char capitalized = Character.toUpperCase(first); return first == capitalized ? input : capitalized + input.substring(1); } + + /** Convert empty string to null. */ + @Nullable + public static String emptyToNull(@Nullable String input) { + if (input == null || input.isEmpty()) { + return null; + } + return input; + } } diff --git a/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationTest.java b/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationTest.java index 3b280c5b253e96..08ac83197f0bf1 100644 --- a/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationTest.java +++ b/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationTest.java @@ -108,11 +108,14 @@ public void testHostCrosstoolTop() throws Exception { BuildConfigurationCollection configs = createCollection("--cpu=piii"); BuildConfiguration config = Iterables.getOnlyElement(configs.getTargetConfigurations()); assertThat(config.getFragment(CppConfiguration.class).getCcToolchainRuleLabel()) - .isEqualTo(Label.parseAbsoluteUnchecked("//third_party/crosstool/mock:cc-compiler-piii")); + .isEqualTo( + Label.parseAbsoluteUnchecked( + "//third_party/crosstool/mock:cc-compiler-piii-gcc-4.4.0")); BuildConfiguration hostConfig = configs.getHostConfiguration(); assertThat(hostConfig.getFragment(CppConfiguration.class).getCcToolchainRuleLabel()) - .isEqualTo(Label.parseAbsoluteUnchecked("//third_party/crosstool/mock:cc-compiler-k8")); + .isEqualTo( + Label.parseAbsoluteUnchecked("//third_party/crosstool/mock:cc-compiler-k8-gcc-4.4.0")); } @Test diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/BazelMockCcSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/BazelMockCcSupport.java index a2b5a882d15507..74ff6656e31f07 100644 --- a/src/test/java/com/google/devtools/build/lib/packages/util/BazelMockCcSupport.java +++ b/src/test/java/com/google/devtools/build/lib/packages/util/BazelMockCcSupport.java @@ -86,7 +86,7 @@ public void setup(MockToolsConfig config) throws IOException { " 'local|compiler': ':cc-compiler-local',", " 'k8|compiler': ':cc-compiler-k8',", " 'k8|compiler_no_dyn_linker': ':cc-no-dyn-linker-k8',", - " 'piii|compiler': ':cc-compiler-piii',", + " 'piii|compiler': ':cc-compiler-piii-gcc-4.4.0',", " 'darwin|compiler': ':cc-compiler-darwin',", " 'darwin|compiler_no_dyn_linker': ':cc-no-dyn-linker-darwin',", " 'ios_x86_64|compiler': ':cc-compiler-ios_x86_64',", @@ -96,7 +96,9 @@ public void setup(MockToolsConfig config) throws IOException { " 'ppc|compiler': ':cc-compiler-ppc',", " })", "cc_toolchain(name = 'cc-compiler-k8', all_files = ':empty', compiler_files = ':empty',", - " cpu = 'k8', compiler = 'compiler', dwp_files = ':empty',", + " cpu = 'k8',", + " compiler = 'compiler',", + " dwp_files = ':empty',", " dynamic_runtime_libs = [':empty'], ", " ar_files = ':empty', as_files = ':empty', linker_files = ':empty',", " module_map = 'crosstool.cppmap', supports_header_parsing = 1,", @@ -130,7 +132,9 @@ public void setup(MockToolsConfig config) throws IOException { " toolchain_type = ':toolchain_type',", ")", "cc_toolchain(name = 'cc-compiler-ppc', all_files = ':empty', compiler_files = ':empty',", - " cpu = 'ppc', compiler = 'compiler', dwp_files = ':empty',", + " cpu = 'ppc',", + " compiler = 'compiler',", + " dwp_files = ':empty',", " dynamic_runtime_libs = [':empty'], ", " ar_files = ':empty', as_files = ':empty', linker_files = ':empty',", " module_map = 'crosstool.cppmap', supports_header_parsing = 1,", @@ -146,9 +150,12 @@ public void setup(MockToolsConfig config) throws IOException { " toolchain = ':cc-compiler-ppc',", " toolchain_type = ':toolchain_type',", ")", - "cc_toolchain(name = 'cc-compiler-piii', all_files = ':all-files-piii',", + "cc_toolchain(name = 'cc-compiler-piii-gcc-4.4.0',", + " all_files = ':all-files-piii',", " compiler_files = ':compiler-files-piii',", - " cpu = 'piii', compiler = 'compiler', dwp_files = ':empty',", + " cpu = 'piii',", + " compiler = 'compiler',", + " dwp_files = ':empty',", " dynamic_runtime_libs = [':empty'], ", " ar_files = ':empty', as_files = ':empty', linker_files = ':empty',", " module_map = 'crosstool.cppmap', supports_header_parsing = 1,", @@ -161,12 +168,14 @@ public void setup(MockToolsConfig config) throws IOException { " '@bazel_tools//platforms:x86_32',", " '@bazel_tools//platforms:linux',", " ],", - " toolchain = ':cc-compiler-piii',", + " toolchain = ':cc-compiler-piii-gcc-4.4.0',", " toolchain_type = ':toolchain_type',", ")", "cc_toolchain(name = 'cc-compiler-darwin', all_files = ':empty', ", " compiler_files = ':empty',", - " cpu = 'darwin', compiler = 'compiler', dwp_files = ':empty',", + " cpu = 'darwin',", + " compiler = 'compiler',", + " dwp_files = ':empty',", " dynamic_runtime_libs = [':empty'], ", " ar_files = ':empty', as_files = ':empty', linker_files = ':empty',", " module_map = 'crosstool.cppmap', supports_header_parsing = 1,", @@ -184,7 +193,8 @@ public void setup(MockToolsConfig config) throws IOException { ")", "cc_toolchain(name = 'cc-no-dyn-linker-darwin', all_files = ':empty', ", " compiler_files = ':empty',", - " cpu = 'darwin', compiler = 'compiler_no_dyn_linker', ", + " cpu = 'darwin',", + " compiler = 'compiler_no_dyn_linker',", " dwp_files = ':empty', dynamic_runtime_libs = [':empty'], ", " ar_files = ':empty', as_files = ':empty', linker_files = ':empty',", " module_map = 'crosstool.cppmap', supports_header_parsing = 1,", @@ -202,7 +212,9 @@ public void setup(MockToolsConfig config) throws IOException { ")", "cc_toolchain(name = 'cc-compiler-ios_x86_64', all_files = ':empty', ", " compiler_files = ':empty',", - " cpu = 'ios_x86_64', compiler = 'compiler', dwp_files = ':empty',", + " cpu = 'ios_x86_64',", + " compiler = 'compiler',", + " dwp_files = ':empty',", " dynamic_runtime_libs = [':empty'], ", " ar_files = ':empty', as_files = ':empty', linker_files = ':empty',", " module_map = 'crosstool.cppmap', supports_header_parsing = 1,", @@ -220,7 +232,8 @@ public void setup(MockToolsConfig config) throws IOException { ")", "cc_toolchain(name = 'cc-compiler-armeabi-v7a', all_files = ':empty', ", " compiler_files = ':empty',", - " cpu = 'armeabi-v7a', compiler = 'compiler',", + " cpu = 'armeabi-v7a',", + " compiler = 'compiler',", " dwp_files = ':empty',", " dynamic_runtime_libs = [':empty'], ", " ar_files = ':empty', as_files = ':empty', linker_files = ':empty',", @@ -239,7 +252,8 @@ public void setup(MockToolsConfig config) throws IOException { ")", "cc_toolchain(name = 'cc-compiler-x64_windows', all_files = ':empty', ", " compiler_files = ':empty',", - " cpu = 'x64_windows', compiler = 'windows_msys64',", + " cpu = 'x64_windows',", + " compiler = 'windows_msys64',", " dwp_files = ':empty',", " dynamic_runtime_libs = [':empty'], ", " ar_files = ':empty', as_files = ':empty', linker_files = ':empty',", @@ -258,7 +272,8 @@ public void setup(MockToolsConfig config) throws IOException { ")", "cc_toolchain(name = 'cc-no-dyn-linker-x64_windows', all_files = ':empty', ", " compiler_files = ':empty',", - " cpu = 'x64_windows', compiler = 'compiler_no_dyn_linker',", + " cpu = 'x64_windows',", + " compiler = 'compiler_no_dyn_linker',", " dwp_files = ':empty',", " dynamic_runtime_libs = [':empty'], ", " ar_files = ':empty', as_files = ':empty', linker_files = ':empty',", 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 cb2740bcdeec14..43f31a3abab402 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 @@ -15,6 +15,7 @@ import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; +import com.google.devtools.build.lib.util.Pair; import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig; import com.google.protobuf.TextFormat; import java.io.IOException; @@ -114,17 +115,20 @@ public void write() throws IOException { TextFormat.merge(crosstoolFileContents, configBuilder); StringBuilder compilerMap = new StringBuilder(); // Remove duplicates - Set keys = new LinkedHashSet<>(); + Set> keys = new LinkedHashSet<>(); for (CrosstoolConfig.CToolchain toolchain : configBuilder.build().getToolchainList()) { - String key = String.format("%s|%s", toolchain.getTargetCpu(), toolchain.getCompiler()); + Pair key = Pair.of(toolchain.getTargetCpu(), toolchain.getCompiler()); if (!keys.contains(key)) { keys.add(key); compilerMap.append( - String.format("'%s': ':cc-compiler-%s',\n", key, toolchain.getTargetCpu())); + String.format( + "'%s|%s': ':cc-compiler-%s-%s',\n", key.first, key.second, key.first, key.second)); } } - for (String arch : archs) { + for (Pair key : keys) { + String cpu = key.first; + String compiler = key.second; String compilerRule; String staticRuntimesString = staticRuntimesLabel == null ? "" : ", '" + staticRuntimesLabel + "'"; @@ -135,28 +139,28 @@ public void write() throws IOException { Joiner.on("\n") .join( "cc_toolchain(", - " name = 'cc-compiler-" + arch + "',", + " name = 'cc-compiler-" + cpu + "-" + compiler + "',", " output_licenses = ['unencumbered'],", addModuleMap ? " module_map = 'crosstool.cppmap'," : "", - " cpu = '" + arch + "',", - " compiler = 'gcc-4.4.0',", - " ar_files = 'ar-" + arch + "',", - " as_files = 'as-" + arch + "',", - " compiler_files = 'compile-" + arch + "',", - " dwp_files = 'dwp-" + arch + "',", - " linker_files = 'link-" + arch + "',", + " cpu = '" + cpu + "',", + " compiler = '" + compiler + "',", + " ar_files = 'ar-" + cpu + "',", + " as_files = 'as-" + cpu + "',", + " compiler_files = 'compile-" + cpu + "',", + " dwp_files = 'dwp-" + cpu + "',", + " linker_files = 'link-" + cpu + "',", " strip_files = ':every-file',", - " objcopy_files = 'objcopy-" + arch + "',", + " objcopy_files = 'objcopy-" + cpu + "',", " all_files = ':every-file',", " licenses = ['unencumbered'],", supportsHeaderParsing ? " supports_header_parsing = 1," : "", " dynamic_runtime_libs = ['dynamic-runtime-libs-" - + arch + + cpu + "'" + dynamicRuntimesString + "],", " static_runtime_libs = ['static-runtime-libs-" - + arch + + cpu + "'" + staticRuntimesString + "])"); diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockPlatformSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockPlatformSupport.java index 9fce2b6bf16419..2a9b7f95dd3815 100644 --- a/src/test/java/com/google/devtools/build/lib/packages/util/MockPlatformSupport.java +++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockPlatformSupport.java @@ -113,7 +113,8 @@ public static void addMockPiiiPlatform(MockToolsConfig mockToolsConfig, Label cr " name = 'toolchain_cc-compiler-piii',", " toolchain_type = '" + TestConstants.TOOLS_REPOSITORY + "//tools/cpp:toolchain_type',", " toolchain = '" - + crosstoolLabel.getRelativeWithRemapping("cc-compiler-piii", ImmutableMap.of()) + + crosstoolLabel.getRelativeWithRemapping( + "cc-compiler-piii-gcc-4.4.0", ImmutableMap.of()) + "',", " target_compatible_with = [':mock_value'],", ")"); diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSelectionTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSelectionTest.java index 75071f359b8934..1e6a4c6a386df6 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSelectionTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSelectionTest.java @@ -58,6 +58,7 @@ private CppCompileAction getCppCompileAction(String label) throws Exception { @Test public void testResolvedCcToolchain() throws Exception { useConfiguration( + "--enabled_toolchain_types=" + CPP_TOOLCHAIN_TYPE, "--experimental_platforms=//mock_platform:mock-piii-platform", "--extra_toolchains=//mock_platform:toolchain_cc-compiler-piii"); ConfiguredTarget target = @@ -82,6 +83,7 @@ public void testToolchainSelectionWithPlatforms() throws Exception { ScratchAttributeWriter.fromLabelString(this, "cc_library", "//lib") .setList("srcs", "a.cc") .write(); + assertNoEvents(); CppCompileAction compileAction = getCppCompileAction("//lib"); boolean isPiii = ImmutableList.copyOf(compileAction.getInputs()) 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 16537a1247b8fe..eed04b1dce83cc 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 @@ -413,7 +413,7 @@ public void testCcToolchainFromToolchainIdentifier() throws Exception { ") for NAME in TOOLCHAIN_NAMES]", "[cc_toolchain(", " name = NAME + '-override',", - " cpu = 'banana',", + " cpu = NAME,", " all_files = ':empty',", " ar_files = ':empty',", " as_files = ':empty',", @@ -458,7 +458,7 @@ public void testCcToolchainFromToolchainIdentifier() throws Exception { ")", "cc_toolchain(", " name = 'wrong-compiler',", - " cpu = 'banana',", + " cpu = 'k8',", " all_files = ':empty',", " ar_files = ':empty',", " as_files = ':empty',", @@ -686,19 +686,6 @@ public void testCcToolchainFromToolchainIdentifier() throws Exception { .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"); - } } @Test diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java index ffa4fc89a548bf..843fc93cd75289 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java @@ -688,53 +688,6 @@ public void testZipperInclusionDependsOnFdoOptimization() throws Exception { assertThat(getPrerequisites(getConfiguredTarget("//a:b"), ":zipper")).isNotEmpty(); } - @Test - public void testInlineCtoolchain_withoutToolchainResolution() throws Exception { - scratch.file( - "a/BUILD", - "filegroup(", - " name='empty')", - "cc_toolchain(", - " name = 'b',", - " 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'],", - " proto=\"\"\"", - " toolchain_identifier: \"banana\"", - " abi_version: \"banana\"", - " abi_libc_version: \"banana\"", - " compiler: \"banana\"", - " host_system_name: \"banana\"", - " target_system_name: \"banana\"", - " target_cpu: \"banana\"", - " target_libc: \"banana\"", - " \"\"\")"); - - getAnalysisMock() - .ccSupport() - .setupCrosstool(mockToolsConfig, CrosstoolConfig.CToolchain.newBuilder() - .setAbiVersion("orange") - .buildPartial()); - - useConfiguration(); - - ConfiguredTarget target = getConfiguredTarget("//a:b"); - CcToolchainProvider toolchainProvider = - (CcToolchainProvider) target.get(ToolchainInfo.PROVIDER); - - // Without toolchain resolution, this should get the toolchain from the CROSSTOOL, not the - // static version in the target. - assertThat(toolchainProvider.getAbi()).isEqualTo("orange"); - } - @Test public void testInlineCtoolchain_withToolchainResolution() throws Exception { scratch.file( diff --git a/src/test/java/com/google/devtools/build/lib/util/StringUtilTest.java b/src/test/java/com/google/devtools/build/lib/util/StringUtilTest.java index 14ae602a35aa66..f04c62323b817a 100644 --- a/src/test/java/com/google/devtools/build/lib/util/StringUtilTest.java +++ b/src/test/java/com/google/devtools/build/lib/util/StringUtilTest.java @@ -15,6 +15,7 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.devtools.build.lib.util.StringUtil.capitalize; +import static com.google.devtools.build.lib.util.StringUtil.emptyToNull; import static com.google.devtools.build.lib.util.StringUtil.indent; import static com.google.devtools.build.lib.util.StringUtil.joinEnglishList; import static com.google.devtools.build.lib.util.StringUtil.stripSuffix; @@ -89,4 +90,12 @@ public void testCapitalize() throws Exception { assertThat(capitalize("o")).isEqualTo("O"); assertThat(capitalize("O")).isEqualTo("O"); } + + @Test + public void testEmptyToNull() { + assertThat(emptyToNull(null)).isNull(); + assertThat(emptyToNull("")).isNull(); + assertThat(emptyToNull("a")).isEqualTo("a"); + assertThat(emptyToNull(" ")).isEqualTo(" "); + } } diff --git a/tools/cpp/CROSSTOOL.tpl b/tools/cpp/CROSSTOOL.tpl index 20042820e5ec17..defd87f8ae5244 100644 --- a/tools/cpp/CROSSTOOL.tpl +++ b/tools/cpp/CROSSTOOL.tpl @@ -21,11 +21,6 @@ default_toolchain { toolchain_identifier: "%{default_toolchain_name}" } -default_toolchain { - cpu: "local" - toolchain_identifier: "stub_armeabi-v7a" -} - default_toolchain { cpu: "armeabi-v7a" toolchain_identifier: "stub_armeabi-v7a"